winbuild/MSProgram-Get.psm1 (426 lines of code) (raw):
function Find-MSBuild
{
[CmdletBinding()]
Param([Parameter(Mandatory=$true)]
[ref]$VCVersion,
[Parameter(Mandatory=$true)]
$MSToolsVersion,
[Parameter(Mandatory=$true)]
[ref]$Toolset,
[Parameter(Mandatory=$true)]
[xml]$configInfo)
$msbuildexe=""
$VisualStudioVersion=$VCVersion.Value
$Toolsetv=$Toolset.Value
$WSDK71Set="Windows7.1SDK"
Write-Debug "VCVersion=$VCVersionv $env:VisualStudioVersion"
[int]$toolsnum=0
#
# Determine VisualStudioVersion
#
if (("$VisualStudioVersion" -eq "") -And ($configInfo -ne $null)) {
$VisualStudioVersion=$configInfo.Configuration.vcversion
}
if ("$VisualStudioVersion" -eq "") {
$VisualStudioVersion = $env:VisualStudioVersion # VC11 or later version of C++ command prompt sets this variable
}
if ("$VisualStudioVersion" -eq "") {
if ("${env:WindowsSDKVersionOverride}" -eq "v7.1") { # SDK7.1+ command prompt
$VisualStudioVersion = "10.0"
} elseif ("${env:VCInstallDir}" -ne "") { # C++ command prompt
if ("${env:VCInstallDir}" -match "Visual Studio\s*(\S+)\\VC\\$") {
$VisualStudioVersion = $matches[1]
}
}
}
$refnum=""
# neither C++ nor SDK prompt
if ("$VisualStudioVersion" -eq "") {
if ((Find-VSDir 15) -ne "") { # VC15 is installed (current official)
$VisualStudioVersion = "15.0"
} elseif ((Find-VSDir 16) -ne "") { # VC16 is installed
$VisualStudioVersion = "16.0"
} elseif ((Find-VSDir 17) -ne "") { #VC 17 is installed
$VisualStudioVersion = "17.0"
} elseif ("${env:VS140COMNTOOLS}" -ne "") { # VC14 is installed
$VisualStudioVersion = "14.0"
} elseif ("${env:VS120COMNTOOLS}" -ne "") { # VC12 is installed
$VisualStudioVersion = "12.0"
} elseif ("${env:VS100COMNTOOLS}" -ne "") { # VC10 is installed
$VisualStudioVersion = "10.0"
} elseif ("${env:VS110COMNTOOLS}" -ne "") { # VC11 is installed
$VisualStudioVersion = "11.0"
} else {
throw "Visual Studio >= 10.0 not found"
}
}
if ([int]::TryParse($VisualStudioVersion, [ref]$refnum)) {
$VisualStudioVersion="${refnum}.0"
}
# Check VisualStudioVersion and prepare for ToolsVersion
switch ($VisualStudioVersion) {
"10.0" { $toolsout = 4 }
"11.0" { $toolsout = 4 }
"12.0" { $toolsout = 12 }
"14.0" { $toolsout = 14 }
"15.0" { $toolsout = 15 }
"16.0" { $toolsout = 16 }
"17.0" { $toolsout = 17 }
default { throw "Selected Visual Studio is Version ${VisualStudioVersion}. Please use VC10 or later"}
}
#
# Determine ToolsVersion
#
[int]$toolsnum=$toolsout
if ("$MSToolsVersion" -eq "") {
$MSToolsVersion=$env:ToolsVersion
}
if ("$MSToolsVersion" -ne "") {
if ([int]::TryParse($MSToolsVersion, [ref]$refnum)) {
$toolsout=[int]$refnum
}
}
if ($toolsnum -lt 12) {
$toolsnum=$toolsout
}
#
# Determine MSBuild executable
#
Write-Debug "ToolsVersion=$MSToolsVersion VisualStudioVersion=$VisualStudioVersion"
try {
$msbver = msbuild.exe /ver /nologo
if ("$msbver" -match "^(\d+)\.(\d+)") {
$major1 = [int] $matches[1]
$minor1 = [int] $matches[2]
if ($MSToolsVersion -match "^(\d+)\.(\d+)") {
$bavail = $false
$major2 = [int] $matches[1]
$minor2 = [int] $matches[2]
if ($major1 -gt $major2) {
Write-Debug "$major1 > $major2"
$bavail = $true
}
elseif ($major1 -eq $major2 -And $minor1 -ge $minor2) {
Write-Debug "($major1, $minor1) >= ($major2, $minor2)"
$bavail = $true
}
if ($bavail) {
$msbuildexe = "MSBuild"
}
}
}
} catch {}
if ("$msbuildexe" -eq "") {
Write-Debug "tools version $toolsnum"
if ($toolsnum -gt 14) { # VC15 ~ VC??
$msbuildexe = msbfind_15_xx $toolsnum
} else { # VC10 ~ VC14
$msbuildexe = msbfind_10_14 "${toolsnum}.0"
if ($toolsnum -eq 4) {
if ((Find-VSDir $VisualStudioVersion) -eq "") {
throw "MSBuild ${toolsnum}.0 found but VisualStudioVersion $VisualStudioVersion not Found"
}
}
}
if ("$msbuildexe" -eq "") {
throw "MSBuild ToolsVersion ${toolsnum}.0 not Found"
}
}
Write-Debug "msbuildexe=$msbuildexe"
#
# Determine PlatformToolset
#
if (("$Toolsetv" -eq "") -And ($configInfo -ne $null)) {
$Toolsetv=$configInfo.Configuration.toolset
}
if ("$Toolsetv" -eq "") {
$Toolsetv=$env:PlatformToolset
}
if ("$Toolsetv" -eq "") {
switch ($VisualStudioVersion) {
"10.0" {
if (Test-path "HKLM:\Software\Microsoft\Microsoft SDKs\Windows\v7.1") {
$Toolsetv=$WSDK71Set
} else {
$Toolsetv="v100"
}
}
"11.0" {$Toolsetv="v110_xp"}
"12.0" {$Toolsetv="v120_xp"}
"14.0" {$Toolsetv="v140_xp"}
"15.0" {$Toolsetv="v141_xp"}
"16.0" {$Toolsetv="v142"}
"17.0" {$Toolsetv="v143"}
}
}
# avoid a bug of Windows7.1SDK PlatformToolset
if ($Toolsetv -eq $WSDK71Set) {
$env:TARGET_CPU=""
}
#
$VCVersion.value=$VisualStudioVersion
$Toolset.value=$Toolsetv
if ("$MSToolsVersion" -eq "") {
if ([int]$toolsout -gt 15) {
$MSToolsVersion="Current"
} else {
$MSToolsVersion="${toolsout}.0"
}
Write-Debug "MSToolsVersion=$MSToolsVersion"
}
return $msbuildexe, $MSToolsVersion
}
# find msbuild.exe for VC10 ~ VC14
function msbfind_10_14
{
[CmdletBinding()]
Param([Parameter(Mandatory=$true)]
[string]$toolsver)
$msbindir=""
$regKey="HKLM:\Software\Wow6432Node\Microsoft\MSBuild\ToolsVersions\${toolsver}"
if (Test-Path -path $regkey) {
$msbitem=Get-ItemProperty $regKey
if ($msbitem -ne $null) {
$msbindir=$msbitem.MSBuildToolsPath
}
} else {
$regKey="HKLM:\Software\Microsoft\MSBuild\ToolsVersions\${toolsver}"
if (Test-Path -path $regkey) {
$msbitem=Get-ItemProperty $regKey
if ($msbitem -ne $null) {
$msbindir=$msbitem.MSBuildToolsPath
}
} else {
return ""
}
}
return "${msbindir}msbuild"
}
# find msbuild.exe for VC15 ~ VC??
function msbfind_15_xx
{
[CmdletBinding()]
Param([Parameter(Mandatory=$true)]
[string]$toolsver)
# via vssetup module
$vsdir = find_vs_installation $toolsver
# vssetup module is unavailable
return find_default_msbuild_path $toolsver $vsdir
}
$dumpbinexe = ""
$addPath=""
function Find-Dumpbin
{
[CmdletBinding()]
Param([int]$CurMaxVC = 16)
if ("$dumpbinexe" -ne "") {
if ("$addPath" -ne "") {
if (${env:PATH}.indexof($addPath) -lt 0) {
$env:PATH = "${addPath};" + $env:PATH
}
}
return $dumpbinexe
}
$addPath=""
$vsdir=""
try {
$dum = dumpbin.exe /NOLOGO
$dumpbinexe="dumpbin"
} catch [Exception] {
# $dumpbinexe="$env:DUMPBINEXE"
if ($dumpbinexe -eq "") {
$searching = $true
for ($i = $CurMaxVc; $searching -and ($i -ge 14); $i--) # VC15 ~ VC??
{
$vsdir = Find-VSDir $i
if ("$vsdir" -ne "") {
$lslist = @(Get-ChildItem "${vsdir}VC\Tools\MSVC\*\bin\HostX86\x86\dumpbin.exe" -ErrorAction SilentlyContinue)
if ($lslist.Count -gt 0) {
$dumpbinexe=$lslist[0].FullName
$searching = $false
break
}
}
}
for (; $searching -and ($i -ge 10); $i--) # VC10 ~ VC14
{
$vsdir = Find-VSDir $i
if ("$vsdir" -ne "") {
$dumpbinexe="${vsdir}VC\bin\dumpbin.exe"
if (Test-Path -Path $dumpbinexe) {
$searching = $false
break
}
}
}
if ($searching) {
throw "dumpbin doesn't exist"
}
elseif ($i -eq 10) {
$addPath = "${vsdir}Common7\ide"
}
}
}
Write-Host "Dumpbin=$dumpbinexe"
Set-Variable -Name dumpbinexe -Value $dumpbinexe -Scope 1
Set-Variable -Name addPath -Value $addPath -Scope 1
if ("$addPath" -ne "") {
if (${env:PATH}.indexof($addPath) -lt 0) {
$env:PATH = "${addPath};" + $env:PATH
}
}
return $dumpbinexe
}
function dumpbinRecurs
{
[CmdletBinding()]
Param([Parameter(Mandatory=$true)]
[string]$dllname,
[Parameter(Mandatory=$true)]
[string]$dllfolder,
[array]$instarray)
$tmem=& ${dumpbinexe} /imports "$dllfolder\${dllname}" | select-string -pattern "^\s*(\S*\.dll)" | foreach-object {$_.Matches.Groups[1].Value} | where-object {test-path ("${dllfolder}\" + $_)}
if ($LASTEXITCODE -ne 0) {
throw "Failed to dumpbin ${dllfolder}\${dllname}"
}
if ($tmem -eq $Null) {
return $instarray
}
if ($tmem.GetType().Name -eq "String") {
[String []]$tarray = @($tmem)
} else {
$tarray = $tmem
}
$iarray=@()
for ($i=0; $i -lt $tarray.length; $i++) {
if (-not($instarray -contains $tarray[$i])) {
$iarray += $tarray[$i]
}
}
if ($iarray.length -eq 0) {
return $instarray
}
$instarray += $iarray
for ($i=0; $i -lt $iarray.length; $i++) {
$instarray=dumpbinRecurs $iarray[$i] $dllfolder $instarray
}
return $instarray
}
function Get-RelatedDlls
{
[CmdletBinding()]
Param([Parameter(Mandatory=$true)]
[string]$dllname,
[Parameter(Mandatory=$true)]
[string]$dllfolder)
Find-Dumpbin | Out-Null
$libpqmem=@()
$libpqmem=dumpbinRecurs $dllname $dllfolder $libpqmem
return $libpqmem
}
function env_vcversion_no()
{
$viver = $env:VisualStudioVersion
if ("$viver" -ne "") {
if ("$viver" -match "(\d+)\.0") {
return [int]$matches[1]
}
}
return 0
}
function Find-VSDir
{
[CmdletBinding()]
Param([Parameter(Mandatory=$true)]
[string]$vcversion)
[int]$vcversion_no = [int]$vcversion
if ("${vcversion}" -match "^(\d+)") {
$vcversion_no = $matches[1]
}
if ((env_vcversion_no) -eq $vcversion_no) {
return $env:VSINSTALLDIR
}
if ($vcversion_no -gt 14) { # VC15 ~ VC??
return find_vsdir_15_xx ${vcversion_no}
} else { # VC10 ~ VC14
$comntools = [environment]::getenvironmentvariable("VS${vcversion_no}0COMNTOOLS")
if ("$comntools" -eq "") {
return ""
}
return (Split-Path (Split-Path $comntools -Parent) -Parent) + "\"
}
}
[bool]$vssetup_available = $true
$vssetup = $null
# find vs installation path for VC15 ~ VC??
function find_vs_installation
{
[CmdletBinding()]
Param([Parameter(Mandatory=$true)]
[string]$toolsver)
$vsdir = ""
# vssetup module is available?
if ($vssetup_available -and ($vsseup -eq $null)) {
try {
$vssetup = @(Get-VssetupInstance)
} catch [Exception] {
$vssetup_available = $false
}
}
$toolsnum = [int]$toolsver
if ($vssetup -ne $null) {
$lslist = @($vssetup | where-object { $_.InstallationVersion.Major -eq $toolsnum } | foreach-object { $_.InstallationPath })
if ($lslist.Count -gt 0) {
$vsdir = $lslist[0]
}
}
return $vsdir
}
$vsarray = @{VC15 = "2017"; VC16 = "2019"; VC17 = "2022"}
# find VS dir for VC15 ~ VC??
function find_default_msbuild_path
{
[CmdletBinding()]
Param([Parameter(Mandatory=$true)]
[string]$toolsver,
[string]$vsdir)
Write-Debug "toolsver=$toolsver vsdir=$vsdir"
if ($vsdir -eq "")
{
$toolsnum = [int]$toolsver
# As of Visual Studio 2022 (VC17), MSBuild is 64-bit and so is always in ProgramFiles
if ($env:PROCESSOR_ARCHITECTURE -eq "x86" -or $toolsver -ge 17) {
$pgmfs = "$env:ProgramFiles"
} else {
$pgmfs = "${env:ProgramFiles(x86)}"
}
$vsverdir = $vsarray["VC$toolsnum"]
Write-Debug "$pgmfs\Microsoft Visual Studio\$vsverdir\*\MSBuild\*\Bin\MSBuild.exe"
$lslist = @(Get-ChildItem "$pgmfs\Microsoft Visual Studio\$vsverdir\*\MSBuild\*\Bin\MSBuild.exe" -ErrorAction SilentlyContinue)
} else {
$lslist = @(Get-ChildItem "$vsdir\MSBuild\*\Bin\MSBuild.exe" -ErrorAction SilentlyContinue)
}
if ($lslist.Count -gt 0) {
return $lslist[0].FullName
}
return ""
}
# find VS dir for VC15 ~ VC??
function find_vsdir_15_xx
{
[CmdletBinding()]
Param([Parameter(Mandatory=$true)]
[string]$toolsver)
# via vssetup module
$vsdir = find_vs_installation $toolsver
if ($vsdir -ne "") {
return $vsdir
}
# vssetup module is unavailable
$msbpath = find_default_msbuild_path $toolsver $vsdir
if ($msbpath -ne "") {
return (Split-Path (Split-Path (Split-Path (Split-Path $msbpath -Parent) -Parent) -Parent) -Parent) + "\"
}
return ""
}
Export-ModuleMember -function Find-MSBuild, Find-Dumpbin, Get-RelatedDlls, Find-VSDir