1
+ [CmdletBinding ()]
2
+ param ([Parameter (Mandatory = $true )]
3
+ [string ]$buildNumber )
4
+
5
+ # Ensure the error action preference is set to the default for PowerShell3, 'Stop'
6
+ $ErrorActionPreference = ' Stop'
7
+
8
+ # Constants
9
+ $WindowsSDKOptions = @ (" OptionId.UWPCpp" )
10
+ $WindowsSDKRegPath = " HKLM:\Software\Microsoft\Windows Kits\Installed Roots"
11
+ $WindowsSDKRegRootKey = " KitsRoot10"
12
+ $WindowsSDKVersion = " 10.0.$buildNumber .0"
13
+ $WindowsSDKInstalledRegPath = " $WindowsSDKRegPath \$WindowsSDKVersion \Installed Options"
14
+ $StrongNameRegPath = " HKLM:\SOFTWARE\Microsoft\StrongName\Verification"
15
+ $PublicKeyTokens = @ (" 31bf3856ad364e35" )
16
+
17
+ function Download-File {
18
+ param ([string ] $outDir ,
19
+ [string ] $downloadUrl ,
20
+ [string ] $downloadName )
21
+
22
+ $downloadPath = Join-Path $outDir " $downloadName .download"
23
+ $downloadDest = Join-Path $outDir $downloadName
24
+ $downloadDestTemp = Join-Path $outDir " $downloadName .tmp"
25
+
26
+ Write-Host - NoNewline " Downloading $downloadName ..."
27
+
28
+ try {
29
+ $webclient = new-object System.Net.WebClient
30
+ $webclient.DownloadFile ($downloadUrl , $downloadPath )
31
+ }
32
+ catch [System.Net.WebException ] {
33
+ Write-Host
34
+ Write-Warning " Failed to fetch updated file from $downloadUrl "
35
+ if (! (Test-Path $downloadDest )) {
36
+ throw " $downloadName was not found at $downloadDest "
37
+ }
38
+ else {
39
+ Write-Warning " $downloadName may be out of date"
40
+ }
41
+ }
42
+
43
+ Unblock-File $downloadPath
44
+
45
+ $downloadDestTemp = $downloadPath ;
46
+
47
+ # Delete and rename to final dest
48
+ if (Test-Path - PathType Container $downloadDest ) {
49
+ [System.IO.Directory ]::Delete($downloadDest , $true )
50
+ }
51
+
52
+ Move-Item - Force $downloadDestTemp $downloadDest
53
+ Write-Host " Done"
54
+
55
+ return $downloadDest
56
+ }
57
+
58
+ function Get-ISODriveLetter {
59
+ param ([string ] $isoPath )
60
+
61
+ $diskImage = Get-DiskImage - ImagePath $isoPath
62
+ if ($diskImage ) {
63
+ $volume = Get-Volume - DiskImage $diskImage
64
+
65
+ if ($volume ) {
66
+ $driveLetter = $volume.DriveLetter
67
+ if ($driveLetter ) {
68
+ $driveLetter += " :"
69
+ return $driveLetter
70
+ }
71
+ }
72
+ }
73
+
74
+ return $null
75
+ }
76
+
77
+ function Mount-ISO {
78
+ param ([string ] $isoPath )
79
+
80
+ # Check if image is already mounted
81
+ $isoDrive = Get-ISODriveLetter $isoPath
82
+
83
+ if (! $isoDrive ) {
84
+ Mount-DiskImage - ImagePath $isoPath - StorageType ISO | Out-Null
85
+ }
86
+
87
+ $isoDrive = Get-ISODriveLetter $isoPath
88
+ Write-Verbose " $isoPath mounted to ${isoDrive} :"
89
+ }
90
+
91
+ function Dismount-ISO {
92
+ param ([string ] $isoPath )
93
+
94
+ $isoDrive = (Get-DiskImage - ImagePath $isoPath | Get-Volume ).DriveLetter
95
+
96
+ if ($isoDrive ) {
97
+ Write-Verbose " $isoPath dismounted"
98
+ Dismount-DiskImage - ImagePath $isoPath | Out-Null
99
+ }
100
+ }
101
+
102
+ function Disable-StrongName {
103
+ param ([string ] $publicKeyToken = " *" )
104
+
105
+ reg ADD " HKLM\SOFTWARE\Microsoft\StrongName\Verification\*,$publicKeyToken " / f | Out-Null
106
+ if ($env: PROCESSOR_ARCHITECTURE -eq " AMD64" ) {
107
+ reg ADD " HKLM\SOFTWARE\Wow6432Node\Microsoft\StrongName\Verification\*,$publicKeyToken " / f | Out-Null
108
+ }
109
+ }
110
+
111
+ function Test-Admin {
112
+ $identity = [Security.Principal.WindowsIdentity ]::GetCurrent()
113
+ $principal = New-Object Security.Principal.WindowsPrincipal $identity
114
+ $principal.IsInRole ([Security.Principal.WindowsBuiltInRole ]::Administrator)
115
+ }
116
+
117
+ function Test-RegistryPathAndValue {
118
+ param (
119
+ [parameter (Mandatory = $true )]
120
+ [ValidateNotNullOrEmpty ()]
121
+ [string ] $path ,
122
+ [parameter (Mandatory = $true )]
123
+ [ValidateNotNullOrEmpty ()]
124
+ [string ] $value )
125
+
126
+ try {
127
+ if (Test-Path $path ) {
128
+ Get-ItemProperty - Path $path | Select-Object - ExpandProperty $value - ErrorAction Stop | Out-Null
129
+ return $true
130
+ }
131
+ }
132
+ catch {
133
+ }
134
+
135
+ return $false
136
+ }
137
+
138
+ function Test-InstallWindowsSDK {
139
+ $retval = $true
140
+
141
+ if (Test-RegistryPathAndValue - Path $WindowsSDKRegPath - Value $WindowsSDKRegRootKey ) {
142
+ # A Windows SDK is installed
143
+ # Is an SDK of our version installed with the options we need?
144
+ if (Test-RegistryPathAndValue - Path $WindowsSDKInstalledRegPath - Value " $WindowsSDKOptions " ) {
145
+ # It appears we have what we need. Double check the disk
146
+ $sdkRoot = Get-ItemProperty - Path $WindowsSDKRegPath | Select-Object - ExpandProperty $WindowsSDKRegRootKey
147
+ if ($sdkRoot ) {
148
+ if (Test-Path $sdkRoot ) {
149
+ $refPath = Join-Path $sdkRoot " References\$WindowsSDKVersion "
150
+ if (Test-Path $refPath ) {
151
+ $umdPath = Join-Path $sdkRoot " UnionMetadata\$WindowsSDKVersion "
152
+ if (Test-Path $umdPath ) {
153
+ # Pretty sure we have what we need
154
+ $retval = $false
155
+ }
156
+ }
157
+ }
158
+ }
159
+ }
160
+ }
161
+
162
+ return $retval
163
+ }
164
+
165
+ function Test-InstallStrongNameHijack {
166
+ foreach ($publicKeyToken in $PublicKeyTokens ) {
167
+ $key = " $StrongNameRegPath \*,$publicKeyToken "
168
+ if (! (Test-Path $key )) {
169
+ return $true
170
+ }
171
+ }
172
+
173
+ return $false
174
+ }
175
+
176
+ Write-Host - NoNewline " Checking for installed Windows SDK $WindowsSDKVersion ..."
177
+ $InstallWindowsSDK = Test-InstallWindowsSDK
178
+ if ($InstallWindowsSDK ) {
179
+ Write-Host " Installation required"
180
+ }
181
+ else {
182
+ Write-Host " INSTALLED"
183
+ }
184
+
185
+ $StrongNameHijack = Test-InstallStrongNameHijack
186
+ Write-Host - NoNewline " Checking if StrongName bypass required..."
187
+
188
+ if ($StrongNameHijack ) {
189
+ Write-Host " REQUIRED"
190
+ }
191
+ else {
192
+ Write-Host " Done"
193
+ }
194
+
195
+ if ($StrongNameHijack -or $InstallWindowsSDK ) {
196
+ if (! (Test-Admin )) {
197
+ Write-Host
198
+ throw " ERROR: Elevation required"
199
+ }
200
+ }
201
+
202
+ if ($InstallWindowsSDK ) {
203
+ # Static(ish) link for Windows SDK
204
+ # Note: there is a delay from Windows SDK announcements to availability via the static link
205
+ $uri = " https://software-download.microsoft.com/download/sg/Windows_InsiderPreview_SDK_en-us_$ ( $buildNumber ) _1.iso" ;
206
+
207
+ if ($null -eq $env: TEMP ) {
208
+ $env: TEMP = Join-Path $env: SystemDrive ' temp'
209
+ }
210
+
211
+ $winsdkTempDir = Join-Path $env: TEMP " WindowsSDK"
212
+
213
+ if (! [System.IO.Directory ]::Exists($winsdkTempDir )) {
214
+ [void ][System.IO.Directory ]::CreateDirectory($winsdkTempDir )
215
+ }
216
+
217
+ $file = " winsdk_$buildNumber .iso"
218
+
219
+ Write-Verbose " Getting WinSDK from $uri "
220
+ $downloadFile = Download- File $winsdkTempDir $uri $file
221
+
222
+ # TODO Check if zip, exe, iso, etc.
223
+ try {
224
+ Write-Host - NoNewline " Mounting ISO $file ..."
225
+ Mount-ISO $downloadFile
226
+ Write-Host " Done"
227
+
228
+ $isoDrive = Get-ISODriveLetter $downloadFile
229
+
230
+ if (Test-Path $isoDrive ) {
231
+ Write-Host - NoNewLine " Installing WinSDK..."
232
+
233
+ $setupPath = Join-Path " $isoDrive " " WinSDKSetup.exe"
234
+ Start-Process - Wait $setupPath " /features $WindowsSDKOptions /q"
235
+ Write-Host " Done"
236
+ }
237
+ else {
238
+ throw " Could not find mounted ISO at ${isoDrive} "
239
+ }
240
+ }
241
+ finally {
242
+ Write-Host - NoNewline " Dismounting ISO $file ..."
243
+ # Dismount-ISO $downloadFile
244
+ Write-Host " Done"
245
+ }
246
+ }
247
+
248
+ if ($StrongNameHijack ) {
249
+ Write-Host - NoNewline " Disabling StrongName for Windows SDK..."
250
+
251
+ foreach ($key in $PublicKeyTokens ) {
252
+ Disable-StrongName $key
253
+ }
254
+
255
+ Write-Host " Done"
256
+ }
0 commit comments