@react-native-windows/cli 0.80.0-preview.7 → 0.81.0-preview.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib-commonjs/commands/healthCheck/healthCheckList.js +1 -1
- package/lib-commonjs/commands/healthCheck/healthCheckList.js.map +1 -1
- package/lib-commonjs/e2etest/createRnwApp.test.d.ts +6 -0
- package/lib-commonjs/e2etest/createRnwApp.test.js +384 -0
- package/lib-commonjs/e2etest/createRnwApp.test.js.map +1 -0
- package/lib-commonjs/utils/deploy.js +1 -1
- package/lib-commonjs/utils/deploy.js.map +1 -1
- package/package.json +11 -11
- package/src/powershell/{WindowsStoreAppUtils.ps1 → WindowsStoreAppUtils.psm1} +465 -274
|
@@ -1,274 +1,465 @@
|
|
|
1
|
-
<#
|
|
2
|
-
Licensed to the Apache Software Foundation (ASF) under one
|
|
3
|
-
or more contributor license agreements. See the NOTICE file
|
|
4
|
-
distributed with this work for additional information
|
|
5
|
-
regarding copyright ownership. The ASF licenses this file
|
|
6
|
-
to you under the Apache License, Version 2.0 (the
|
|
7
|
-
"License"); you may not use this file except in compliance
|
|
8
|
-
with the License. You may obtain a copy of the License at
|
|
9
|
-
|
|
10
|
-
http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
-
|
|
12
|
-
Unless required by applicable law or agreed to in writing,
|
|
13
|
-
software distributed under the License is distributed on an
|
|
14
|
-
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
15
|
-
KIND, either express or implied. See the License for the
|
|
16
|
-
specific language governing permissions and limitations
|
|
17
|
-
under the License.
|
|
18
|
-
#>
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
{
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
return
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
if (!(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
{
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
{
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
function
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
$
|
|
272
|
-
$
|
|
273
|
-
|
|
274
|
-
|
|
1
|
+
<#
|
|
2
|
+
Licensed to the Apache Software Foundation (ASF) under one
|
|
3
|
+
or more contributor license agreements. See the NOTICE file
|
|
4
|
+
distributed with this work for additional information
|
|
5
|
+
regarding copyright ownership. The ASF licenses this file
|
|
6
|
+
to you under the Apache License, Version 2.0 (the
|
|
7
|
+
"License"); you may not use this file except in compliance
|
|
8
|
+
with the License. You may obtain a copy of the License at
|
|
9
|
+
|
|
10
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
|
|
12
|
+
Unless required by applicable law or agreed to in writing,
|
|
13
|
+
software distributed under the License is distributed on an
|
|
14
|
+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
15
|
+
KIND, either express or implied. See the License for the
|
|
16
|
+
specific language governing permissions and limitations
|
|
17
|
+
under the License.
|
|
18
|
+
#>
|
|
19
|
+
|
|
20
|
+
# SDL CE.10116 SECURITY FIX: Removed PowerShell injection vulnerabilities
|
|
21
|
+
# - Replaced Invoke-Expression with direct cmdlet invocation
|
|
22
|
+
# - Implemented parameterized ScriptBlock pattern for elevated execution
|
|
23
|
+
# - Added input validation for package IDs and paths
|
|
24
|
+
# Date: October 14, 2025
|
|
25
|
+
|
|
26
|
+
$code = @"
|
|
27
|
+
using System;
|
|
28
|
+
using System.Runtime.CompilerServices;
|
|
29
|
+
using System.Runtime.InteropServices;
|
|
30
|
+
namespace StoreAppRunner
|
|
31
|
+
{
|
|
32
|
+
public enum ActivateOptions
|
|
33
|
+
{
|
|
34
|
+
None = 0,
|
|
35
|
+
DesignMode = 0x1,
|
|
36
|
+
NoErrorUI = 0x2,
|
|
37
|
+
NoSplashScreen = 0x4
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
[ComImport]
|
|
41
|
+
[Guid("2e941141-7f97-4756-ba1d-9decde894a3d")]
|
|
42
|
+
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
43
|
+
public interface IApplicationActivationManager
|
|
44
|
+
{
|
|
45
|
+
IntPtr ActivateApplication([In] String appUserModelId, [In] String arguments, [In] ActivateOptions options, [Out] out UInt32 processId);
|
|
46
|
+
IntPtr ActivateForFile([In] String appUserModelId, [In] IntPtr itemArray, [In] String verb, [Out] out UInt32 processId);
|
|
47
|
+
IntPtr ActivateForProtocol([In] String appUserModelId, [In] IntPtr itemArray, [Out] out UInt32 processId);
|
|
48
|
+
}
|
|
49
|
+
[ComImport]
|
|
50
|
+
[Guid("45BA127D-10A8-46EA-8AB7-56EA9078943C")]
|
|
51
|
+
public class ApplicationActivationManager : IApplicationActivationManager
|
|
52
|
+
{
|
|
53
|
+
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
|
|
54
|
+
public extern IntPtr ActivateApplication([In] String appUserModelId, [In] String arguments, [In] ActivateOptions options, [Out] out UInt32 processId);
|
|
55
|
+
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
|
|
56
|
+
public extern IntPtr ActivateForFile([In] String appUserModelId, [In] IntPtr itemArray, [In] String verb, [Out] out UInt32 processId);
|
|
57
|
+
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
|
|
58
|
+
public extern IntPtr ActivateForProtocol([In] String appUserModelId, [In] IntPtr itemArray, [Out] out UInt32 processId);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
"@
|
|
62
|
+
|
|
63
|
+
#region Security Helper Functions
|
|
64
|
+
|
|
65
|
+
<#
|
|
66
|
+
.SYNOPSIS
|
|
67
|
+
Validates package identifier format to prevent injection attacks.
|
|
68
|
+
.DESCRIPTION
|
|
69
|
+
Ensures package ID contains only safe characters and matches expected format.
|
|
70
|
+
SDL CE.10116 compliance - prevents PowerShell injection via package names.
|
|
71
|
+
#>
|
|
72
|
+
function Validate-PackageIdentifier {
|
|
73
|
+
param(
|
|
74
|
+
[Parameter(Mandatory=$true)]
|
|
75
|
+
[string]$PackageId
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
# Valid format: alphanumeric, dots, hyphens, underscores only
|
|
79
|
+
if ($PackageId -notmatch '^[a-zA-Z0-9\.\-_]+$') {
|
|
80
|
+
throw "Invalid package identifier format. Only alphanumeric characters, dots, hyphens, and underscores are allowed."
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
# Prevent common injection patterns
|
|
84
|
+
$dangerousPatterns = @(';', '|', '&', '$', '`', '<', '>', "`n", "`r", '(', ')', '{', '}')
|
|
85
|
+
foreach ($pattern in $dangerousPatterns) {
|
|
86
|
+
if ($PackageId.Contains($pattern)) {
|
|
87
|
+
throw "Package identifier contains forbidden characters: $pattern"
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return $true
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
<#
|
|
95
|
+
.SYNOPSIS
|
|
96
|
+
Validates and canonicalizes script path to prevent path traversal attacks.
|
|
97
|
+
.DESCRIPTION
|
|
98
|
+
Ensures path is a valid .ps1 file and resolves to canonical path.
|
|
99
|
+
SDL CE.10116 compliance - prevents path injection attacks.
|
|
100
|
+
#>
|
|
101
|
+
function Validate-ScriptPath {
|
|
102
|
+
param(
|
|
103
|
+
[Parameter(Mandatory=$true)]
|
|
104
|
+
[string]$Path
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
# Check file exists
|
|
108
|
+
if (!(Test-Path $Path -PathType Leaf)) {
|
|
109
|
+
throw "Script path does not exist: $Path"
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
# Check .ps1 extension
|
|
113
|
+
if ([System.IO.Path]::GetExtension($Path) -ne '.ps1') {
|
|
114
|
+
throw "Path must reference a PowerShell script (.ps1)"
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
# Get canonical path (prevents ../ traversal)
|
|
118
|
+
$canonicalPath = [System.IO.Path]::GetFullPath($Path)
|
|
119
|
+
|
|
120
|
+
return $canonicalPath
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
<#
|
|
124
|
+
.SYNOPSIS
|
|
125
|
+
Executes a ScriptBlock with optional elevation using parameterized approach.
|
|
126
|
+
.DESCRIPTION
|
|
127
|
+
SDL CE.10116 compliant - uses ScriptBlock with ArgumentList instead of string concatenation.
|
|
128
|
+
Prevents PowerShell injection attacks by properly isolating parameters.
|
|
129
|
+
#>
|
|
130
|
+
function Invoke-ElevatedScriptBlock {
|
|
131
|
+
param(
|
|
132
|
+
[Parameter(Mandatory=$true)]
|
|
133
|
+
[ScriptBlock]$ScriptBlock,
|
|
134
|
+
|
|
135
|
+
[Parameter(Mandatory=$false)]
|
|
136
|
+
[object[]]$ArgumentList = @()
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
if (!(IsElevated)) {
|
|
140
|
+
# Serialize ScriptBlock and arguments for elevated execution
|
|
141
|
+
$encodedCommand = [Convert]::ToBase64String(
|
|
142
|
+
[System.Text.Encoding]::Unicode.GetBytes($ScriptBlock.ToString())
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
$encodedArgs = [Convert]::ToBase64String(
|
|
146
|
+
[System.Text.Encoding]::Unicode.GetBytes(
|
|
147
|
+
($ArgumentList | ConvertTo-Json -Compress -Depth 10)
|
|
148
|
+
)
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
# Create secure argument list (no string interpolation)
|
|
152
|
+
$startArgs = @(
|
|
153
|
+
'-NoProfile',
|
|
154
|
+
'-NonInteractive',
|
|
155
|
+
'-Command',
|
|
156
|
+
"& ([ScriptBlock]::Create([System.Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('$encodedCommand')))) @(ConvertFrom-Json ([System.Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('$encodedArgs'))))"
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
$process = Start-Process PowerShell -ArgumentList $startArgs `
|
|
160
|
+
-Verb RunAs -Wait -PassThru -WindowStyle Hidden -ErrorAction Stop
|
|
161
|
+
|
|
162
|
+
if ($process.ExitCode -ne 0) {
|
|
163
|
+
throw "Elevated command failed with exit code $($process.ExitCode)"
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
# Already elevated, execute directly with splatting
|
|
168
|
+
& $ScriptBlock @ArgumentList
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
#endregion
|
|
173
|
+
|
|
174
|
+
#region Core Functions
|
|
175
|
+
|
|
176
|
+
<#
|
|
177
|
+
.SYNOPSIS
|
|
178
|
+
Uninstalls an AppX package by package identifier.
|
|
179
|
+
.DESCRIPTION
|
|
180
|
+
SDL CE.10116 FIX: Replaced Invoke-Expression with direct Remove-AppxPackage cmdlet.
|
|
181
|
+
Uses parameterized ScriptBlock for elevated execution.
|
|
182
|
+
#>
|
|
183
|
+
function Uninstall-App {
|
|
184
|
+
param(
|
|
185
|
+
[Parameter(Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)]
|
|
186
|
+
[string] $ID <# package.appxmanifest//Identity@name #>
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
# SDL FIX: Validate package ID to prevent injection
|
|
190
|
+
Validate-PackageIdentifier -PackageId $ID | Out-Null
|
|
191
|
+
|
|
192
|
+
$package = Get-AppxPackage $ID
|
|
193
|
+
|
|
194
|
+
if($package) {
|
|
195
|
+
$pfn = $package.PackageFullName
|
|
196
|
+
|
|
197
|
+
# SDL FIX: Direct cmdlet invocation instead of Invoke-Expression
|
|
198
|
+
try {
|
|
199
|
+
Remove-AppxPackage $pfn -ErrorAction Stop
|
|
200
|
+
} catch {
|
|
201
|
+
# SDL FIX: Use parameterized ScriptBlock for elevation
|
|
202
|
+
$scriptBlock = {
|
|
203
|
+
param($PackageFullName)
|
|
204
|
+
Remove-AppxPackage $PackageFullName -ErrorAction Stop
|
|
205
|
+
}
|
|
206
|
+
Invoke-ElevatedScriptBlock -ScriptBlock $scriptBlock -ArgumentList @($pfn)
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
#
|
|
212
|
+
# Checks whether the machine is missing a valid developer license.
|
|
213
|
+
#
|
|
214
|
+
function CheckIfNeedDeveloperLicense
|
|
215
|
+
{
|
|
216
|
+
$Result = $true
|
|
217
|
+
try
|
|
218
|
+
{
|
|
219
|
+
$Result = (Get-WindowsDeveloperLicense | Where-Object { $_.IsValid }).Count -eq 0
|
|
220
|
+
}
|
|
221
|
+
catch {}
|
|
222
|
+
|
|
223
|
+
return $Result
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function IsElevated {
|
|
227
|
+
return [bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-32-544");
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
<#
|
|
231
|
+
.SYNOPSIS
|
|
232
|
+
Enables developer mode by setting registry keys.
|
|
233
|
+
.DESCRIPTION
|
|
234
|
+
SDL CE.10116 FIX: Replaced Invoke-Expression-MayElevate with direct cmdlet calls
|
|
235
|
+
and parameterized ScriptBlock for elevation.
|
|
236
|
+
#>
|
|
237
|
+
function EnableDevmode {
|
|
238
|
+
$RegistryKeyPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock"
|
|
239
|
+
|
|
240
|
+
# Create registry key if it doesn't exist
|
|
241
|
+
if (-not(Test-Path -Path $RegistryKeyPath)) {
|
|
242
|
+
if (!(IsElevated)) {
|
|
243
|
+
$scriptBlock = {
|
|
244
|
+
param($Path)
|
|
245
|
+
New-Item -Path $Path -ItemType Directory -Force | Out-Null
|
|
246
|
+
}
|
|
247
|
+
Invoke-ElevatedScriptBlock -ScriptBlock $scriptBlock -ArgumentList @($RegistryKeyPath)
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
New-Item -Path $RegistryKeyPath -ItemType Directory -Force | Out-Null
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
# SDL FIX: Direct cmdlet invocation for AllowDevelopmentWithoutDevLicense
|
|
255
|
+
$value = Get-ItemProperty -Path $RegistryKeyPath -Name AllowDevelopmentWithoutDevLicense -ErrorAction SilentlyContinue
|
|
256
|
+
if (($value -eq $null) -or ($value.AllowDevelopmentWithoutDevLicense -ne 1)) {
|
|
257
|
+
if (!(IsElevated)) {
|
|
258
|
+
$scriptBlock = {
|
|
259
|
+
param($Path, $Name, $Value)
|
|
260
|
+
Set-ItemProperty -Path $Path -Name $Name -Value $Value -ErrorAction Stop
|
|
261
|
+
}
|
|
262
|
+
Invoke-ElevatedScriptBlock -ScriptBlock $scriptBlock `
|
|
263
|
+
-ArgumentList @($RegistryKeyPath, 'AllowDevelopmentWithoutDevLicense', 1)
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
Set-ItemProperty -Path $RegistryKeyPath -Name AllowDevelopmentWithoutDevLicense -Value 1 -ErrorAction Stop
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
# SDL FIX: Direct cmdlet invocation for AllowAllTrustedApps
|
|
271
|
+
$value = Get-ItemProperty -Path $RegistryKeyPath -Name AllowAllTrustedApps -ErrorAction SilentlyContinue
|
|
272
|
+
if (($value -eq $null) -or ($value.AllowAllTrustedApps -ne 1)) {
|
|
273
|
+
if (!(IsElevated)) {
|
|
274
|
+
$scriptBlock = {
|
|
275
|
+
param($Path, $Name, $Value)
|
|
276
|
+
Set-ItemProperty -Path $Path -Name $Name -Value $Value -ErrorAction Stop
|
|
277
|
+
}
|
|
278
|
+
Invoke-ElevatedScriptBlock -ScriptBlock $scriptBlock `
|
|
279
|
+
-ArgumentList @($RegistryKeyPath, 'AllowAllTrustedApps', 1)
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
Set-ItemProperty -Path $RegistryKeyPath -Name AllowAllTrustedApps -Value 1 -ErrorAction Stop
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
#
|
|
288
|
+
# Checks whether the package certificate must be installed on the machine.
|
|
289
|
+
#
|
|
290
|
+
function CheckIfNeedInstallCertificate
|
|
291
|
+
{
|
|
292
|
+
param(
|
|
293
|
+
[Parameter(Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)]
|
|
294
|
+
[string] $ScriptDir <# Full path to the dir where Add-AppDevPackage.ps1 is stored #>
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
$PackagePath = Get-ChildItem (Join-Path $ScriptDir "*.appx") | Where-Object { $_.Mode -NotMatch "d" }
|
|
298
|
+
if ($PackagePath -eq $null)
|
|
299
|
+
{
|
|
300
|
+
$PackagePath = Get-ChildItem (Join-Path $ScriptDir "*.msix") | Where-Object { $_.Mode -NotMatch "d" }
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
$BundlePath = Get-ChildItem (Join-Path $ScriptDir "*.appxbundle") | Where-Object { $_.Mode -NotMatch "d" }
|
|
304
|
+
if ($BundlePath -eq $null)
|
|
305
|
+
{
|
|
306
|
+
$BundlePath = Get-ChildItem (Join-Path $ScriptDir "*.msixbundle") | Where-Object { $_.Mode -NotMatch "d" }
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
# There must be exactly 1 package/bundle
|
|
310
|
+
if (($PackagePath.Count + $BundlePath.Count) -lt 1)
|
|
311
|
+
{
|
|
312
|
+
Throw "The app package has not been found at dir $ScriptDir"
|
|
313
|
+
}
|
|
314
|
+
if (($PackagePath.Count + $BundlePath.Count) -gt 1)
|
|
315
|
+
{
|
|
316
|
+
Throw "To many app packages have been found at dir $ScriptDir"
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if ($PackagePath.Count -ne 1) # there is *.appxbundle
|
|
320
|
+
{
|
|
321
|
+
$PackagePath = $BundlePath
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
$PackageSignature = (Get-AuthenticodeSignature $PackagePath)
|
|
325
|
+
$Valid = ($PackageSignature -and $PackageSignature.Status -eq "Valid")
|
|
326
|
+
return (-not $Valid)
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
<#
|
|
330
|
+
.SYNOPSIS
|
|
331
|
+
Installs an app package using Add-AppDevPackage.ps1 script.
|
|
332
|
+
.DESCRIPTION
|
|
333
|
+
SDL CE.10116 FIX: Replaced Invoke-Expression with call operator (&) and
|
|
334
|
+
parameterized ScriptBlock for elevated execution.
|
|
335
|
+
#>
|
|
336
|
+
function Install-App {
|
|
337
|
+
param(
|
|
338
|
+
[Parameter(Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)]
|
|
339
|
+
[string] $Path, <# Full path to Add-AppDevPackage.ps1 #>
|
|
340
|
+
[switch] $Force = $false
|
|
341
|
+
)
|
|
342
|
+
|
|
343
|
+
# SDL FIX: Validate script path
|
|
344
|
+
$Path = Validate-ScriptPath -Path $Path
|
|
345
|
+
|
|
346
|
+
$needInstallCertificate = CheckIfNeedInstallCertificate (Join-Path $Path "..")
|
|
347
|
+
|
|
348
|
+
if (!$Force -and ((CheckIfNeedDeveloperLicense) -or ($needInstallCertificate)))
|
|
349
|
+
{
|
|
350
|
+
# SDL FIX: Use call operator (&) instead of Invoke-Expression
|
|
351
|
+
# No user input in path (validated above), so safe to execute
|
|
352
|
+
& $Path
|
|
353
|
+
}
|
|
354
|
+
else
|
|
355
|
+
{
|
|
356
|
+
# SDL FIX: Use parameterized ScriptBlock for elevation
|
|
357
|
+
if (!(IsElevated)) {
|
|
358
|
+
$scriptBlock = {
|
|
359
|
+
param($ScriptPath)
|
|
360
|
+
& $ScriptPath -Force
|
|
361
|
+
}
|
|
362
|
+
Invoke-ElevatedScriptBlock -ScriptBlock $scriptBlock -ArgumentList @($Path)
|
|
363
|
+
}
|
|
364
|
+
else {
|
|
365
|
+
& $Path -Force
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
function Install-AppFromDirectory {
|
|
371
|
+
param(
|
|
372
|
+
[Parameter(Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)]
|
|
373
|
+
[string] $Path <# Full path to actual AppxManifest.xml #>
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
Add-AppxPackage -Path $Path -Register -ForceApplicationShutdown
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
function Install-AppFromAppx {
|
|
380
|
+
param(
|
|
381
|
+
[Parameter(Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)]
|
|
382
|
+
[string] $Path <# Full path to actual .appx #>
|
|
383
|
+
)
|
|
384
|
+
|
|
385
|
+
Add-AppxPackage -Path $Path -ForceApplicationShutdown
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
function Start-Locally {
|
|
389
|
+
param(
|
|
390
|
+
[Parameter(Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)]
|
|
391
|
+
[string] $ID, <# package.appxmanifest//Identity@name #>
|
|
392
|
+
|
|
393
|
+
[Parameter(Mandatory=$false, Position=1, ValueFromPipelineByPropertyName=$true)]
|
|
394
|
+
[string[]] $argv
|
|
395
|
+
)
|
|
396
|
+
|
|
397
|
+
# SDL FIX: Validate package ID
|
|
398
|
+
Validate-PackageIdentifier -PackageId $ID | Out-Null
|
|
399
|
+
|
|
400
|
+
$package = Get-AppxPackage $ID
|
|
401
|
+
$manifest = Get-appxpackagemanifest $package
|
|
402
|
+
$applicationUserModelId = $package.PackageFamilyName + "!" + $manifest.package.applications.application.id
|
|
403
|
+
|
|
404
|
+
add-type -TypeDefinition $code
|
|
405
|
+
$appActivator = new-object StoreAppRunner.ApplicationActivationManager
|
|
406
|
+
if ($argv.Count -gt 0) {
|
|
407
|
+
$args = [system.String]::Join(" ", $argv)
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
try {
|
|
411
|
+
$appActivator.ActivateApplication($applicationUserModelId,$args,[StoreAppRunner.ActivateOptions]::None,[ref]0) | Out-Null
|
|
412
|
+
} catch {
|
|
413
|
+
$log = Get-EventLog 'Application' -EntryType Error -Message "*$ID*" -Newest 1
|
|
414
|
+
if ($log -ne $null) {
|
|
415
|
+
Write-Error $log.Message
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
function Map-PackageNameToPackage {
|
|
421
|
+
param([Parameter(Mandatory=$true)] [string]$DependenciesPath)
|
|
422
|
+
$mapP2N = @{};
|
|
423
|
+
[Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.Zipfile') | Out-Null;
|
|
424
|
+
foreach ($package in (gci $DependenciesPath)) {
|
|
425
|
+
$archive = [System.IO.Compression.Zipfile]::OpenRead($package.FullName);
|
|
426
|
+
$packageManifestReader = New-Object System.IO.StreamReader($archive.GetEntry('AppxManifest.xml').Open());
|
|
427
|
+
$manifest = [xml]($packageManifestReader.ReadToEnd());
|
|
428
|
+
$mapP2N[$manifest.Package.Identity.Name] = $package;
|
|
429
|
+
}
|
|
430
|
+
return $mapP2N;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
function Install-AppDependencies {
|
|
434
|
+
param(
|
|
435
|
+
[Parameter(Mandatory=$true)] [string]$AppxManifestPath,
|
|
436
|
+
[Parameter(Mandatory=$true)] [string]$AppPackagePath,
|
|
437
|
+
[Parameter(Mandatory=$true)] [string]$Architecture
|
|
438
|
+
)
|
|
439
|
+
|
|
440
|
+
$xml=[xml] (gc $AppxManifestPath);
|
|
441
|
+
$packageNamesToInstall = $xml.Package.Dependencies.PackageDependency |
|
|
442
|
+
Where-Object {
|
|
443
|
+
$installed = Get-AppxPackage $_.Name | Where-Object -Property Architecture -EQ -Value $Architecture;
|
|
444
|
+
$installed -eq $null -or $installed.Version -lt $_.MinVersion
|
|
445
|
+
} |
|
|
446
|
+
% { $_.Name };
|
|
447
|
+
$map = Map-PackageNameToPackage $AppPackagePath\Dependencies\$Architecture
|
|
448
|
+
$packagePaths = $packageNamesToInstall | % { $map[$_] }
|
|
449
|
+
$packagePaths | % { Add-AppxPackage -Path $_ }
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
#endregion
|
|
453
|
+
|
|
454
|
+
# Export functions
|
|
455
|
+
Export-ModuleMember -Function @(
|
|
456
|
+
'Uninstall-App',
|
|
457
|
+
'EnableDevmode',
|
|
458
|
+
'CheckIfNeedDeveloperLicense',
|
|
459
|
+
'CheckIfNeedInstallCertificate',
|
|
460
|
+
'Install-App',
|
|
461
|
+
'Install-AppFromDirectory',
|
|
462
|
+
'Install-AppFromAppx',
|
|
463
|
+
'Start-Locally',
|
|
464
|
+
'Install-AppDependencies'
|
|
465
|
+
)
|