├── .editorconfig
├── .gitattributes
├── .github
└── workflows
│ ├── cd.yml
│ └── ci.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Directory.Build.props
├── LICENSE
├── MyWPFApp.Package
├── Images
│ ├── BadgeLogo.scale-100.png
│ ├── BadgeLogo.scale-125.png
│ ├── BadgeLogo.scale-150.png
│ ├── BadgeLogo.scale-200.png
│ ├── BadgeLogo.scale-400.png
│ ├── LargeTile.scale-100.png
│ ├── LargeTile.scale-125.png
│ ├── LargeTile.scale-150.png
│ ├── LargeTile.scale-200.png
│ ├── LargeTile.scale-400.png
│ ├── SmallTile.scale-100.png
│ ├── SmallTile.scale-125.png
│ ├── SmallTile.scale-150.png
│ ├── SmallTile.scale-200.png
│ ├── SmallTile.scale-400.png
│ ├── SplashScreen.scale-100.png
│ ├── SplashScreen.scale-125.png
│ ├── SplashScreen.scale-150.png
│ ├── SplashScreen.scale-200.png
│ ├── SplashScreen.scale-400.png
│ ├── Square150x150Logo.png
│ ├── Square150x150Logo.scale-100.png
│ ├── Square150x150Logo.scale-125.png
│ ├── Square150x150Logo.scale-150.png
│ ├── Square150x150Logo.scale-200.png
│ ├── Square150x150Logo.scale-400.png
│ ├── Square44x44Logo.altform-unplated_targetsize-16.png
│ ├── Square44x44Logo.altform-unplated_targetsize-24.png
│ ├── Square44x44Logo.altform-unplated_targetsize-256.png
│ ├── Square44x44Logo.altform-unplated_targetsize-32.png
│ ├── Square44x44Logo.altform-unplated_targetsize-48.png
│ ├── Square44x44Logo.scale-100.png
│ ├── Square44x44Logo.scale-125.png
│ ├── Square44x44Logo.scale-150.png
│ ├── Square44x44Logo.scale-200.png
│ ├── Square44x44Logo.scale-400.png
│ ├── Square44x44Logo.targetsize-16.png
│ ├── Square44x44Logo.targetsize-24.png
│ ├── Square44x44Logo.targetsize-256.png
│ ├── Square44x44Logo.targetsize-32.png
│ ├── Square44x44Logo.targetsize-48.png
│ ├── StoreLogo.backup.png
│ ├── StoreLogo.scale-100.png
│ ├── StoreLogo.scale-125.png
│ ├── StoreLogo.scale-150.png
│ ├── StoreLogo.scale-200.png
│ ├── StoreLogo.scale-400.png
│ ├── WideTile.scale-100.png
│ ├── WideTile.scale-125.png
│ ├── WideTile.scale-150.png
│ ├── WideTile.scale-200.png
│ └── WideTile.scale-400.png
├── MyWPFApp.Package.wapproj
├── Package.appinstaller
└── Package.appxmanifest
├── MyWPFApp.sln
├── MyWPFApp
├── App.xaml
├── App.xaml.cs
├── ApplicationInsights.config
├── MainWindow.xaml
├── MainWindow.xaml.cs
├── MyWPFApp.csproj
├── Properties
│ └── PublishProfiles
│ │ ├── SelfContainedWin64.pubxml
│ │ ├── SelfContainedWin64Debug.pubxml
│ │ ├── SelfContainedWin86.pubxml
│ │ └── SelfContainedWin86Debug.pubxml
├── Telemetry
│ ├── AppVersionTelemetryInitializer.cs
│ ├── DiagnosticsClient.cs
│ └── EnvironmentTelemetryInitializer.cs
├── ThisAppInfo.cs
└── win.ico
├── MyWpfApp.Tests
├── MyWPFApp.Tests.csproj
└── ThisAppInfoTest.cs
├── README.md
├── SECURITY.md
├── doc
└── images
│ ├── editToCustomizeSettings.png
│ ├── findArtifact.png
│ ├── myWpfApp.Package.Properties.png
│ ├── pickAPublishTarget.png
│ ├── profileSettings.png
│ ├── publishProfileComplete.png
│ ├── releaseAssetLocation.png
│ ├── releases.png
│ ├── renameProfile.png
│ └── versionEnvironmentVariables.png
└── version.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome:http://EditorConfig.org
2 | # From https://raw.githubusercontent.com/dotnet/roslyn/master/.editorconfig
3 |
4 | # top-most EditorConfig file
5 | root = true
6 |
7 | # Don't use tabs for indentation.
8 | [*]
9 | indent_style = space
10 | trim_trailing_whitespace = true
11 | # (Please don't specify an indent_size here; that has too many unintended consequences.)
12 |
13 | # Code files
14 | [*.{cs,csx,vb,vbx}]
15 | indent_size = 4
16 | insert_final_newline = true
17 | charset = utf-8-bom
18 |
19 | # Xml project files
20 | [*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj}]
21 | indent_size = 2
22 |
23 | # Xml config files
24 | [*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}]
25 | indent_size = 2
26 |
27 | # Yml/Yaml files
28 | [*.{yaml,yml}]
29 | indent_size = 2
30 |
31 | # Powershell files
32 | [*.ps1]
33 | indent_size = 2
34 |
35 | # JSON files
36 | [*.json]
37 | indent_size = 2
38 |
39 | # Shell scripts
40 | [*.sh]
41 | end_of_line = lf
42 |
43 | [*.{cmd,bat}]
44 | end_of_line = crlf
45 |
46 | # Dotnet code style settings:
47 | [*.{cs,vb}]
48 | # Sort using and Import directives with System.* appearing first
49 | dotnet_sort_system_directives_first = true
50 | # Put a blank line between System.* and Microsoft.*
51 | dotnet_separate_import_directive_groups = true
52 |
53 | # Avoid "this." and "Me." if not necessary
54 | dotnet_style_qualification_for_field = false:suggestion
55 | dotnet_style_qualification_for_property = false:suggestion
56 | dotnet_style_qualification_for_method = false:suggestion
57 | dotnet_style_qualification_for_event = false:suggestion
58 |
59 | # Use language keywords instead of framework type names for type references
60 | dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
61 | dotnet_style_predefined_type_for_member_access = true:suggestion
62 |
63 | # Prefer read-only on fields
64 | dotnet_style_readonly_field = true:warning
65 |
66 | # Suggest more modern language features when available
67 | dotnet_style_object_initializer = true:suggestion
68 | dotnet_style_collection_initializer = true:suggestion
69 | dotnet_style_coalesce_expression = true:suggestion
70 | dotnet_style_null_propagation = true:suggestion
71 | dotnet_style_explicit_tuple_names = true:suggestion
72 | dotnet_style_prefer_inferred_tuple_names = true:suggestion
73 | dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
74 | dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
75 | dotnet_style_prefer_conditional_expression_over_return = false
76 | dotnet_style_prefer_conditional_expression_over_assignment = false
77 | dotnet_style_prefer_auto_properties = true:suggestion
78 |
79 | # Parentheses
80 | dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
81 | dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
82 | dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
83 | dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
84 |
85 | # Accessibility modifiers
86 | dotnet_style_require_accessibility_modifiers = always:suggestion
87 |
88 |
89 | # Naming Rules
90 |
91 | # Interfaces start with an I and are PascalCased
92 | dotnet_naming_rule.interfaces_must_be_pascal_cased_and_prefixed_with_I.symbols = interface_symbols
93 | dotnet_naming_rule.interfaces_must_be_pascal_cased_and_prefixed_with_I.style = pascal_case_and_prefix_with_I_style
94 | dotnet_naming_rule.interfaces_must_be_pascal_cased_and_prefixed_with_I.severity = warning
95 |
96 | # External members are PascalCased
97 | dotnet_naming_rule.externally_visible_members_must_be_pascal_cased.symbols = externally_visible_symbols
98 | dotnet_naming_rule.externally_visible_members_must_be_pascal_cased.style = pascal_case_style
99 | dotnet_naming_rule.externally_visible_members_must_be_pascal_cased.severity = warning
100 |
101 | # Parameters are camelCased
102 | dotnet_naming_rule.parameters_must_be_camel_cased.symbols = parameter_symbols
103 | dotnet_naming_rule.parameters_must_be_camel_cased.style = camel_case_style
104 | dotnet_naming_rule.parameters_must_be_camel_cased.severity = warning
105 |
106 | # Constants are PascalCased
107 | dotnet_naming_rule.constants_must_be_pascal_cased.symbols = constant_symbols
108 | dotnet_naming_rule.constants_must_be_pascal_cased.style = pascal_case_style
109 | dotnet_naming_rule.constants_must_be_pascal_cased.severity = warning
110 |
111 | # Uncomment this group and comment out the next group if you prefer s_ prefixes for static fields
112 |
113 | # Private static fields are prefixed with s_ and are camelCased like s_myStatic
114 | #dotnet_naming_rule.private_static_fields_must_be_camel_cased_and_prefixed_with_s_underscore.symbols = private_static_field_symbols
115 | #dotnet_naming_rule.private_static_fields_must_be_camel_cased_and_prefixed_with_s_underscore.style = camel_case_and_prefix_with_s_underscore_style
116 | #dotnet_naming_rule.private_static_fields_must_be_camel_cased_and_prefixed_with_s_underscore.severity = warning
117 |
118 | # Static readonly fields are PascalCased
119 | dotnet_naming_rule.static_readonly_fields_should_be_pascal_case.symbols = private_static_readonly_field_symbols
120 | dotnet_naming_rule.static_readonly_fields_should_be_pascal_case.style = pascal_case_style
121 | dotnet_naming_rule.static_readonly_fields_should_be_pascal_case.severity = warning
122 |
123 | # Comment this group and uncomment out the next group if you don't want _ prefixed fields.
124 |
125 | # Private instance fields are camelCased with an _ like _myField
126 | dotnet_naming_rule.private_instance_fields_must_be_camel_cased_and_prefixed_with_underscore.symbols = private_field_symbols
127 | dotnet_naming_rule.private_instance_fields_must_be_camel_cased_and_prefixed_with_underscore.style = camel_case_and_prefix_with_underscore_style
128 | dotnet_naming_rule.private_instance_fields_must_be_camel_cased_and_prefixed_with_underscore.severity = warning
129 |
130 | # Private instance fields are camelCased
131 | #dotnet_naming_rule.private_instance_fields_must_be_camel_cased.symbols = private_field_symbols
132 | #dotnet_naming_rule.private_instance_fields_must_be_camel_cased.style = camel_case_style
133 | #dotnet_naming_rule.private_instance_fields_must_be_camel_cased.severity = warning
134 |
135 | # Symbols
136 | dotnet_naming_symbols.externally_visible_symbols.applicable_kinds = class,struct,interface,enum,property,method,field,event,delegate
137 | dotnet_naming_symbols.externally_visible_symbols.applicable_accessibilities = public,internal,friend,protected,protected_internal,protected_friend,private_protected
138 |
139 | dotnet_naming_symbols.interface_symbols.applicable_kinds = interface
140 | dotnet_naming_symbols.interface_symbols.applicable_accessibilities = *
141 |
142 | dotnet_naming_symbols.parameter_symbols.applicable_kinds = parameter
143 | dotnet_naming_symbols.parameter_symbols.applicable_accessibilities = *
144 |
145 | dotnet_naming_symbols.constant_symbols.applicable_kinds = field
146 | dotnet_naming_symbols.constant_symbols.required_modifiers = const
147 | dotnet_naming_symbols.constant_symbols.applicable_accessibilities = *
148 |
149 | dotnet_naming_symbols.private_static_field_symbols.applicable_kinds = field
150 | dotnet_naming_symbols.private_static_field_symbols.required_modifiers = static,shared
151 | dotnet_naming_symbols.private_static_field_symbols.applicable_accessibilities = private
152 |
153 | dotnet_naming_symbols.private_static_readonly_field_symbols.applicable_kinds = field
154 | dotnet_naming_symbols.private_static_readonly_field_symbols.required_modifiers = static,shared,readonly
155 | dotnet_naming_symbols.private_static_readonly_field_symbols.applicable_accessibilities = private
156 |
157 | dotnet_naming_symbols.private_field_symbols.applicable_kinds = field
158 | dotnet_naming_symbols.private_field_symbols.applicable_accessibilities = private
159 |
160 | # Styles
161 | dotnet_naming_style.camel_case_style.capitalization = camel_case
162 |
163 | dotnet_naming_style.pascal_case_style.capitalization = pascal_case
164 |
165 | dotnet_naming_style.camel_case_and_prefix_with_s_underscore_style.required_prefix = s_
166 | dotnet_naming_style.camel_case_and_prefix_with_s_underscore_style.capitalization = camel_case
167 |
168 | dotnet_naming_style.camel_case_and_prefix_with_underscore_style.required_prefix = _
169 | dotnet_naming_style.camel_case_and_prefix_with_underscore_style.capitalization = camel_case
170 |
171 | dotnet_naming_style.pascal_case_and_prefix_with_I_style.required_prefix = I
172 | dotnet_naming_style.pascal_case_and_prefix_with_I_style.capitalization = pascal_case
173 |
174 |
175 | # CSharp code style settings:
176 | [*.cs]
177 | # Modifier order
178 | csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion
179 |
180 | # Code block
181 | csharp_prefer_braces = false:none
182 |
183 | # Indentation preferences
184 | csharp_indent_block_contents = true
185 | csharp_indent_braces = false
186 | csharp_indent_case_contents = true
187 | csharp_indent_switch_labels = true
188 | csharp_indent_labels = flush_left
189 |
190 | # Prefer "var" everywhere
191 | csharp_style_var_for_built_in_types = true:suggestion
192 | csharp_style_var_when_type_is_apparent = true:suggestion
193 | csharp_style_var_elsewhere = true:suggestion
194 |
195 | # Code style defaults
196 | csharp_preserve_single_line_blocks = true
197 | csharp_preserve_single_line_statements = true
198 |
199 | # Prefer method-like constructs to have a block body
200 | csharp_style_expression_bodied_methods = false:none
201 | csharp_style_expression_bodied_constructors = false:none
202 | csharp_style_expression_bodied_operators = false:none
203 |
204 | # Prefer property-like constructs to have an expression-body
205 | csharp_style_expression_bodied_properties = true:none
206 | csharp_style_expression_bodied_indexers = true:none
207 | csharp_style_expression_bodied_accessors = true:none
208 |
209 | # Expression
210 | csharp_prefer_simple_default_expression = true:suggestion
211 | csharp_style_deconstructed_variable_declaration = true:suggestion
212 | csharp_style_pattern_local_over_anonymous_function = true:suggestion
213 |
214 | # Pattern matching
215 | csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
216 | csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
217 | csharp_style_inlined_variable_declaration = true:suggestion
218 |
219 | # Null checking preferences
220 | csharp_style_throw_expression = true:suggestion
221 | csharp_style_conditional_delegate_call = true:suggestion
222 |
223 | # Newline settings
224 | csharp_new_line_before_open_brace = all
225 | csharp_new_line_before_else = true
226 | csharp_new_line_before_catch = true
227 | csharp_new_line_before_finally = true
228 | csharp_new_line_before_members_in_object_initializers = true
229 | csharp_new_line_before_members_in_anonymous_types = true
230 | csharp_new_line_between_query_expression_clauses = true
231 |
232 | # Space preferences
233 | csharp_space_after_cast = false
234 | csharp_space_after_colon_in_inheritance_clause = true
235 | csharp_space_after_comma = true
236 | csharp_space_after_dot = false
237 | csharp_space_after_keywords_in_control_flow_statements = true
238 | csharp_space_after_semicolon_in_for_statement = true
239 | csharp_space_around_binary_operators = before_and_after
240 | csharp_space_around_declaration_statements = do_not_ignore
241 | csharp_space_before_colon_in_inheritance_clause = true
242 | csharp_space_before_comma = false
243 | csharp_space_before_dot = false
244 | csharp_space_before_open_square_brackets = false
245 | csharp_space_before_semicolon_in_for_statement = false
246 | csharp_space_between_empty_square_brackets = false
247 | csharp_space_between_method_call_empty_parameter_list_parentheses = false
248 | csharp_space_between_method_call_name_and_opening_parenthesis = false
249 | csharp_space_between_method_call_parameter_list_parentheses = false
250 | csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
251 | csharp_space_between_method_declaration_name_and_open_parenthesis = false
252 | csharp_space_between_method_declaration_parameter_list_parentheses = false
253 | csharp_space_between_parentheses = false
254 | csharp_space_between_square_brackets = false
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 | *.sln merge=union
7 | *.csproj merge=union
8 | *.vbproj merge=union
9 | *.fsproj merge=union
10 | *.dbproj merge=union
11 |
12 | # Standard to msysgit
13 | *.doc diff=astextplain
14 | *.DOC diff=astextplain
15 | *.docx diff=astextplain
16 | *.DOCX diff=astextplain
17 | *.dot diff=astextplain
18 | *.DOT diff=astextplain
19 | *.pdf diff=astextplain
20 | *.PDF diff=astextplain
21 | *.rtf diff=astextplain
22 | *.RTF diff=astextplain
23 |
--------------------------------------------------------------------------------
/.github/workflows/cd.yml:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT license.
3 |
4 | # This continuous delivery pipeline is meant to be triggered on release, anytime a user pushes code associated to a git tag,
5 | # and will run against multiple configurations and production environments.
6 | # This pipeline builds the Wpf project based upon the configuration matrix below. In order to
7 | # create different channels of the application, the pipeline uses the Package.Identity.Name defined in the
8 | # Package.appxmanifest in the Windows Application Packaging Project to uniquely identify the application,
9 | # depending on which channel is being built.
10 | # Once the MSIX is created for each channel configuration, the agent archives the AppPackages folder, then creates
11 | # a Release with the specified git release tag. The archive is uploaded to the release as an asset for storage or distribution.
12 | name: Wpf Continuous Delivery
13 |
14 | # Trigger on any push with a git tag
15 | # To create a git tag, run the following commands on the branch you wish to release:
16 | # git tag 1.0.0.0
17 | # git push origin --tags
18 | on:
19 | push:
20 | tags:
21 | - '*'
22 |
23 | jobs:
24 |
25 | build:
26 |
27 | strategy:
28 |
29 | # The following build matrix allows builds across multiple configurations (Debug and Release) and production environments such as
30 | # development, production for sideload applications and production for the Microsoft store.
31 | # For more information, see https://help.github.com/en/actions/configuring-and-managing-workflows/configuring-a-workflow#configuring-a-build-matrix
32 | matrix:
33 | channel: [Dev, Prod_Sideload, Prod_Store]
34 | targetPlatform: [x86, x64]
35 | include:
36 |
37 | # includes the following variables for the matrix leg matching Dev
38 | - channel: Dev
39 | ChannelName: Dev
40 | Configuration: Debug
41 | DistributionUrl: https://microsoft.github.io/github-actions-for-desktop-apps-distribution-dev
42 | MsixPackageId: MyWPFApp.DevOpsDemo.Dev
43 | MsixPublisherId: CN=GitHubActionsDemo
44 | MsixPackageDisplayName: MyWPFApp (Dev)
45 |
46 | # includes the following variables for the matrix leg matching Prod_Sideload
47 | - channel: Prod_Sideload
48 | Configuration: Release
49 | ChannelName: Prod_Sideload
50 | DistributionUrl: https://microsoft.github.io/github-actions-for-desktop-apps-distribution-prod
51 | MsixPackageId: MyWPFApp.DevOpsDemo.ProdSideload
52 | MsixPublisherId: CN=GitHubActionsDemo
53 | MsixPackageDisplayName: MyWPFApp (ProdSideload)
54 |
55 | # includes the following variables for the matrix leg matching Prod_Store
56 | - channel: Prod_Store
57 | Configuration: Release
58 | ChannelName: Prod_Store
59 | DistributionUrl:
60 | MsixPackageId: MyWPFApp.DevOpsDemo.ProdStore
61 | MsixPublisherId: CN=GitHubActionsDemo
62 | MsixPackageDisplayName: MyWPFApp (ProdStore)
63 |
64 | runs-on: windows-latest
65 |
66 | env:
67 | App_Packages_Archive: AppPackages.zip
68 | App_Packages_Directory: AppPackages
69 | SigningCertificate: GitHubActionsDemo.pfx
70 | Solution_Path: MyWpfApp.sln
71 | Test_Project_Path: MyWpfApp.Tests\MyWpfApp.Tests.csproj
72 | Wpf_Project_Path: MyWpfApp\MyWpfApp.csproj
73 | Wap_Project_Directory: MyWpfApp.Package
74 | Wap_Project_Name: MyWpfApp.Package.wapproj
75 | Actions_Allow_Unsecure_Commands: true # Allows AddPAth and SetEnv commands
76 |
77 | steps:
78 | - name: Checkout
79 | uses: actions/checkout@v2
80 | with:
81 | fetch-depth: 0 # avoid shallow clone so nbgv can do its work.
82 |
83 | # Use Nerdbank.GitVersioning to set version variables: https://github.com/AArnott/nbgv
84 | - name: Use Nerdbank.GitVersioning to set version variables
85 | uses: dotnet/nbgv@master
86 | id: nbgv
87 |
88 | # Install the .NET Core workload
89 | - name: Install .NET Core
90 | uses: actions/setup-dotnet@v3
91 | with:
92 | dotnet-version: '6.0.x'
93 |
94 | # Add MsBuild to the PATH: https://github.com/microsoft/setup-msbuild
95 | - name: Setup MSBuild.exe
96 | uses: microsoft/setup-msbuild@v1.1
97 |
98 | # Update the appxmanifest before build by setting the per-channel values set in the matrix such as
99 | # the Package.Identity.Version or the Package.Identity.Name, which allows multiple channels to be built.
100 | - name: Update manifest version
101 | run: |
102 | [xml]$manifest = get-content ".\$env:Wap_Project_Directory\Package.appxmanifest"
103 | $manifest.Package.Identity.Version = "${{ steps.nbgv.outputs.SimpleVersion }}.0"
104 | $manifest.Package.Identity.Name = "${{ matrix.MsixPackageId }}"
105 | $manifest.Package.Identity.Publisher = "${{ matrix.MsixPublisherId }}"
106 | $manifest.Package.Properties.DisplayName = "${{ matrix.MsixPackageDisplayName }}"
107 | $manifest.Package.Applications.Application.VisualElements.DisplayName = "${{ matrix.MsixPackageDisplayName }}"
108 | $manifest.save(".\$env:Wap_Project_Directory\Package.appxmanifest")
109 |
110 | # Decode the Base64 encoded Pfx
111 | - name: Decode the Pfx
112 | run: |
113 | $pfx_cert_byte = [System.Convert]::FromBase64String("${{ secrets.Base64_Encoded_Pfx }}")
114 | $currentDirectory = Get-Location
115 | $certificatePath = Join-Path -Path $currentDirectory -ChildPath $env:Wap_Project_Directory -AdditionalChildPath $env:SigningCertificate
116 | [IO.File]::WriteAllBytes("$certificatePath", $pfx_cert_byte)
117 | if: matrix.ChannelName != 'Prod_Store'
118 |
119 | # Restore the application
120 | - name: Restore the Wpf application to populate the obj folder
121 | run: msbuild $env:Solution_Path /t:Restore /p:Configuration=$env:Configuration /p:RuntimeIdentifier=$env:RuntimeIdentifier
122 | env:
123 | Configuration: ${{ matrix.Configuration }}
124 | RuntimeIdentifier: win-${{ matrix.targetplatform }}
125 |
126 | # Build the Windows Application Packaging project for Dev and Prod_Sideload
127 | - name: Build the Windows Application Packaging Project (wapproj) for ${{ matrix.ChannelName }}
128 | run: msbuild $env:Solution_Path /p:Platform=$env:TargetPlatform /p:Configuration=$env:Configuration /p:UapAppxPackageBuildMode=$env:BuildMode /p:AppxBundle=$env:AppxBundle /p:PackageCertificateKeyFile=$env:SigningCertificate /p:PackageCertificatePassword=${{ secrets.Pfx_Key }}
129 | if: matrix.ChannelName != 'Prod_Store'
130 | env:
131 | AppxBundle: Never
132 | AppInstallerUri: ${{ matrix.DistributionUrl }}
133 | BuildMode: SideloadOnly
134 | Configuration: ${{ matrix.Configuration }}
135 | GenerateAppInstallerFile: True
136 | TargetPlatform: ${{ matrix.targetplatform }}
137 |
138 | # Build the Windows Application Packaging project for Prod_Store
139 | - name: Build the Windows Application Packaging Project (wapproj) for ${{ matrix.ChannelName }}
140 | run: msbuild $env:Solution_Path /p:Platform=$env:TargetPlatform /p:Configuration=$env:Configuration /p:UapAppxPackageBuildMode=$env:BuildMode /p:AppxBundle=$env:AppxBundle /p:GenerateAppInstallerFile=$env:GenerateAppInstallerFile /p:AppxPackageSigningEnabled=$env:AppxPackageSigningEnabled
141 | if: matrix.ChannelName == 'Prod_Store'
142 | env:
143 | AppxBundle: Never
144 | AppxPackageSigningEnabled: False
145 | BuildMode: StoreUpload
146 | Configuration: ${{ matrix.Configuration }}
147 | GenerateAppInstallerFile: False
148 | TargetPlatform: ${{ matrix.targetplatform }}
149 |
150 | # Remove the .pfx
151 | - name: Remove the .pfx
152 | run: Remove-Item -path $env:Wap_Project_Directory\$env:SigningCertificate
153 | if: matrix.ChannelName != 'Prod_Store'
154 |
155 | # Archive the package
156 | - name: Create archive
157 | run: Compress-Archive -Path $env:Wap_Project_Directory\$env:App_Packages_Directory\* -DestinationPath $env:Wap_Project_Directory\$env:App_Packages_Directory\$env:App_Packages_Archive
158 |
159 | # Create the release: https://github.com/actions/create-release
160 | - name: Create release
161 | id: create_release
162 | uses: actions/create-release@v1
163 | env:
164 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
165 | with:
166 | tag_name: ${{ github.ref}}.${{matrix.ChannelName}}.${{ matrix.targetplatform }}
167 | release_name: ${{ github.ref }}.${{ matrix.ChannelName }}.${{ matrix.targetplatform }}
168 | draft: false
169 | prerelease: false
170 |
171 | # Upload release asset: https://github.com/actions/upload-release-asset
172 | - name: Update release asset
173 | id: upload-release-asset
174 | uses: actions/upload-release-asset@v1
175 | env:
176 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
177 | with:
178 | upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
179 | asset_path: ${{ env.Wap_Project_Directory }}\${{ env.App_Packages_Directory }}\${{ env.App_Packages_Archive }}
180 | asset_name: ${{ env.App_Packages_Archive }}
181 | asset_content_type: application/zip
182 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation.
2 | # Licensed under the MIT license.
3 |
4 | # This continuous integration pipeline is triggered anytime a user pushes code to the repo.
5 | # This pipeline builds the Wpf project, runs unit tests, then saves the MSIX build artifact.
6 | name: Wpf Continuous Integration
7 |
8 | # Trigger on every master branch push and pull request
9 | on:
10 | push:
11 | branches:
12 | - master
13 | - 'maintenence/*'
14 | pull_request:
15 | branches:
16 | - master
17 |
18 | jobs:
19 |
20 | build:
21 |
22 | strategy:
23 | matrix:
24 | targetplatform: [x86, x64]
25 |
26 | runs-on: windows-latest
27 |
28 | env:
29 | App_Packages_Directory: AppPackages
30 | SigningCertificate: GitHubActionsDemo.pfx
31 | Solution_Path: MyWpfApp.sln
32 | Test_Project_Path: MyWpfApp.Tests\MyWpfApp.Tests.csproj
33 | Wpf_Project_Path: MyWpfApp\MyWpfApp.csproj
34 | Wap_Project_Directory: MyWpfApp.Package
35 | Wap_Project_Name: MyWpfApp.Package.wapproj
36 | Actions_Allow_Unsecure_Commands: true # Allows AddPAth and SetEnv commands
37 |
38 | steps:
39 | - name: Checkout
40 | uses: actions/checkout@v2
41 | with:
42 | fetch-depth: 0 # avoid shallow clone so nbgv can do its work.
43 |
44 | # Use Nerdbank.GitVersioning to set version variables: https://github.com/AArnott/nbgv
45 | - name: Use Nerdbank.GitVersioning to set version variables
46 | uses: dotnet/nbgv@master
47 | id: nbgv
48 |
49 | # Install the .NET Core workload
50 | - name: Install .NET Core
51 | uses: actions/setup-dotnet@v3
52 | with:
53 | dotnet-version: '6.0.x'
54 |
55 | # Add MsBuild to the PATH: https://github.com/microsoft/setup-msbuild
56 | - name: Setup MSBuild.exe
57 | uses: microsoft/setup-msbuild@v1.1
58 |
59 | # Update the version before build
60 | - name: Update manifest version
61 | run: |
62 | [xml]$manifest = get-content ".\$env:Wap_Project_Directory\Package.appxmanifest"
63 | $manifest.Package.Identity.Version = "${{ steps.nbgv.outputs.SimpleVersion }}.0"
64 | $manifest.save(".\$env:Wap_Project_Directory\Package.appxmanifest")
65 |
66 | # Test
67 | - name: Execute Unit Tests
68 | run: dotnet test $env:Test_Project_Path
69 |
70 | # Restore the application
71 | - name: Restore the Wpf application to populate the obj folder
72 | run: msbuild $env:Solution_Path /t:Restore /p:Configuration=$env:Configuration /p:RuntimeIdentifier=$env:RuntimeIdentifier
73 | env:
74 | Configuration: Debug
75 | RuntimeIdentifier: win-${{ matrix.targetplatform }}
76 |
77 | # Decode the Base64 encoded Pfx
78 | - name: Decode the Pfx
79 | run: |
80 | $pfx_cert_byte = [System.Convert]::FromBase64String("${{ secrets.Base64_Encoded_Pfx }}")
81 | $currentDirectory = Get-Location
82 | $certificatePath = Join-Path -Path $currentDirectory -ChildPath $env:Wap_Project_Directory -AdditionalChildPath $env:SigningCertificate
83 | [IO.File]::WriteAllBytes("$certificatePath", $pfx_cert_byte)
84 |
85 | # Build the Windows Application Packaging project
86 | - name: Build the Windows Application Packaging Project (wapproj)
87 | run: msbuild $env:Solution_Path /p:Platform=$env:TargetPlatform /p:Configuration=$env:Configuration /p:UapAppxPackageBuildMode=$env:BuildMode /p:AppxBundle=$env:AppxBundle /p:PackageCertificateKeyFile=$env:SigningCertificate /p:PackageCertificatePassword=${{ secrets.Pfx_Key }}
88 | env:
89 | AppxBundle: Never
90 | BuildMode: SideloadOnly
91 | Configuration: Debug
92 | TargetPlatform: ${{ matrix.targetplatform }}
93 |
94 | # Remove the .pfx
95 | - name: Remove the .pfx
96 | run: Remove-Item -path $env:Wap_Project_Directory\$env:SigningCertificate
97 |
98 | # Upload the MSIX package: https://github.com/marketplace/actions/upload-artifact
99 | - name: Upload build artifacts
100 | uses: actions/upload-artifact@v1
101 | with:
102 | name: MSIX Package
103 | path: ${{ env.Wap_Project_Directory }}\${{ env.App_Packages_Directory }}
104 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Aa][Rr][Mm]/
27 | [Aa][Rr][Mm]64/
28 | bld/
29 | [Bb]in/
30 | [Oo]bj/
31 | [Ll]og/
32 | [Ll]ogs/
33 |
34 | # Visual Studio 2015/2017 cache/options directory
35 | .vs/
36 | # Uncomment if you have tasks that create the project's static files in wwwroot
37 | #wwwroot/
38 |
39 | # Visual Studio 2017 auto generated files
40 | Generated\ Files/
41 |
42 | # MSTest test Results
43 | [Tt]est[Rr]esult*/
44 | [Bb]uild[Ll]og.*
45 |
46 | # NUnit
47 | *.VisualState.xml
48 | TestResult.xml
49 | nunit-*.xml
50 |
51 | # Build Results of an ATL Project
52 | [Dd]ebugPS/
53 | [Rr]eleasePS/
54 | dlldata.c
55 |
56 | # Benchmark Results
57 | BenchmarkDotNet.Artifacts/
58 |
59 | # .NET Core
60 | project.lock.json
61 | project.fragment.lock.json
62 | artifacts/
63 |
64 | # StyleCop
65 | StyleCopReport.xml
66 |
67 | # Files built by Visual Studio
68 | *_i.c
69 | *_p.c
70 | *_h.h
71 | *.ilk
72 | *.meta
73 | *.obj
74 | *.iobj
75 | *.pch
76 | *.pdb
77 | *.ipdb
78 | *.pgc
79 | *.pgd
80 | *.rsp
81 | *.sbr
82 | *.tlb
83 | *.tli
84 | *.tlh
85 | *.tmp
86 | *.tmp_proj
87 | *_wpftmp.csproj
88 | *.log
89 | *.vspscc
90 | *.vssscc
91 | .builds
92 | *.pidb
93 | *.svclog
94 | *.scc
95 |
96 | # Chutzpah Test files
97 | _Chutzpah*
98 |
99 | # Visual C++ cache files
100 | ipch/
101 | *.aps
102 | *.ncb
103 | *.opendb
104 | *.opensdf
105 | *.sdf
106 | *.cachefile
107 | *.VC.db
108 | *.VC.VC.opendb
109 |
110 | # Visual Studio profiler
111 | *.psess
112 | *.vsp
113 | *.vspx
114 | *.sap
115 |
116 | # Visual Studio Trace Files
117 | *.e2e
118 |
119 | # TFS 2012 Local Workspace
120 | $tf/
121 |
122 | # Guidance Automation Toolkit
123 | *.gpState
124 |
125 | # ReSharper is a .NET coding add-in
126 | _ReSharper*/
127 | *.[Rr]e[Ss]harper
128 | *.DotSettings.user
129 |
130 | # TeamCity is a build add-in
131 | _TeamCity*
132 |
133 | # DotCover is a Code Coverage Tool
134 | *.dotCover
135 |
136 | # AxoCover is a Code Coverage Tool
137 | .axoCover/*
138 | !.axoCover/settings.json
139 |
140 | # Visual Studio code coverage results
141 | *.coverage
142 | *.coveragexml
143 |
144 | # NCrunch
145 | _NCrunch_*
146 | .*crunch*.local.xml
147 | nCrunchTemp_*
148 |
149 | # MightyMoose
150 | *.mm.*
151 | AutoTest.Net/
152 |
153 | # Web workbench (sass)
154 | .sass-cache/
155 |
156 | # Installshield output folder
157 | [Ee]xpress/
158 |
159 | # DocProject is a documentation generator add-in
160 | DocProject/buildhelp/
161 | DocProject/Help/*.HxT
162 | DocProject/Help/*.HxC
163 | DocProject/Help/*.hhc
164 | DocProject/Help/*.hhk
165 | DocProject/Help/*.hhp
166 | DocProject/Help/Html2
167 | DocProject/Help/html
168 |
169 | # Click-Once directory
170 | publish/
171 |
172 | # Publish Web Output
173 | *.[Pp]ublish.xml
174 | *.azurePubxml
175 | # Note: Comment the next line if you want to checkin your web deploy settings,
176 | # but database connection strings (with potential passwords) will be unencrypted
177 | *.publishproj
178 |
179 | # Uncomment the next line if you don't want to checkin Publisher Profiles.
180 | # *.pubxml
181 |
182 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
183 | # checkin your Azure Web App publish settings, but sensitive information contained
184 | # in these scripts will be unencrypted
185 | PublishScripts/
186 |
187 | # NuGet Packages
188 | *.nupkg
189 | # NuGet Symbol Packages
190 | *.snupkg
191 | # The packages folder can be ignored because of Package Restore
192 | **/[Pp]ackages/*
193 | # except build/, which is used as an MSBuild target.
194 | !**/[Pp]ackages/build/
195 | # Uncomment if necessary however generally it will be regenerated when needed
196 | #!**/[Pp]ackages/repositories.config
197 | # NuGet v3's project.json files produces more ignorable files
198 | *.nuget.props
199 | *.nuget.targets
200 |
201 | # Microsoft Azure Build Output
202 | csx/
203 | *.build.csdef
204 |
205 | # Microsoft Azure Emulator
206 | ecf/
207 | rcf/
208 |
209 | # Windows Store app package directories and files
210 | AppPackages/
211 | BundleArtifacts/
212 | Package.StoreAssociation.xml
213 | _pkginfo.txt
214 | *.appx
215 | *.appxbundle
216 | *.appxupload
217 |
218 | # Visual Studio cache files
219 | # files ending in .cache can be ignored
220 | *.[Cc]ache
221 | # but keep track of directories ending in .cache
222 | !?*.[Cc]ache/
223 |
224 | # Others
225 | ClientBin/
226 | ~$*
227 | *~
228 | *.dbmdl
229 | *.dbproj.schemaview
230 | *.jfm
231 | *.pfx
232 | *.publishsettings
233 | orleans.codegen.cs
234 |
235 | # Including strong name files can present a security risk
236 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
237 | #*.snk
238 |
239 | # Since there are multiple workflows, uncomment next line to ignore bower_components
240 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
241 | #bower_components/
242 |
243 | # RIA/Silverlight projects
244 | Generated_Code/
245 |
246 | # Backup & report files from converting an old project file
247 | # to a newer Visual Studio version. Backup files are not needed,
248 | # because we have git ;-)
249 | _UpgradeReport_Files/
250 | Backup*/
251 | UpgradeLog*.XML
252 | UpgradeLog*.htm
253 | ServiceFabricBackup/
254 | *.rptproj.bak
255 |
256 | # SQL Server files
257 | *.mdf
258 | *.ldf
259 | *.ndf
260 |
261 | # Business Intelligence projects
262 | *.rdl.data
263 | *.bim.layout
264 | *.bim_*.settings
265 | *.rptproj.rsuser
266 | *- [Bb]ackup.rdl
267 | *- [Bb]ackup ([0-9]).rdl
268 | *- [Bb]ackup ([0-9][0-9]).rdl
269 |
270 | # Microsoft Fakes
271 | FakesAssemblies/
272 |
273 | # GhostDoc plugin setting file
274 | *.GhostDoc.xml
275 |
276 | # Node.js Tools for Visual Studio
277 | .ntvs_analysis.dat
278 | node_modules/
279 |
280 | # Visual Studio 6 build log
281 | *.plg
282 |
283 | # Visual Studio 6 workspace options file
284 | *.opt
285 |
286 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
287 | *.vbw
288 |
289 | # Visual Studio LightSwitch build output
290 | **/*.HTMLClient/GeneratedArtifacts
291 | **/*.DesktopClient/GeneratedArtifacts
292 | **/*.DesktopClient/ModelManifest.xml
293 | **/*.Server/GeneratedArtifacts
294 | **/*.Server/ModelManifest.xml
295 | _Pvt_Extensions
296 |
297 | # Paket dependency manager
298 | .paket/paket.exe
299 | paket-files/
300 |
301 | # FAKE - F# Make
302 | .fake/
303 |
304 | # CodeRush personal settings
305 | .cr/personal
306 |
307 | # Python Tools for Visual Studio (PTVS)
308 | __pycache__/
309 | *.pyc
310 |
311 | # Cake - Uncomment if you are using it
312 | # tools/**
313 | # !tools/packages.config
314 |
315 | # Tabs Studio
316 | *.tss
317 |
318 | # Telerik's JustMock configuration file
319 | *.jmconfig
320 |
321 | # BizTalk build output
322 | *.btp.cs
323 | *.btm.cs
324 | *.odx.cs
325 | *.xsd.cs
326 |
327 | # OpenCover UI analysis results
328 | OpenCover/
329 |
330 | # Azure Stream Analytics local run output
331 | ASALocalRun/
332 |
333 | # MSBuild Binary and Structured Log
334 | *.binlog
335 |
336 | # NVidia Nsight GPU debugger configuration file
337 | *.nvuser
338 |
339 | # MFractors (Xamarin productivity tool) working folder
340 | .mfractor/
341 |
342 | # Local History for Visual Studio
343 | .localhistory/
344 |
345 | # BeatPulse healthcheck temp database
346 | healthchecksdb
347 |
348 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
349 | MigrationBackup/
350 |
351 | # Ionide (cross platform F# VS Code tools) working folder
352 | .ionide/
353 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Microsoft Open Source Code of Conduct
2 |
3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
4 |
5 | Resources:
6 |
7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
10 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | This project welcomes contributions and suggestions. Most contributions require you to
4 | agree to a Contributor License Agreement (CLA) declaring that you have the right to,
5 | and actually do, grant us the rights to use your contribution. For details, visit
6 | https://cla.microsoft.com.
7 |
8 | When you submit a pull request, a CLA-bot will automatically determine whether you need
9 | to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the
10 | instructions provided by the bot. You will only need to do this once across all repositories using our CLA.
11 |
12 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
13 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
14 | or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
--------------------------------------------------------------------------------
/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | win-x64;win-x86
4 |
5 |
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Microsoft Corporation.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE
22 |
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/BadgeLogo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/BadgeLogo.scale-100.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/BadgeLogo.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/BadgeLogo.scale-125.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/BadgeLogo.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/BadgeLogo.scale-150.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/BadgeLogo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/BadgeLogo.scale-200.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/BadgeLogo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/BadgeLogo.scale-400.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/LargeTile.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/LargeTile.scale-100.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/LargeTile.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/LargeTile.scale-125.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/LargeTile.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/LargeTile.scale-150.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/LargeTile.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/LargeTile.scale-200.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/LargeTile.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/LargeTile.scale-400.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/SmallTile.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/SmallTile.scale-100.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/SmallTile.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/SmallTile.scale-125.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/SmallTile.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/SmallTile.scale-150.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/SmallTile.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/SmallTile.scale-200.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/SmallTile.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/SmallTile.scale-400.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/SplashScreen.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/SplashScreen.scale-100.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/SplashScreen.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/SplashScreen.scale-125.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/SplashScreen.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/SplashScreen.scale-150.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/SplashScreen.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/SplashScreen.scale-200.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/SplashScreen.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/SplashScreen.scale-400.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/Square150x150Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/Square150x150Logo.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/Square150x150Logo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/Square150x150Logo.scale-100.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/Square150x150Logo.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/Square150x150Logo.scale-125.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/Square150x150Logo.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/Square150x150Logo.scale-150.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/Square150x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/Square150x150Logo.scale-200.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/Square150x150Logo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/Square150x150Logo.scale-400.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/Square44x44Logo.altform-unplated_targetsize-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/Square44x44Logo.altform-unplated_targetsize-16.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/Square44x44Logo.altform-unplated_targetsize-24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/Square44x44Logo.altform-unplated_targetsize-24.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/Square44x44Logo.altform-unplated_targetsize-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/Square44x44Logo.altform-unplated_targetsize-256.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/Square44x44Logo.altform-unplated_targetsize-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/Square44x44Logo.altform-unplated_targetsize-32.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/Square44x44Logo.altform-unplated_targetsize-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/Square44x44Logo.altform-unplated_targetsize-48.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/Square44x44Logo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/Square44x44Logo.scale-100.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/Square44x44Logo.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/Square44x44Logo.scale-125.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/Square44x44Logo.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/Square44x44Logo.scale-150.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/Square44x44Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/Square44x44Logo.scale-200.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/Square44x44Logo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/Square44x44Logo.scale-400.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/Square44x44Logo.targetsize-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/Square44x44Logo.targetsize-16.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/Square44x44Logo.targetsize-24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/Square44x44Logo.targetsize-24.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/Square44x44Logo.targetsize-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/Square44x44Logo.targetsize-256.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/Square44x44Logo.targetsize-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/Square44x44Logo.targetsize-32.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/Square44x44Logo.targetsize-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/Square44x44Logo.targetsize-48.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/StoreLogo.backup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/StoreLogo.backup.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/StoreLogo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/StoreLogo.scale-100.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/StoreLogo.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/StoreLogo.scale-125.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/StoreLogo.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/StoreLogo.scale-150.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/StoreLogo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/StoreLogo.scale-200.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/StoreLogo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/StoreLogo.scale-400.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/WideTile.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/WideTile.scale-100.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/WideTile.scale-125.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/WideTile.scale-125.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/WideTile.scale-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/WideTile.scale-150.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/WideTile.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/WideTile.scale-200.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/Images/WideTile.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp.Package/Images/WideTile.scale-400.png
--------------------------------------------------------------------------------
/MyWPFApp.Package/MyWPFApp.Package.wapproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 15.0
5 |
6 |
7 |
8 | Debug
9 | x86
10 |
11 |
12 | Release
13 | x86
14 |
15 |
16 | Debug
17 | x64
18 |
19 |
20 | Release
21 | x64
22 |
23 |
24 | Debug
25 | AnyCPU
26 |
27 |
28 | Release
29 | AnyCPU
30 |
31 |
32 |
33 | $(MSBuildExtensionsPath)\Microsoft\DesktopBridge\
34 |
35 |
36 |
37 | 0536b61a-90cf-428d-b4f8-cf011b3a0830
38 | 10.0.19041.0
39 | 10.0.17763.0
40 | en-US
41 |
42 | True
43 |
48 |
49 |
50 |
51 |
52 | True
53 |
54 | neutral
55 |
56 | https://microsoft.github.io/github-actions-for-desktop-apps-distribution-local
57 | False
58 | ..\MyWPFApp\MyWPFApp.csproj
59 | 0
60 | OnApplicationRun
61 | True
62 | SHA256
63 |
64 |
65 | Always
66 |
67 |
68 | Always
69 |
70 |
71 | Always
72 |
73 |
74 | Always
75 |
76 |
77 | Always
78 |
79 |
80 | Always
81 |
82 |
83 |
84 | Designer
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | True
95 | Full
96 | Properties\PublishProfiles\SelfContainedWin86.pubxml
97 | Properties\PublishProfiles\SelfContainedWin64.pubxml
98 | Properties\PublishProfiles\SelfContainedWin86Debug.pubxml
99 | Properties\PublishProfiles\SelfContainedWin64Debug.pubxml
100 |
101 |
102 |
103 |
--------------------------------------------------------------------------------
/MyWPFApp.Package/Package.appinstaller:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/MyWPFApp.Package/Package.appxmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
13 |
14 |
15 | MyWPFApp (Local)
16 | Build
17 | Images\StoreLogo.png
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
32 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/MyWPFApp.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.28817.109
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MyWPFApp", "MyWPFApp\MyWPFApp.csproj", "{044FC6EF-3251-4AC0-BC2E-C90C16A068CB}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{4F26147B-A031-40ED-9CA1-A765A6997816}"
9 | ProjectSection(SolutionItems) = preProject
10 | .gitignore = .gitignore
11 | .github\workflows\cd.yml = .github\workflows\cd.yml
12 | .github\workflows\ci.yml = .github\workflows\ci.yml
13 | Directory.Build.props = Directory.Build.props
14 | global.json = global.json
15 | README.md = README.md
16 | version.json = version.json
17 | EndProjectSection
18 | EndProject
19 | Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "MyWPFApp.Package", "MyWPFApp.Package\MyWPFApp.Package.wapproj", "{0536B61A-90CF-428D-B4F8-CF011B3A0830}"
20 | EndProject
21 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MyWPFApp.Tests", "MyWpfApp.Tests\MyWPFApp.Tests.csproj", "{203E0C07-10FC-450B-8D92-F6AA50167946}"
22 | EndProject
23 | Global
24 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
25 | Debug|Any CPU = Debug|Any CPU
26 | Debug|x64 = Debug|x64
27 | Debug|x86 = Debug|x86
28 | Release|Any CPU = Release|Any CPU
29 | Release|x64 = Release|x64
30 | Release|x86 = Release|x86
31 | EndGlobalSection
32 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
33 | {044FC6EF-3251-4AC0-BC2E-C90C16A068CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
34 | {044FC6EF-3251-4AC0-BC2E-C90C16A068CB}.Debug|Any CPU.Build.0 = Debug|Any CPU
35 | {044FC6EF-3251-4AC0-BC2E-C90C16A068CB}.Debug|x64.ActiveCfg = Debug|Any CPU
36 | {044FC6EF-3251-4AC0-BC2E-C90C16A068CB}.Debug|x64.Build.0 = Debug|Any CPU
37 | {044FC6EF-3251-4AC0-BC2E-C90C16A068CB}.Debug|x86.ActiveCfg = Debug|Any CPU
38 | {044FC6EF-3251-4AC0-BC2E-C90C16A068CB}.Debug|x86.Build.0 = Debug|Any CPU
39 | {044FC6EF-3251-4AC0-BC2E-C90C16A068CB}.Release|Any CPU.ActiveCfg = Release|Any CPU
40 | {044FC6EF-3251-4AC0-BC2E-C90C16A068CB}.Release|Any CPU.Build.0 = Release|Any CPU
41 | {044FC6EF-3251-4AC0-BC2E-C90C16A068CB}.Release|x64.ActiveCfg = Release|Any CPU
42 | {044FC6EF-3251-4AC0-BC2E-C90C16A068CB}.Release|x64.Build.0 = Release|Any CPU
43 | {044FC6EF-3251-4AC0-BC2E-C90C16A068CB}.Release|x86.ActiveCfg = Release|Any CPU
44 | {044FC6EF-3251-4AC0-BC2E-C90C16A068CB}.Release|x86.Build.0 = Release|Any CPU
45 | {0536B61A-90CF-428D-B4F8-CF011B3A0830}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
46 | {0536B61A-90CF-428D-B4F8-CF011B3A0830}.Debug|Any CPU.Build.0 = Debug|Any CPU
47 | {0536B61A-90CF-428D-B4F8-CF011B3A0830}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
48 | {0536B61A-90CF-428D-B4F8-CF011B3A0830}.Debug|x64.ActiveCfg = Debug|x64
49 | {0536B61A-90CF-428D-B4F8-CF011B3A0830}.Debug|x64.Build.0 = Debug|x64
50 | {0536B61A-90CF-428D-B4F8-CF011B3A0830}.Debug|x64.Deploy.0 = Debug|x64
51 | {0536B61A-90CF-428D-B4F8-CF011B3A0830}.Debug|x86.ActiveCfg = Debug|x86
52 | {0536B61A-90CF-428D-B4F8-CF011B3A0830}.Debug|x86.Build.0 = Debug|x86
53 | {0536B61A-90CF-428D-B4F8-CF011B3A0830}.Debug|x86.Deploy.0 = Debug|x86
54 | {0536B61A-90CF-428D-B4F8-CF011B3A0830}.Release|Any CPU.ActiveCfg = Release|x86
55 | {0536B61A-90CF-428D-B4F8-CF011B3A0830}.Release|Any CPU.Build.0 = Release|x86
56 | {0536B61A-90CF-428D-B4F8-CF011B3A0830}.Release|Any CPU.Deploy.0 = Release|x86
57 | {0536B61A-90CF-428D-B4F8-CF011B3A0830}.Release|x64.ActiveCfg = Release|x64
58 | {0536B61A-90CF-428D-B4F8-CF011B3A0830}.Release|x64.Build.0 = Release|x64
59 | {0536B61A-90CF-428D-B4F8-CF011B3A0830}.Release|x64.Deploy.0 = Release|x64
60 | {0536B61A-90CF-428D-B4F8-CF011B3A0830}.Release|x86.ActiveCfg = Release|x86
61 | {0536B61A-90CF-428D-B4F8-CF011B3A0830}.Release|x86.Build.0 = Release|x86
62 | {0536B61A-90CF-428D-B4F8-CF011B3A0830}.Release|x86.Deploy.0 = Release|x86
63 | {203E0C07-10FC-450B-8D92-F6AA50167946}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
64 | {203E0C07-10FC-450B-8D92-F6AA50167946}.Debug|Any CPU.Build.0 = Debug|Any CPU
65 | {203E0C07-10FC-450B-8D92-F6AA50167946}.Debug|x64.ActiveCfg = Debug|Any CPU
66 | {203E0C07-10FC-450B-8D92-F6AA50167946}.Debug|x64.Build.0 = Debug|Any CPU
67 | {203E0C07-10FC-450B-8D92-F6AA50167946}.Debug|x86.ActiveCfg = Debug|Any CPU
68 | {203E0C07-10FC-450B-8D92-F6AA50167946}.Debug|x86.Build.0 = Debug|Any CPU
69 | {203E0C07-10FC-450B-8D92-F6AA50167946}.Release|Any CPU.ActiveCfg = Release|Any CPU
70 | {203E0C07-10FC-450B-8D92-F6AA50167946}.Release|Any CPU.Build.0 = Release|Any CPU
71 | {203E0C07-10FC-450B-8D92-F6AA50167946}.Release|x64.ActiveCfg = Release|Any CPU
72 | {203E0C07-10FC-450B-8D92-F6AA50167946}.Release|x64.Build.0 = Release|Any CPU
73 | {203E0C07-10FC-450B-8D92-F6AA50167946}.Release|x86.ActiveCfg = Release|Any CPU
74 | {203E0C07-10FC-450B-8D92-F6AA50167946}.Release|x86.Build.0 = Release|Any CPU
75 | EndGlobalSection
76 | GlobalSection(SolutionProperties) = preSolution
77 | HideSolutionNode = FALSE
78 | EndGlobalSection
79 | GlobalSection(ExtensibilityGlobals) = postSolution
80 | SolutionGuid = {FE785289-C15B-4F37-AA72-8EFFD2710DDD}
81 | EndGlobalSection
82 | EndGlobal
83 |
--------------------------------------------------------------------------------
/MyWPFApp/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/MyWPFApp/App.xaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation.
2 | // Licensed under the MIT license.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Configuration;
7 | using System.Data;
8 | using System.Linq;
9 | using System.Threading.Tasks;
10 | using System.Windows;
11 | using MyWPFApp.Telemetry;
12 |
13 | namespace MyWPFApp
14 | {
15 | ///
16 | /// Interaction logic for App.xaml
17 | ///
18 | public partial class App : Application
19 | {
20 | public App()
21 | {
22 | DiagnosticsClient.Initialize();
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/MyWPFApp/ApplicationInsights.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/MyWPFApp/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
15 |
19 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/MyWPFApp/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Windows;
3 | using OSVersionHelper;
4 |
5 | using MyWPFApp.Telemetry;
6 |
7 | namespace MyWPFApp
8 | {
9 | ///
10 | /// Interaction logic for MainWindow.xaml
11 | ///
12 | public partial class MainWindow : Window
13 | {
14 | public MainWindow()
15 | {
16 | InitializeComponent();
17 |
18 | packageName.Text = ThisAppInfo.GetDisplayName();
19 | assemblyVersion.Text = ThisAppInfo.GetThisAssemblyVersion();
20 | packageVersion.Text = ThisAppInfo.GetPackageVersion();
21 | installedFrom.Text = ThisAppInfo.GetAppInstallerUri();
22 | installLocation.Text = ThisAppInfo.GetInstallLocation();
23 | DiagnosticsClient.TrackPageView(nameof(MainWindow));
24 | }
25 | private void Button_Click(object sender, RoutedEventArgs e)
26 | {
27 | DiagnosticsClient.TrackEvent("ClickShowRuntimeInfo");
28 |
29 | if (ButtonShowRuntimeVersionInfo.Content.ToString().StartsWith("Show"))
30 | {
31 | RuntimeVersionInfo.Text = ThisAppInfo.GetDotNetRuntimeInfo();
32 | ButtonShowRuntimeVersionInfo.Content = "Hide Runtime Info";
33 | }
34 | else
35 | {
36 | RuntimeVersionInfo.Text = "";
37 | ButtonShowRuntimeVersionInfo.Content = "Show Runtime Info";
38 | }
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/MyWPFApp/MyWPFApp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | WinExe
5 | netcoreapp3.1
6 | true
7 | win.ico
8 | win-x86;win-x64
9 | 10.0.17134.0
10 | MyWPFApp.App
11 |
12 |
13 | $(Platform)
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/MyWPFApp/Properties/PublishProfiles/SelfContainedWin64.pubxml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 | FileSystem
8 | Release
9 | x64
10 | netcoreapp3.1
11 | bin\Release\netcoreapp3.1\publish\
12 | win-x64
13 | true
14 | False
15 | False
16 | False
17 |
18 |
--------------------------------------------------------------------------------
/MyWPFApp/Properties/PublishProfiles/SelfContainedWin64Debug.pubxml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 | FileSystem
8 | Debug
9 | x64
10 | netcoreapp3.1
11 | bin\Debug\netcoreapp3.1\publish\
12 | win-x64
13 | true
14 | False
15 | False
16 | False
17 |
18 |
--------------------------------------------------------------------------------
/MyWPFApp/Properties/PublishProfiles/SelfContainedWin86.pubxml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 | FileSystem
8 | Release
9 | x86
10 | netcoreapp3.1
11 | bin\Release\netcoreapp3.1\publish\
12 | win-x86
13 | true
14 | False
15 | False
16 | False
17 |
18 |
--------------------------------------------------------------------------------
/MyWPFApp/Properties/PublishProfiles/SelfContainedWin86Debug.pubxml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 | FileSystem
8 | Debug
9 | x86
10 | netcoreapp3.1
11 | bin\Debug\netcoreapp3.1\publish\
12 | win-x86
13 | true
14 | False
15 | False
16 | False
17 |
18 |
--------------------------------------------------------------------------------
/MyWPFApp/Telemetry/AppVersionTelemetryInitializer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 | using System.Text;
6 | using Microsoft.ApplicationInsights.Channel;
7 | using Microsoft.ApplicationInsights.Extensibility;
8 |
9 | namespace MyWPFApp.Telemetry
10 | {
11 | internal class AppVersionTelemetryInitializer : ITelemetryInitializer
12 | {
13 | private readonly string _wpfVersion;
14 | private readonly string _appVersion;
15 |
16 | public AppVersionTelemetryInitializer()
17 | {
18 | _wpfVersion = typeof(System.Windows.Application).Assembly.GetCustomAttribute().InformationalVersion;
19 | _appVersion = ThisAppInfo.GetPackageVersion();
20 | }
21 |
22 | public void Initialize(ITelemetry telemetry)
23 | {
24 | telemetry.Context.GlobalProperties["WPF version"] = _wpfVersion;
25 | telemetry.Context.Component.Version = _appVersion;
26 | }
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/MyWPFApp/Telemetry/DiagnosticsClient.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Text;
5 | using Microsoft.ApplicationInsights;
6 | using Microsoft.ApplicationInsights.Extensibility;
7 |
8 | namespace MyWPFApp.Telemetry
9 | {
10 | public static class DiagnosticsClient
11 | {
12 | private static bool _initialized;
13 | private static TelemetryClient _client;
14 |
15 | public static void Initialize()
16 | {
17 | TelemetryConfiguration.Active.TelemetryInitializers.Add(new AppVersionTelemetryInitializer());
18 | TelemetryConfiguration.Active.TelemetryInitializers.Add(new EnvironmentTelemetryInitializer());
19 |
20 | _initialized = true;
21 | _client = new TelemetryClient();
22 | System.Windows.Application.Current.Startup += Application_Startup;
23 | System.Windows.Application.Current.Exit += Application_Exit;
24 | System.Windows.Application.Current.DispatcherUnhandledException += DispatcherUnhandledException;
25 | }
26 |
27 | private static void DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
28 | {
29 | TrackException(e.Exception);
30 | }
31 |
32 | private static void Application_Exit(object sender, System.Windows.ExitEventArgs e)
33 | {
34 | TrackEvent("AppExit");
35 | _client.Flush();
36 | // Allow time for flushing:
37 | System.Threading.Thread.Sleep(1000);
38 | }
39 |
40 | private static void Application_Startup(object sender, System.Windows.StartupEventArgs e)
41 | {
42 | TrackEvent("AppStart");
43 | }
44 |
45 | public static void TrackEvent(string eventName, IDictionary properties = null, IDictionary metrics = null)
46 | {
47 | if (!_initialized) return;
48 | _client.TrackEvent(eventName, properties, metrics);
49 | }
50 |
51 | public static void TrackTrace(string evt)
52 | {
53 | if (!_initialized) return;
54 | _client.TrackTrace(evt);
55 | }
56 |
57 | public static void TrackException(Exception exception, IDictionary properties = null, IDictionary metrics = null)
58 | {
59 | if (!_initialized) return;
60 | _client.TrackException(exception, properties, metrics);
61 | }
62 |
63 | public static void TrackPageView(string pageName)
64 | {
65 | if (!_initialized) return;
66 | _client.TrackPageView(pageName);
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/MyWPFApp/Telemetry/EnvironmentTelemetryInitializer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Runtime.InteropServices;
6 | using System.Security.Cryptography;
7 | using System.Text;
8 | using Microsoft.ApplicationInsights.Channel;
9 | using Microsoft.ApplicationInsights.Extensibility;
10 |
11 | namespace MyWPFApp.Telemetry
12 | {
13 | internal class EnvironmentTelemetryInitializer : ITelemetryInitializer
14 | {
15 | public void Initialize(ITelemetry telemetry)
16 | {
17 | telemetry.Context.GlobalProperties["Environment"] = ThisAppInfo.GetPackageChannel() ?? "Local";
18 |
19 | // Always default to Local if we're in the debugger
20 | if (Debugger.IsAttached)
21 | {
22 | telemetry.Context.GlobalProperties["Environment"] = "Local";
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/MyWPFApp/ThisAppInfo.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation.
2 | // Licensed under the MIT license.
3 |
4 | using System;
5 | using System.IO;
6 | using System.Reflection;
7 | using System.Runtime.CompilerServices;
8 |
9 | using OSVersionHelper;
10 |
11 | using Windows.ApplicationModel;
12 | using Windows.Foundation.Metadata;
13 |
14 | namespace MyWPFApp
15 | {
16 | public class ThisAppInfo
17 | {
18 | public static string GetDisplayName()
19 | {
20 | if (WindowsVersionHelper.HasPackageIdentity)
21 | {
22 | return Package.Current.DisplayName;
23 | }
24 | return "Not packaged";
25 | }
26 |
27 | internal static string GetThisAssemblyVersion()
28 | {
29 | return typeof(MainWindow).Assembly.GetCustomAttribute().InformationalVersion;
30 | }
31 |
32 | internal static string GetInstallLocation()
33 | {
34 | return Assembly.GetExecutingAssembly().Location;
35 | }
36 |
37 | internal static string GetPackageVersion()
38 | {
39 | if (WindowsVersionHelper.HasPackageIdentity)
40 | {
41 | return $"{Package.Current.Id.Version.Major}.{Package.Current.Id.Version.Minor}.{Package.Current.Id.Version.Build}.{Package.Current.Id.Version.Revision}";
42 | }
43 | return "Not packaged";
44 | }
45 |
46 | internal static string GetPackageChannel()
47 | {
48 | if(WindowsVersionHelper.HasPackageIdentity)
49 | {
50 | return Package.Current.Id.Name.Substring(Package.Current.Id.Name.LastIndexOf('.') + 1);
51 | }
52 |
53 | return null;
54 | }
55 |
56 | internal static string GetDotNetInfo()
57 | {
58 | var runTimeDir = new FileInfo(typeof(string).Assembly.Location);
59 | var entryDir = new FileInfo(Assembly.GetEntryAssembly().Location);
60 | var IsSelfContaied = runTimeDir.DirectoryName == entryDir.DirectoryName;
61 |
62 | var result = ".NET Framework - ";
63 | if (IsSelfContaied)
64 | {
65 | result += "Self Contained Deployment";
66 | }
67 | else
68 | {
69 | result += "Framework Dependent Deployment";
70 | }
71 |
72 | return result;
73 | }
74 |
75 | public static string GetAppInstallerUri()
76 | {
77 | string result;
78 |
79 | if (!WindowsVersionHelper.HasPackageIdentity) return "Not packaged";
80 |
81 | if (ApiInformation.IsMethodPresent("Windows.ApplicationModel.Package", "GetAppInstallerInfo"))
82 | {
83 | var aiUri = GetAppInstallerInfoUri(Package.Current);
84 | if (aiUri != null)
85 | {
86 | result = aiUri.ToString();
87 | }
88 | else
89 | {
90 | result = "not present";
91 | }
92 | }
93 | else
94 | {
95 | result = "Not Available";
96 | }
97 |
98 | return result;
99 | }
100 |
101 | internal static string GetDotNetRuntimeInfo()
102 | {
103 | return typeof(object).Assembly.GetCustomAttribute().InformationalVersion;
104 | }
105 |
106 | [MethodImpl(MethodImplOptions.NoInlining)]
107 | private static Uri GetAppInstallerInfoUri(Package p)
108 | {
109 | var aiInfo = p.GetAppInstallerInfo();
110 | if (aiInfo != null)
111 | {
112 | return aiInfo.Uri;
113 | }
114 | return null;
115 | }
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/MyWPFApp/win.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/MyWPFApp/win.ico
--------------------------------------------------------------------------------
/MyWpfApp.Tests/MyWPFApp.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 | false
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/MyWpfApp.Tests/ThisAppInfoTest.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation.
2 | // Licensed under the MIT license.
3 |
4 | using NUnit.Framework;
5 | using MyWPFApp;
6 |
7 | namespace MyWPFApp.Tests
8 | {
9 | public class Tests
10 | {
11 | [SetUp]
12 | public void Setup()
13 | {
14 | var thisAppInfo = new ThisAppInfo();
15 | }
16 |
17 | [Test]
18 | public void GetDisplayName()
19 | {
20 | var displayName = ThisAppInfo.GetDisplayName();
21 | Assert.AreEqual("Not packaged", displayName);
22 | }
23 |
24 | [Test]
25 | public void GetAppInstallerUri()
26 | {
27 | var appInstallerUri = ThisAppInfo.GetAppInstallerUri();
28 |
29 | Assert.AreEqual("Not packaged", appInstallerUri);
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DevOps for Windows Desktop Apps Using GitHub Actions
2 |
3 | ### Create CI/CD workflows for WPF and Windows Forms Applications built on .NET Core 3.x
4 |
5 | This repo contains a sample application to demonstrate how to create CI/CD pipelines using [GitHub Actions](https://github.com/features/actions "GitHub Actions page").
6 |
7 | With GitHub Actions, you can quickly and easily automate your software workflows with CI/CD.
8 | * Integrate code changes directly into GitHub to speed up development cycles
9 | * Trigger builds to quickly identify breaking changes and create testable debug builds
10 | * Continuously run tests to identify and eliminate bugs, improving code quality
11 | * Automatically build, sign, package and deploy branches that pass CI
12 |
13 | Build, test, and deploy your code entirely within GitHub.
14 |
15 | | Workflow | Status |
16 | |----------|--------|
17 | | WPF - CI |  |
18 | | WPF - CD |  |
19 | | WPF - CI (.NET 6 experimental) | [](https://github.com/microsoft/github-actions-for-desktop-apps/actions/workflows/ci-net6-temp.yml) |
20 |
21 | ## Workflows
22 |
23 | To take advantage of GitHub Actions, workflows are defined in YAML files that are in the .github/workflows folder.
24 | In the project, there are two workflows defined:
25 |
26 | * .github/workflows/ci.yml
27 | * .github/workflows/cd.yml
28 |
29 | The ci.yml file defines the continuous integration workflow which is used to build, test, and create a package every time a developer pushes code to the repo.
30 |
31 | The benefits of kicking off a CI run on every push are multi-fold:
32 | * Quickly identify breaking changes
33 | * Create a testable debug build
34 | * Continuously run tests to identify and eliminate bugs, improving code quality
35 | * Keep workflow relatively lightweight by only testing configurations necessary to ensure good quality
36 |
37 | The cd.yml file defines our continuous delivery workflow used to build, sign, package and archive release assets for every configuration that is planned for release.
38 |
39 |
40 | ### ci.yml: Build, test, package, and save package artifacts.
41 |
42 | The CI workflow defines the Package.Identity.Name in the Windows Application Packaging project’s Package.appxmanifest to identify the application as "MyWPFApp.DevOpsDemo.Local." By suffixing the application name with ".Local," developers are able to install it side by side with other channels of the app.
43 | ```yaml
44 |
48 | ```
49 |
50 | On every push to the repo, take advantage of the [setup-dotnet](https://github.com/actions/setup-dotnet "Setup dotnet GitHub Action") GitHub Action and install the [dotnet core cli](https://github.com/dotnet/cli "DotNet Core CLI page") environment. Then add [MSBuild](https://github.com/microsoft/setup-msbuild "MSBuild GitHub Action page") to the PATH and execute unit tests using the [dotnet test](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-test "DotNet test page") runner console application.
51 | ```yaml
52 | - name: Install .NET Core
53 | uses: actions/setup-dotnet@v1
54 | with:
55 | dotnet-version: 3.1.100
56 |
57 | # Add MsBuild to the PATH: https://github.com/microsoft/setup-msbuild
58 | - name: Setup MSBuild.exe
59 | uses: microsoft/setup-msbuild@v1.0.0
60 |
61 | # Test
62 | - name: Execute Unit Tests
63 | run: dotnet test $env:Test_Project_Path
64 | ```
65 |
66 | As mentioned above, you can target multiple platforms by authoring the workflow file to define a build matrix, a set of different configurations that are each run in a fresh instance of a virtual environment by the [GitHub-hosted runner](https://help.github.com/en/actions/getting-started-with-github-actions/core-concepts-for-github-actions#github-hosted-runner "GitHub Hosted Runner page").
67 |
68 | In the continuous integration workflow, create a release build for x86 and x64 that runs on the latest windows OS installed on the GitHub-hosted runners. Then, define [environment variables](https://help.github.com/en/actions/configuring-and-managing-workflows/using-environment-variables "Configuring and Managing Workflows Using Environment Variables page") that are common to all the runs in the matrix such as the signing certificate name, the relative path to the solution file and the Windows Application Packaging project name.
69 | ```yaml
70 | strategy:
71 | matrix:
72 | targetplatform: [x86, x64]
73 |
74 | runs-on: windows-latest
75 |
76 | env:
77 | SigningCertificate: GitHubActionsDemo.pfx
78 | Solution_Path: MyWpfApp.sln
79 | Test_Project_Path: MyWpfApp.Tests\MyWpfApp.Tests.csproj
80 | Wpf_Project_Path: MyWpfApp\MyWpfApp.csproj
81 | Wap_Project_Directory: MyWpfApp.Package
82 | Wap_Project_Name: MyWpfApp.Package.wapproj
83 | ```
84 |
85 | Next, execute the unit tests in MYWPFApp.Tests by calling ‘donet test’.
86 | ```yaml
87 | # Test
88 | - name: Execute Unit Tests
89 | run: dotnet test $env:Test_Project_Path
90 | ```
91 |
92 | After executing the tests, restore the application while passing in the RuntimeIdentifier parameter in order to populate the obj folder with the appropriate platform dependencies for use during build.
93 | ```yaml
94 | # Restore the application
95 | - name: Restore the Wpf application to populate the obj folder
96 | run: msbuild $env:Solution_Path /t:Restore /p:Configuration=$env:Configuration /p:RuntimeIdentifier=$env:RuntimeIdentifier
97 | env:
98 | Configuration: Debug
99 | RuntimeIdentifier: win-${{ matrix.targetplatform }}
100 | ```
101 |
102 | Once the application has been restored, build and create the MSIX. Rather than build each project separately, simply build the solution, making sure to pass the target platform, configuration, build mode, whether to produce an app bundle, the signing certificate, and certificate password as parameters.
103 | ```yaml
104 | # Build the Windows Application Packaging project
105 | - name: Build the Windows Application Packaging Project (wapproj)
106 | run: msbuild $env:Solution_Path /p:Platform=$env:TargetPlatform /p:Configuration=$env:Configuration /p:UapAppxPackageBuildMode=$env:BuildMode /p:AppxBundle=$env:AppxBundle /p:PackageCertificateKeyFile=$env:SigningCertificate /p:PackageCertificatePassword=${{ secrets.Pfx_Key }}
107 | env:
108 | AppxBundle: Never
109 | BuildMode: SideLoadOnly
110 | Configuration: Release
111 | TargetPlatform: ${{ matrix.targetplatform }}
112 | ```
113 |
114 | Once the app package has been created, take advantage of the [upload-artifact](https://github.com/marketplace/actions/upload-artifact "upload-artifact GitHub Action page") GitHub Action to save the artifact. You have the option to download the artifact to test the build or upload the artifact to a website or file share to distribute the application.
115 | ```yaml
116 | # Upload the MSIX package: https://github.com/marketplace/actions/upload-artifact
117 | - name: Upload build artifacts
118 | uses: actions/upload-artifact@v1
119 | with:
120 | name: MSIX Package
121 | path: MyWpfApp.Package\AppPackages\
122 | ```
123 |
124 | To find the artifact, navigate to "Actions," select the workflow, then download the artifact on the right side of the window.
125 | 
126 |
127 |
128 | ### cd.yml: Build, package, and create a GitHub release for multiple channels
129 |
130 | In the CD workflow, you can build, package and distribute code built for multiple channels such as “Dev”, “Prod_Sideload” and “Prod_Store.” During every workflow run, the applications’ Package.Identity.Name, Package.Identity.Version and Package.Properties.DisplayName are changed according to which channel of the build matrix will be built.
131 | We use a Powershell script to overwrite these values in the Windows Application Packaging project's Package.appxmanifest. By doing so, we change the identity of the application to *MyWPFApp.DevOpsDemo.Dev*, *MyWPFApp.DevOpsDemo.ProdSideload*, or *MyWPFApp.DevOpsDemo.ProdStore* depending on which matrix channel is built, thus enabling multiple channels of the application.
132 | ```yaml
133 | # Update the appxmanifest before build by setting the per-channel values set in the matrix.
134 | - name: Update manifest version
135 | run: |
136 | [xml]$manifest = get-content ".\$env:Wap_Project_Directory\Package.appxmanifest"
137 | $manifest.Package.Identity.Version = "$env:NBGV_SimpleVersion.0"
138 | $manifest.Package.Identity.Name = "${{ matrix.MsixPackageId }}"
139 | $manifest.Package.Identity.Publisher = "${{ matrix.MsixPublisherId }}"
140 | $manifest.Package.Properties.DisplayName = "${{ matrix.MsixPackageDisplayName }}"
141 | $manifest.Package.Applications.Application.VisualElements.DisplayName = "${{ matrix.MsixPackageDisplayName }}"
142 | $manifest.save(".\$env:Wap_Project_Directory\Package.appxmanifest")
143 | ```
144 |
145 | On every push to the repo with a tag matching the pattern *, the workflow will build the solution, create a release and upload the release asset. For more information on how to configure a workflow to run on specific branches or tags, see [GitHub Workflow syntax for GitHub Actions - on..](https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#onpushpull_requestbranchestags "GitHub Workflow Syntax for GitHub Actions").
146 | ```yaml
147 | on:
148 | push:
149 | tags:
150 | - '*'
151 | ```
152 |
153 | To create a git `tag`, run the following commands on the branch you wish to release:
154 | ```cmd
155 | git tag 1.0.0.0
156 | git push origin --tags
157 | ```
158 |
159 | The above commands will add the tag "1.0.0.0" and then `push` the branch and tag to the repo. Learn more about [Git Tagging.](https://git-scm.com/book/en/v2/Git-Basics-Tagging "Basics of Git Tagging")
160 |
161 | Channels and environment variables used during the run are defined in the build matrix and will build and create app packages for development (Dev), production sideload (Prod_Sideload), and also production for the [Microsoft Store](https://www.microsoft.com/en-us/store/apps/windows "Microsoft Store home page") (Prod_Store). In this example, each channel is built for two configurations: x86 and x64. However, arm or arm64 are valid configurations as well.
162 |
163 | A build matrix can be created to execute jobs across multiple operating systems, build configurations or different supported versions of a programming language. With GitHub Actions, you can define incredibly complex build matrices that can generate up to 256 builds per run! Learn how to [configure a build matrix.](https://help.github.com/en/actions/configuring-and-managing-workflows/configuring-a-workflow#configuring-a-build-matrix "Learn how to configure a build matrix page")
164 | ```yaml
165 | jobs:
166 |
167 | build:
168 |
169 | strategy:
170 | matrix:
171 | channel: [Dev, Prod_Sideload, Prod_Store]
172 | targetPlatform: [x86, x64]
173 | include:
174 |
175 | # includes the following variables for the matrix leg matching Dev
176 | - channel: Dev
177 | ChannelName: Dev
178 | Configuration: Debug
179 | DistributionUrl: https://microsoft.github.io/github-actions-for-desktop-apps-distribution-dev
180 | MsixPackageId: MyWPFApp.DevOpsDemo.Dev
181 | MsixPublisherId: CN=GitHubActionsDemo
182 | MsixPackageDisplayName: MyWPFApp (Dev)
183 |
184 | # includes the following variables for the matrix leg matching Prod_Sideload
185 | - channel: Prod_Sideload
186 | Configuration: Release
187 | ChannelName: Prod_Sideload
188 | DistributionUrl: https://microsoft.github.io/github-actions-for-desktop-apps-distribution-prod
189 | MsixPackageId: MyWPFApp.DevOpsDemo.ProdSideload
190 | MsixPublisherId: CN=GitHubActionsDemo
191 | MsixPackageDisplayName: MyWPFApp (ProdSideload)
192 |
193 | # includes the following variables for the matrix leg matching Prod_Store
194 | - channel: Prod_Store
195 | Configuration: Release
196 | ChannelName: Prod_Store
197 | DistributionUrl:
198 | MsixPackageId: MyWPFApp.DevOpsDemo.ProdStore
199 | MsixPublisherId: CN=GitHubActionsDemo
200 | MsixPackageDisplayName: MyWPFApp (ProdStore)
201 | ```
202 | Just like the CI workflow, restore the solution.
203 | ```yaml
204 | # Restore the application
205 | - name: Restore the Wpf application to populate the obj folder
206 | run: msbuild $env:Solution_Path /t:Restore /p:Configuration=$env:Configuration /p:RuntimeIdentifier=$env:RuntimeIdentifier
207 | env:
208 | Configuration: Debug
209 | RuntimeIdentifier: win-${{ matrix.targetplatform }}
210 | ```
211 |
212 | This time, however, use GitHub’s ```if``` conditional to build and package the MSIX for Dev and Prod_Sideload (which requires an AppInstaller Uri and Signing Certificate) or for Prod_Store.
213 | We pass different parameters depending on which channel we are building for.
214 | ```yaml
215 | # Build the Windows Application Packaging project for Dev and Prod_Sideload
216 | - name: Build the Windows Application Packaging Project (wapproj) for ${{ matrix.ChannelName }}
217 | run: msbuild $env:Solution_Path /p:Platform=$env:TargetPlatform /p:Configuration=$env:Configuration /p:UapAppxPackageBuildMode=$env:BuildMode /p:AppxBundle=$env:AppxBundle /p:PackageCertificateKeyFile=$env:SigningCertificate /p:PackageCertificatePassword=${{ secrets.Pfx_Key }}
218 | if: matrix.ChannelName != 'Prod_Store'
219 | env:
220 | AppxBundle: Never
221 | AppInstallerUri: ${{ matrix.DistributionUrl }}
222 | BuildMode: SideLoadOnly
223 | Configuration: ${{ matrix.Configuration }}
224 | GenerateAppInstallerFile: True
225 | TargetPlatform: ${{ matrix.targetplatform }}
226 |
227 | # Build the Windows Application Packaging project for Prod_Store
228 | - name: Build the Windows Application Packaging Project (wapproj) for ${{ matrix.ChannelName }}
229 | run: msbuild $env:Solution_Path /p:Platform=$env:TargetPlatform /p:Configuration=$env:Configuration /p:UapAppxPackageBuildMode=$env:BuildMode /p:AppxBundle=$env:AppxBundle /p:GenerateAppInstallerFile=$env:GenerateAppInstallerFile /p:AppxPackageSigningEnabled=$env:AppxPackageSigningEnabled
230 | if: matrix.ChannelName == 'Prod_Store'
231 | env:
232 | AppxBundle: Never
233 | AppxPackageSigningEnabled: False
234 | BuildMode: StoreOnly
235 | Configuration: ${{ matrix.Configuration }}
236 | GenerateAppInstallerFile: False
237 | TargetPlatform: ${{ matrix.targetplatform }}
238 | ```
239 |
240 | Once the MSIX is created for each channel, the agent archives the AppPackages folder then creates a Release with the specified git release tag. The archive is uploaded to the release as an asset for storage or distribution.
241 | It’s important to note that release names must be unique or an error will be generated. This is why tag_name and release_name include the github reference, channel name and target platform.
242 | ```yaml
243 | # Create the release: https://github.com/actions/create-release
244 | - name: Create release
245 | id: create_release
246 | uses: actions/create-release@v1
247 | env:
248 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
249 | with:
250 | tag_name: ${{ github.ref}}.${{matrix.ChannelName}}.${{ matrix.targetplatform }}
251 | release_name: ${{ github.ref }}.${{ matrix.ChannelName }}.${{ matrix.targetplatform }}
252 | draft: false
253 | prerelease: false
254 |
255 | # Upload release asset: https://github.com/actions/upload-release-asset
256 | - name: Update release asset
257 | id: upload-release-asset
258 | uses: actions/upload-release-asset@v1
259 | env:
260 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
261 | with:
262 | upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
263 | asset_path: MyWpfApp.Package\AppPackages\AppPackages.zip
264 | asset_name: AppPackages.zip
265 | asset_content_type: application/zip
266 |
267 | ```
268 |
269 | To find the Release artifacts, navigate to the "Releases" link in the repo.
270 | 
271 |
272 | Find the release and asset location.
273 | 
274 |
275 | Creating channels for the application is a powerful way to create multiple distributions of an application in the same CD pipeline.
276 |
277 |
278 | ### Versioning
279 |
280 | In both workflows, one of the first things to do is create a version and store version information as environment variables. Having a different version for every push is especially important when a release is created as each release must have a unique release_name.
281 |
282 | The [Nerdbank.GitVersioning GitHub Action](https://github.com/AArnott/nbgv "Nerbank.GitVersioning GitHub Action page") sets the build version based on a combination of the included version.json file, and the git height of the version.
283 | ```yaml
284 | # Use Nerdbank.GitVersioning to set version variables: https://github.com/AArnott/nbgv
285 | - name: Use Nerdbank.GitVersioning to set version variables
286 | uses: aarnott/nbgv@v0.3
287 | with:
288 | setAllVars: true
289 | ```
290 |
291 | Once the action runs, a number of environment variables are available for use, such as:
292 | * NBGV_Version (e.g. 1.1.159.47562)
293 | * NBGV_SimpleVersion (e.g. 1.1.159)
294 | * NBGV_NuGetPackageVersion (e.g. 1.1.159-gcab9873dd7)
295 | * NBGV_ChocolateyPackageVersion
296 | * NBGV_NpmPackageVersion
297 |
298 | A list of all the environment variables available to use in the run are shown below.
299 | 
300 |
301 | See the [Nerdbank.GitVersioning](https://github.com/aarnott/nerdbank.gitversioning "Nerdbank.GitVersioning page") package for more information.
302 |
303 |
304 | ### Signing
305 | Avoid submitting certificates to the repo if at all possible to ensure security best practices. (Git ignores them by default.) To manage the safe handling of sensitive files like certificates, take advantage of [GitHub secrets](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets "GitHub Secrets page"), which allow the storage of sensitive information in the repository.
306 |
307 | First, generate a signing certificate in the Windows Application Packaging Project or add an existing signing certificate to the project. Next, use PowerShell to encode the .pfx file using Base64 encoding by running the following Powershell script to generate the output file.
308 | ```pwsh
309 | $pfx_cert = Get-Content '.\GitHubActionsDemo.pfx' -Encoding Byte
310 | [System.Convert]::ToBase64String($pfx_cert) | Out-File 'SigningCertificate_Encoded.txt'
311 | ```
312 |
313 | Open the output file, *SigningCertificate_Encoded.txt*, and copy the string inside. Finally, add the string to the repo as a GitHub secret and name it Base64_Encoded_Pfx. [Learn how to add a secret to the workflow.](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/virtual-environments-for-github-hosted-runners#creating-and-using-secrets-encrypted-variables "Creating and using secrets page")
314 | In the workflow, add a step to decode the secret, save the .pfx to the build agent, and package the application with the Windows Application Packaging project.
315 | ```yaml
316 | # Decode the Base64 encoded Pfx
317 | - name: Decode the Pfx
318 | run: |
319 | $pfx_cert_byte = [System.Convert]::FromBase64String("${{ secrets.Base64_Encoded_Pfx }}")
320 | $currentDirectory = Get-Location
321 | $certificatePath = Join-Path -Path $currentDirectory -ChildPath $env:Wap_Project_Directory -AdditionalChildPath $env:SigningCertificate
322 | [IO.File]::WriteAllBytes("$certificatePath", $pfx_cert_byte)
323 | ```
324 |
325 | Once the certificate is decoded and saved to the Windows Application Packaging Project, use it to sign the package during packaging making sure to pass the signing certificate's password, stored as a GitHub secret, to MSBuild as a parameter.
326 | ```yaml
327 | # Build the Windows Application Packaging project for Dev and Prod_Sideload
328 | - name: Build the Windows Application Packaging Project (wapproj) for ${{ matrix.ChannelName }}
329 | run: msbuild $env:Wap_Project_Directory/$env:Wap_Project_Name /p:Platform=$env:TargetPlatform /p:Configuration=$env:Configuration /p:UapAppxPackageBuildMode=$env:BuildMode /p:GenerateAppInstallerFile=$env:GenerateAppInstallerFile /p:AppInstallerUri=$env:AppInstallerUri /p:PackageCertificateKeyFile=$env:SigningCertificate /p:PackageCertificatePassword=${{ secrets.Pfx_Key }}
330 | if: ${{ matrix.ChannelName }} != Prod_Store
331 | env:
332 | AppInstallerUri: ${{ matrix.DistributionUrl }}
333 | BuildMode: SideLoadOnly
334 | Configuration: ${{ matrix.Configuration }}
335 | GenerateAppInstallerFile: True
336 | TargetPlatform: ${{ matrix.TargetPlatform }}
337 | ```
338 |
339 | Finally, to ensure the certificate doesn’t stay on the build machine, delete the .pfx.
340 | ```yaml
341 | # Remove the .pfx
342 | - name: Remove the .pfx
343 | run: Remove-Item -path $env:Wap_Project_Directory/$env:SigningCertificate
344 | if: ${{ matrix.ChannelName }} != Prod_Store
345 | ```
346 |
347 | ### Publisher Profiles
348 | Publisher Profiles allow developers to store publishing information on their WPF application such as the configuration, target runtime, and deployment mode (whether the application is self contained or framework dependent). These profiles can be easily referenced by the Windows Application Packaging project and used during build and packaging.
349 |
350 | To add a Publisher Profile to the WPF application, right-click the Wpf application and select “Publish.” In the Publish dialog, select 'New.' In the "Pick a publish target" dialog, choose the folder or file share to publish the app to and "Create Profile."
351 | 
352 |
353 | In the Publish dialog, click "Edit" to customize the profile settings.
354 | 
355 |
356 | Select the configuration, framework and runtime to target, then select whether the deployment mode should be "Framework Dependent" or "Self-contained."
357 | 
358 |
359 | Edit the profile name to reflect the settings by clicking "Rename" in the Publish dialog.
360 | 
361 |
362 | Finally, in the Windows Application Packaging project, add a reference to the Publish Profile.
363 | In the Solution Explorer, open MyWPFApp.Package and navigate to Applications. Click on MyWFPApp and, in the properties window, select Publishing Profile. The dropdown should be populated with the recently-created profile.
364 | 
365 |
366 | To ensure the settings were added correctly to MyWPFApp.Package, double click on the project to open the .wapproj file and scroll to the bottom to find the PublishProfile elements.
367 | 
368 |
369 | # Conclusion
370 | GitHub workflows that leverage GitHub Actions are a great way for developers to create and customize continuous integration and continuous deployment pipelines to build, test, package, publish and distribute their application from start to finish entirely in GitHub.
371 |
372 | To learn more about other GitHub Actions that you can add to your pipelines, take a look at the [GitHub Marketplace](https://github.com/marketplace?type=actions "GitHub Marketplace page"). For more information on GitHub Actions, check out the [GitHub Actions](https://github.com/features/actions "GitHub Actions home page") home page.
373 |
374 | We are always open to your feedback. Please feel free to email us at [devdeploymenttools@microsoft.com](mailto:devdeploymenttools@microsoft.com "Email us at devdeploymenttools at Microsoft.com").
375 |
376 | Our repo is open source and welcomes contributions and suggestions. Please see [Contributing.md](https://github.com/microsoft/github-actions-for-desktop-apps/blob/master/CONTRIBUTING.md "Contributing.md page") for more information on how to submit a PR to the repo.
377 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Security
4 |
5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
6 |
7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets Microsoft's [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)) of a security vulnerability, please report it to us as described below.
8 |
9 | ## Reporting Security Issues
10 |
11 | **Please do not report security vulnerabilities through public GitHub issues.**
12 |
13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report).
14 |
15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc).
16 |
17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
18 |
19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
20 |
21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
22 | * Full paths of source file(s) related to the manifestation of the issue
23 | * The location of the affected source code (tag/branch/commit or direct URL)
24 | * Any special configuration required to reproduce the issue
25 | * Step-by-step instructions to reproduce the issue
26 | * Proof-of-concept or exploit code (if possible)
27 | * Impact of the issue, including how an attacker might exploit the issue
28 |
29 | This information will help us triage your report more quickly.
30 |
31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs.
32 |
33 | ## Preferred Languages
34 |
35 | We prefer all communications to be in English.
36 |
37 | ## Policy
38 |
39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd).
40 |
41 |
42 |
--------------------------------------------------------------------------------
/doc/images/editToCustomizeSettings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/doc/images/editToCustomizeSettings.png
--------------------------------------------------------------------------------
/doc/images/findArtifact.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/doc/images/findArtifact.png
--------------------------------------------------------------------------------
/doc/images/myWpfApp.Package.Properties.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/doc/images/myWpfApp.Package.Properties.png
--------------------------------------------------------------------------------
/doc/images/pickAPublishTarget.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/doc/images/pickAPublishTarget.png
--------------------------------------------------------------------------------
/doc/images/profileSettings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/doc/images/profileSettings.png
--------------------------------------------------------------------------------
/doc/images/publishProfileComplete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/doc/images/publishProfileComplete.png
--------------------------------------------------------------------------------
/doc/images/releaseAssetLocation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/doc/images/releaseAssetLocation.png
--------------------------------------------------------------------------------
/doc/images/releases.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/doc/images/releases.png
--------------------------------------------------------------------------------
/doc/images/renameProfile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/doc/images/renameProfile.png
--------------------------------------------------------------------------------
/doc/images/versionEnvironmentVariables.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/github-actions-for-desktop-apps/fb81ac030181846f53b1c4a4cafae2c9394f3976/doc/images/versionEnvironmentVariables.png
--------------------------------------------------------------------------------
/version.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
3 | "publicReleaseRefSpec": [
4 | "^refs/heads/master$",
5 | "^refs/heads/develop$",
6 | "^refs/heads/rel/v\\d+\\.\\d+"
7 | ],
8 | "version": "1.1"
9 | }
10 |
--------------------------------------------------------------------------------