simh-testsetgenerator/cmake/github_v141_xp.ps1
B. Scott Michel 06d41835fe CMake: Win XP (v141_xp) VS install script
Move the PowerShell code from .github/workflow/cmake-builds.yml into its
own script, cmake/github_v141_xp.ps1, to keep cmake-buils.yml readable.
The script also facilitates synchronizng with the Chocolatey installer's
Wait-VSIstallerProcesses function easier (from which this this code is
derived.)

cmake-builds.yml: Check the output from Get-VSSetupInstance and
Set-VSSetupInstance. Empty (or null) output indicates that the v141_xp
install did not complete successfully. Build process will bail when that
happens.

cmake/v141_xp_install.ps1: Unused and now unnecessary script.
2023-10-24 12:46:51 -04:00

153 lines
6.1 KiB
PowerShell

<#
.SYNOPSIS
Install Visual Studio's 'v141_xp' XP toolkit on Github.
.DESCRIPTION
Update the existing Github Visual Studio installation in-place. This script
will iterate through all VS installations identified by the `vswhere` utility.
This script is Grey Magic. The `vs_installer` installer utility exits almost
immediately if you run it from the command line. `vs_installer`'s subprocesses
are reasonably well known, which allows this script to query the processes and
wait for them to terminate.
GitHub Actions does something strange with stdout and stderr, so you won't get any
indication of failure or output that shows you that something is happening.
The waiting code was adapted from the Chocolatey VS installer scripts (Wait-VSIstallerProcesses).
Ref: https://github.com/jberezanski/ChocolateyPackages/blob/master/chocolatey-visualstudio.extension/extensions/Wait-VSInstallerProcesses.ps1
#>
$exitcode = $null
$vswhere = "${env:ProgramFiles} (x86)\Microsoft Visual Studio\Installer\vswhere"
$vsinstaller = "${env:ProgramFiles} (x86)\Microsoft Visual Studio\Installer\vs_installer.exe"
$vsInstallOut = "$env:TEMP\vsinstall-out.txt"
$vsInstallErr = "$env:TEMP\vsinstall-err.txt"
& ${vswhere} -property installationPath | Foreach-Object -process {
# Save the installlation path for the current iteration
$installPath = $_
# Make sure that previously running installers have all exited.
Write-Debug ('Looking for previously running VS installer processes')
$lazyQuitterProcessNames = @('vs_installershell', 'vs_installerservice')
do
{
$lazyQuitterProcesses = Get-Process -Name $lazyQuitterProcessNames -ErrorAction SilentlyContinue | `
Where-Object { $null -ne $_ -and -not $_.HasExited }
$lazyQuitterProcessCount = ($lazyQuitterProcesses | Measure-Object).Count
if ($lazyQuitterProcessCount -gt 0)
{
try
{
$lazyQuitterProcesses | Sort-Object -Property Name, Id | ForEach-Object { '[{0}] {1}' -f $_.Id, $_.Name } | Write-Debug
$lazyQuitterProcesses | Wait-Process -Timeout 10 -ErrorAction SilentlyContinue
}
finally
{
$lazyQuitterProcesses | ForEach-Object { $_.Dispose() }
$lazyQuitterProcesses = $null
}
}
}
while ($lazyQuitterProcessCount -gt 0)
## Now kick off our install:
##
## --quiet: Don't open/show UI
## --force: Terminate any VS instances forcibly
## --norestart: Delay reboot after install, if needed
## --installWhileDownloading: Self-explanitory.
##
## Note: "--wait" doesn't.
$vsinstallParams = @(
"modify",
"--installPath", "$installPath",
"--add", "Microsoft.VisualStudio.Component.VC.v141.x86.x64",
"--add", "Microsoft.VisualStudio.Component.WinXP",
"--quiet", "--force", "--norestart", "--installWhileDownloading"
)
& $vsInstaller $vsinstallParams 2> $vsInstallErr > $vsInstallOut
## VS installer processes for which we want to wait because installation isn't complete. Yet.
$vsinstallerProcesses = @( 'vs_bootstrapper', 'vs_setup_bootstrapper', 'vs_installer', 'vs_installershell', `
'vs_installerservice', 'setup')
$vsInstallerProcessFilter = { $_.Name -ne 'setup' -or $_.Path -like '*\Microsoft Visual Studio\Installer*\setup.exe' }
do
{
Write-Debug ('Looking for running VS installer processes')
$vsInstallerRemaining = Get-Process -Name $vsinstallerProcesses -ErrorAction SilentlyContinue | `
Where-Object { $null -ne $_ -and -not $_.HasExited } | `
Where-Object $vsInstallerProcessFilter
$vsInstallerProcessCount = ($vsInstallerRemaining | Measure-Object).Count
if ($vsInstallerProcessCount -gt 0)
{
try
{
Write-Debug "Found $vsInstallerProcessCount running Visual Studio installer processes:"
$vsInstallerRemaining | Sort-Object -Property Name, Id | ForEach-Object { '[{0}] {1}' -f $_.Id, $_.Name } | Write-Debug
foreach ($p in $vsInstallerProcesses)
{
[void] $p.Handle # make sure we get the exit code http://stackoverflow.com/a/23797762/266876
}
Write-Debug ('Waiting 60 seconds for process(es) to exit...')
$vsInstallerRemaining | Wait-Process -Timeout 60 -ErrorAction SilentlyContinue
foreach ($proc in $vsInstallerProcesses)
{
if (-not $proc.HasExited)
{
continue
}
if ($null -eq $exitCode)
{
$exitCode = $proc.ExitCode
}
if ($proc.ExitCode -ne 0 -and $null -ne $proc.ExitCode)
{
Write-Debug "$($proc.Name) process $($proc.Id) exited with code $($proc.ExitCode)"
if ($exitCode -eq 0)
{
$exitCode = $proc.ExitCode
}
}
}
}
finally
{
$vsInstallerRemaining | ForEach-Object { $_.Dispose() }
$vsInstallerRemaining = $null
}
}
}
while (($vsInstallerStartup -and $vsInstallerStartCount -gt 0) -or $vsInstallerProcessCount -gt 0)
}
if ((Test-Path $vsInstallOut -PathType Leaf) -and (Get-Item $vsInstallOut).length -gt 0kb)
{
Write-Output "-- vsinstaller output:"
Get-Content $vsInstallOut
}
else
{
Write-Debug "-- No vsinstaller output."
}
if ((Test-Path $vsInstallErr -PathType Leaf) -and (Get-Item $vsInstallErr).length -gt 0kb)
{
Write-Output "-- vsinstaller error output:"
Get-Content $vsInstallErr
}
else
{
Write-Debug "-- No vsinstaller error/diag output."
}
if ($null -ne $exitcode -and $exitcode -ne 0)
{
throw "VS installer exited with non-zero exit status: $exitcode"
}