1
Find-MSBuildnull2 function Find-MSBuild
3 {
4 [CmdletBinding()]
5
6 Param([Parameter(Mandatory=$true)]
7 [ref]$VCVersion,
8 [Parameter(Mandatory=$true)]
9 $MSToolsVersion,
10 [Parameter(Mandatory=$true)]
11 [ref]$Toolset,
12 [Parameter(Mandatory=$true)]
13 [xml]$configInfo)
14
15 $msbuildexe=""
16 $VisualStudioVersion=$VCVersion.Value
17 $Toolsetv=$Toolset.Value
18
19 $WSDK71Set="Windows7.1SDK"
20 Write-Debug "VCVersion=$VCVersionv $env:VisualStudioVersion"
21 [int]$toolsnum=0
22 #
23 # Determine VisualStudioVersion
24 #
25 if (("$VisualStudioVersion" -eq "") -And ($configInfo -ne $null)) {
26 $VisualStudioVersion=$configInfo.Configuration.vcversion
27 }
28 if ("$VisualStudioVersion" -eq "") {
29 $VisualStudioVersion = $env:VisualStudioVersion # VC11 or later version of C++ command prompt sets this variable
30 }
31 if ("$VisualStudioVersion" -eq "") {
32 if ("${env:WindowsSDKVersionOverride}" -eq "v7.1") { # SDK7.1+ command prompt
33 $VisualStudioVersion = "10.0"
34 } elseif ("${env:VCInstallDir}" -ne "") { # C++ command prompt
35 if ("${env:VCInstallDir}" -match "Visual Studio\s*(\S+)\\VC\\$") {
36 $VisualStudioVersion = $matches[1]
37 }
38 }
39 }
40 $refnum=""
41 # neither C++ nor SDK prompt
42 if ("$VisualStudioVersion" -eq "") {
43 if ((Find-VSDir 15) -ne "") { # VC15 is installed (current official)
44 $VisualStudioVersion = "15.0"
45 } elseif ((Find-VSDir 16) -ne "") { # VC16 is installed
46 $VisualStudioVersion = "16.0"
47 } elseif ("${env:VS140COMNTOOLS}" -ne "") { # VC14 is installed
48 $VisualStudioVersion = "14.0"
49 } elseif ("${env:VS120COMNTOOLS}" -ne "") { # VC12 is installed
50 $VisualStudioVersion = "12.0"
51 } elseif ("${env:VS100COMNTOOLS}" -ne "") { # VC10 is installed
52 $VisualStudioVersion = "10.0"
53 } elseif ("${env:VS110COMNTOOLS}" -ne "") { # VC11 is installed
54 $VisualStudioVersion = "11.0"
55 } else {
56 throw "Visual Studio >= 10.0 not found"
57 }
58 }
59 if ([int]::TryParse($VisualStudioVersion, [ref]$refnum)) {
60 $VisualStudioVersion="${refnum}.0"
61 }
62 # Check VisualStudioVersion and prepare for ToolsVersion
63 switch ($VisualStudioVersion) {
64 "10.0" { $toolsout = 4 }
65 "11.0" { $toolsout = 4 }
66 "12.0" { $toolsout = 12 }
67 "14.0" { $toolsout = 14 }
68 "15.0" { $toolsout = 15 }
69 "16.0" { $toolsout = 16 }
70 default { throw "Selected Visual Stuidio is Version ${VisualStudioVersion}. Please use VC10 or later"}
71 }
72 #
73 # Determine ToolsVersion
74 #
75 [int]$toolsnum=$toolsout
76 if ("$MSToolsVersion" -eq "") {
77 $MSToolsVersion=$env:ToolsVersion
78 }
79 if ("$MSToolsVersion" -ne "") {
80 if ([int]::TryParse($MSToolsVersion, [ref]$refnum)) {
81 $toolsout=[int]$refnum
82 }
83 }
84 if ($toolsnum -lt 12) {
85 $toolsnum=$toolsout
86 }
87 #
88 # Determine MSBuild executable
89 #
90 Write-Debug "ToolsVersion=$MSToolsVersion VisualStudioVersion=$VisualStudioVersion"
91 try {
92 $msbver = msbuild.exe /ver /nologo
93 if ("$msbver" -match "^(\d+)\.(\d+)") {
94 $major1 = [int] $matches[1]
95 $minor1 = [int] $matches[2]
96 if ($MSToolsVersion -match "^(\d+)\.(\d+)") {
97 $bavail = $false
98 $major2 = [int] $matches[1]
99 $minor2 = [int] $matches[2]
100 if ($major1 -gt $major2) {
101 Write-Debug "$major1 > $major2"
102 $bavail = $true
103 }
104 elseif ($major1 -eq $major2 -And $minor1 -ge $minor2) {
105 Write-Debug "($major1, $minor1) >= ($major2, $minor2)"
106 $bavail = $true
107 }
108 if ($bavail) {
109 $msbuildexe = "MSBuild"
110 }
111 }
112 }
113 } catch {}
114 if ("$msbuildexe" -eq "") {
115 if ($toolsnum -gt 14) { # VC15 ~ VC16
116 $msbuildexe = msbfind_15_xx $toolsnum
117 } else { # VC10 ~ VC14
118 $msbuildexe = msbfind_10_14 "${toolsnum}.0"
119 if ($toolsnum -eq 4) {
120 if ((Find-VSDir $VisualStudioVersion) -eq "") {
121 throw "MSBuild ${toolsnum}.0 found but VisualStudioVersion $VisualStudioVersion not Found"
122 }
123 }
124 }
125 if ("$msbuildexe" -eq "") {
126 throw "MSBuild ToolsVersion ${toolsnum}.0 not Found"
127 }
128 }
129 #
130 # Determine PlatformToolset
131 #
132 if (("$Toolsetv" -eq "") -And ($configInfo -ne $null)) {
133 $Toolsetv=$configInfo.Configuration.toolset
134 }
135 if ("$Toolsetv" -eq "") {
136 $Toolsetv=$env:PlatformToolset
137 }
138 if ("$Toolsetv" -eq "") {
139 switch ($VisualStudioVersion) {
140 "10.0" {
141 if (Test-path "HKLM:\Software\Microsoft\Microsoft SDKs\Windows\v7.1") {
142 $Toolsetv=$WSDK71Set
143 } else {
144 $Toolsetv="v100"
145 }
146 }
147 "11.0" {$Toolsetv="v110_xp"}
148 "12.0" {$Toolsetv="v120_xp"}
149 "14.0" {$Toolsetv="v140_xp"}
150 "15.0" {$Toolsetv="v141_xp"}
151 "16.0" {$Toolsetv="v142"}
152 }
153 }
154 # avoid a bug of Windows7.1SDK PlatformToolset
155 if ($Toolsetv -eq $WSDK71Set) {
156 $env:TARGET_CPU=""
157 }
158 #
159 $VCVersion.value=$VisualStudioVersion
160 $Toolset.value=$Toolsetv
161
162 if ("$MSToolsVersion" -eq "") {
163 if ([int]$toolsout -gt 15) {
164 $MSToolsVersion="Current"
165 } else {
166 $MSToolsVersion="${toolsout}.0"
167 }
168 }
169 return $msbuildexe, $MSToolsVersion
170 }
171
172 # find msbuild.exe for VC10 ~ VC14
msbfind_10_14null173 function msbfind_10_14
174 {
175 [CmdletBinding()]
176
177 Param([Parameter(Mandatory=$true)]
178 [string]$toolsver)
179
180 $msbindir=""
181 $regKey="HKLM:\Software\Wow6432Node\Microsoft\MSBuild\ToolsVersions\${toolsver}"
182 if (Test-Path -path $regkey) {
183 $msbitem=Get-ItemProperty $regKey
184 if ($msbitem -ne $null) {
185 $msbindir=$msbitem.MSBuildToolsPath
186 }
187 } else {
188 $regKey="HKLM:\Software\Microsoft\MSBuild\ToolsVersions\${toolsver}"
189 if (Test-Path -path $regkey) {
190 $msbitem=Get-ItemProperty $regKey
191 if ($msbitem -ne $null) {
192 $msbindir=$msbitem.MSBuildToolsPath
193 }
194 } else {
195 return ""
196 }
197 }
198 return "${msbindir}msbuild"
199 }
200
201 # find msbuild.exe for VC15 ~ VC16
msbfind_15_xx()202 function msbfind_15_xx
203 {
204 [CmdletBinding()]
205
206 Param([Parameter(Mandatory=$true)]
207 [string]$toolsver)
208
209 # via vssetup module
210 $vsdir = find_vs_installation $toolsver
211 # vssetup module is unavailable
212 return find_default_msbuild_path $toolsver $vsdir
213 }
214
215 $dumpbinexe = ""
216 $addPath=""
217
Find-Dumpbinnull218 function Find-Dumpbin
219 {
220 [CmdletBinding()]
221
222 Param([int]$CurMaxVC = 16)
223
224 if ("$dumpbinexe" -ne "") {
225 if ("$addPath" -ne "") {
226 if (${env:PATH}.indexof($addPath) -lt 0) {
227 $env:PATH = "${addPath};" + $env:PATH
228 }
229 }
230 return $dumpbinexe
231 }
232 $addPath=""
233 $vsdir=""
234 try {
235 $dum = dumpbin.exe /NOLOGO
236 $dumpbinexe="dumpbin"
237 } catch [Exception] {
238 # $dumpbinexe="$env:DUMPBINEXE"
239 if ($dumpbinexe -eq "") {
240 $searching = $true
241 for ($i = $CurMaxVc; $searching -and ($i -ge 14); $i--) # VC15 ~ VC16
242 {
243 $vsdir = Find-VSDir $i
244 if ("$vsdir" -ne "") {
245 $lslist = @(Get-ChildItem "${vsdir}VC\Tools\MSVC\*\bin\HostX86\x86\dumpbin.exe" -ErrorAction SilentlyContinue)
246 if ($lslist.Count -gt 0) {
247 $dumpbinexe=$lslist[0].FullName
248 $searching = $false
249 break
250 }
251 }
252 }
253 for (; $searching -and ($i -ge 10); $i--) # VC10 ~ VC14
254 {
255 $vsdir = Find-VSDir $i
256 if ("$vsdir" -ne "") {
257 $dumpbinexe="${vsdir}VC\bin\dumpbin.exe"
258 if (Test-Path -Path $dumpbinexe) {
259 $searching = $false
260 break
261 }
262 }
263 }
264 if ($searching) {
265 throw "dumpbin doesn't exist"
266 }
267 elseif ($i -eq 10) {
268 $addPath = "${vsdir}Common7\ide"
269 }
270 }
271 }
272
273 Write-Host "Dumpbin=$dumpbinexe"
274 Set-Variable -Name dumpbinexe -Value $dumpbinexe -Scope 1
275 Set-Variable -Name addPath -Value $addPath -Scope 1
276 if ("$addPath" -ne "") {
277 if (${env:PATH}.indexof($addPath) -lt 0) {
278 $env:PATH = "${addPath};" + $env:PATH
279 }
280 }
281 return $dumpbinexe
282 }
283
dumpbinRecurs()284 function dumpbinRecurs
285 {
286 [CmdletBinding()]
287
288 Param([Parameter(Mandatory=$true)]
289 [string]$dllname,
290 [Parameter(Mandatory=$true)]
291 [string]$dllfolder,
292 [array]$instarray)
293
294 $tmem=& ${dumpbinexe} /imports "$dllfolder\${dllname}" | select-string -pattern "^\s*(\S*\.dll)" | foreach-object {$_.Matches.Groups[1].Value} | where-object {test-path ("${dllfolder}\" + $_)}
295 if ($LASTEXITCODE -ne 0) {
296 throw "Failed to dumpbin ${dllfolder}\${dllname}"
297 }
298 if ($tmem -eq $Null) {
299 return $instarray
300 }
301 if ($tmem.GetType().Name -eq "String") {
302 [String []]$tarray = @($tmem)
303 } else {
304 $tarray = $tmem
305 }
306 $iarray=@()
307 for ($i=0; $i -lt $tarray.length; $i++) {
308 if (-not($instarray -contains $tarray[$i])) {
309 $iarray += $tarray[$i]
310 }
311 }
312 if ($iarray.length -eq 0) {
313 return $instarray
314 }
315 $instarray += $iarray
316 for ($i=0; $i -lt $iarray.length; $i++) {
317 $instarray=dumpbinRecurs $iarray[$i] $dllfolder $instarray
318 }
319 return $instarray
320 }
321
Get-RelatedDlls()322 function Get-RelatedDlls
323 {
324 [CmdletBinding()]
325
326 Param([Parameter(Mandatory=$true)]
327 [string]$dllname,
328 [Parameter(Mandatory=$true)]
329 [string]$dllfolder)
330
331 Find-Dumpbin | Out-Null
332 $libpqmem=@()
333 $libpqmem=dumpbinRecurs $dllname $dllfolder $libpqmem
334
335 return $libpqmem
336 }
337
env_vcversion_no()338 function env_vcversion_no()
339 {
340 $viver = $env:VisualStudioVersion
341 if ("$viver" -ne "") {
342 if ("$viver" -match "(\d+)\.0") {
343 return [int]$matches[1]
344 }
345 }
346 return 0
347 }
348
Find-VSDir()349 function Find-VSDir
350 {
351 [CmdletBinding()]
352
353 Param([Parameter(Mandatory=$true)]
354 [string]$vcversion)
355
356 [int]$vcversion_no = [int]$vcversion
357 if ("${vcversion}" -match "^(\d+)") {
358 $vcversion_no = $matches[1]
359 }
360 if ((env_vcversion_no) -eq $vcversion_no) {
361 return $env:VSINSTALLDIR
362 }
363 if ($vcversion_no -gt 14) { # VC15 ~ VC16
364 return find_vsdir_15_xx ${vcversion_no}
365 } else { # VC10 ~ VC14
366 $comntools = [environment]::getenvironmentvariable("VS${vcversion_no}0COMNTOOLS")
367 if ("$comntools" -eq "") {
368 return ""
369 }
370 return (Split-Path (Split-Path $comntools -Parent) -Parent) + "\"
371 }
372 }
373
374 [bool]$vssetup_available = $true
375 $vssetup = $null
376 # find vs installation path for VC15 ~ VC16
find_vs_installation()377 function find_vs_installation
378 {
379 [CmdletBinding()]
380
381 Param([Parameter(Mandatory=$true)]
382 [string]$toolsver)
383
384 $vsdir = ""
385 # vssetup module is available?
386 if ($vssetup_available -and ($vsseup -eq $null)) {
387 try {
388 $vssetup = @(Get-VssetupInstance)
389 } catch [Exception] {
390 $vssetup_available = $false
391 }
392 }
393 $toolsnum = [int]$toolsver
394 if ($vssetup -ne $null) {
395 $lslist = @($vssetup | where-object { $_.InstallationVersion.Major -eq $toolsnum } | foreach-object { $_.InstallationPath })
396 if ($lslist.Count -gt 0) {
397 $vsdir = $lslist[0]
398 }
399 }
400 return $vsdir
401 }
402
403 $vsarray = @{VC15 = "2017"; VC16 = "2019"}
404 # find VS dir for VC15 ~ VC16
find_default_msbuild_path()405 function find_default_msbuild_path
406 {
407 [CmdletBinding()]
408
409 Param([Parameter(Mandatory=$true)]
410 [string]$toolsver,
411 [string]$vsdir)
412
413 if ($vsdir -eq "")
414 {
415 $toolsnum = [int]$toolsver
416 if ($env:PROCESSOR_ARCHITECTURE -eq "x86") {
417 $pgmfs = "$env:ProgramFiles"
418 } else {
419 $pgmfs = "${env:ProgramFiles(x86)}"
420 }
421 $vsverdir = $vsarray["VC$toolsnum"]
422 $lslist = @(Get-ChildItem "$pgmfs\Microsoft Visual Studio\$vsverdir\*\MSBuild\*\Bin\MSBuild.exe" -ErrorAction SilentlyContinue)
423 } else {
424 $lslist = @(Get-ChildItem "$vsdir\MSBuild\*\Bin\MSBuild.exe" -ErrorAction SilentlyContinue)
425 }
426 if ($lslist.Count -gt 0) {
427 return $lslist[0].FullName
428 }
429
430 return ""
431 }
432
433 # find VS dir for VC15 ~ VC16
find_vsdir_15_xx()434 function find_vsdir_15_xx
435 {
436 [CmdletBinding()]
437
438 Param([Parameter(Mandatory=$true)]
439 [string]$toolsver)
440
441 # via vssetup module
442 $vsdir = find_vs_installation $toolsver
443 if ($vsdir -ne "") {
444 return $vsdir
445 }
446 # vssetup module is unavailable
447 $msbpath = find_default_msbuild_path $toolsver $vsdir
448 if ($msbpath -ne "") {
449 return (Split-Path (Split-Path (Split-Path (Split-Path $msbpath -Parent) -Parent) -Parent) -Parent) + "\"
450 }
451
452 return ""
453 }
454
455 Export-ModuleMember -function Find-MSBuild, Find-Dumpbin, Get-RelatedDlls, Find-VSDir
456