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