Files
windows-imaging-tools-builder/hooks/RunBeforeCloudbaseInitInstall.ps1

121 lines
5.6 KiB
PowerShell

$ErrorActionPreference = "Stop"
function Write-TemplateStage {
param([string]$Stage, [string]$Message)
Write-Host "$Stage - $Message"
if (Get-Command Write-Log -CommandType Function -ErrorAction SilentlyContinue) {
Write-Log -Stage $Stage -StageLog $Message
}
}
function Test-ApplicationFile {
param([string]$Path)
if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) { return $false }
$value = (Get-Item -LiteralPath $Path).VersionInfo.ProductVersion
return -not [string]::IsNullOrWhiteSpace($value)
}
function Test-VirtioBundleInstalled {
$roots = @(
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*',
'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
)
$entries = @(Get-ItemProperty -Path $roots -ErrorAction SilentlyContinue)
foreach ($entry in $entries) {
if ($entry.DisplayName -eq 'Virtio-win-guest-tools') {
return $true
}
}
return $false
}
function Invoke-TemplateInstaller {
param(
[string]$Name,
[string]$FilePath,
[string]$Arguments,
[ref]$RebootRequired
)
Write-TemplateStage -Stage ($Name + 'InstallStart') -Message 'Starting silent installation.'
$process = Start-Process -FilePath $FilePath -ArgumentList $Arguments `
-WindowStyle Hidden -PassThru
# Wait for the installer itself; GUI descendants must not block imaging.
$null = $process.Handle
$process.WaitForExit()
if ($process.ExitCode -notin @(0, 3010, 1641)) {
throw "$Name installation failed: ExitCode=$($process.ExitCode). Check the installer log in C:\Windows\Temp."
}
if ($process.ExitCode -in @(3010, 1641)) { $RebootRequired.Value = $true }
}
try {
if (-not (Test-Path -LiteralPath 'C:\UnattendResources\config.ini')) {
throw 'This installation hook is intended for the imaging guest, not the build host.'
}
$resourceRoot = 'C:\UnattendResources\CustomResources'
if (Test-Path -LiteralPath (Join-Path $resourceRoot 'Software.Selection.ps1')) {
. (Join-Path $resourceRoot 'Software.Selection.ps1')
$selection = Get-GuestSoftwareSelection -ResourceRoot $resourceRoot
} else { $selection = [PSCustomObject]@{InstallChrome=$true;InstallVSCode=$true} }
. (Join-Path $resourceRoot 'Package.Validation.ps1')
foreach ($package in @(Get-SelectedImagePackages -SkipChrome:(-not $selection.InstallChrome) -SkipVSCode:(-not $selection.InstallVSCode))) {
Assert-ImagePackage -Path (Join-Path $resourceRoot $package.File) -Package $package
}
$rebootRequired = $false
$chrome = "$env:ProgramFiles\Google\Chrome\Application\chrome.exe"
if ($selection.InstallChrome -and -not (Test-ApplicationFile -Path $chrome)) {
$msi = Join-Path $resourceRoot 'chrome-enterprise64.msi'
$arguments = "/i `"$msi`" ALLUSERS=1 /qn /norestart /L*v `"C:\Windows\Temp\chrome-install.log`""
Invoke-TemplateInstaller -Name 'Chrome' -FilePath 'msiexec.exe' `
-Arguments $arguments -RebootRequired ([ref]$rebootRequired)
}
if ($selection.InstallChrome -and -not (Test-ApplicationFile -Path $chrome)) {
throw 'Chrome installation verification failed.'
}
if ($selection.InstallChrome) {
Write-TemplateStage -Stage 'ChromeInstall' -Message (
'Google Chrome ' + (Get-Item -LiteralPath $chrome).VersionInfo.ProductVersion.Trim() + ' installed for all users.'
)
} else { Write-TemplateStage -Stage 'ChromeInstall' -Message 'Skipped by software selection.' }
$code = "$env:ProgramFiles\Microsoft VS Code\Code.exe"
if ($selection.InstallVSCode -and -not (Test-ApplicationFile -Path $code)) {
$setup = Join-Path $resourceRoot 'VSCodeSetup-x64.exe'
$arguments = '/VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- /MERGETASKS="addtopath,!runcode" /LOG="C:\Windows\Temp\vscode-install.log"'
Invoke-TemplateInstaller -Name 'VSCode' -FilePath $setup `
-Arguments $arguments -RebootRequired ([ref]$rebootRequired)
}
if ($selection.InstallVSCode -and -not (Test-ApplicationFile -Path $code)) {
throw 'VS Code system installation verification failed.'
}
if ($selection.InstallVSCode) {
Write-TemplateStage -Stage 'VSCodeInstall' -Message (
'Visual Studio Code ' + (Get-Item -LiteralPath $code).VersionInfo.ProductVersion.Trim() + ' installed for all users.'
)
} else { Write-TemplateStage -Stage 'VSCodeInstall' -Message 'Skipped by software selection.' }
if (-not (Test-VirtioBundleInstalled)) {
$setup = Join-Path $resourceRoot 'virtio-win-guest-tools.exe'
$arguments = '/install /quiet /norestart /log "C:\Windows\Temp\virtio-guest-tools-install.log"'
Invoke-TemplateInstaller -Name 'VirtioGuestTools' -FilePath $setup `
-Arguments $arguments -RebootRequired ([ref]$rebootRequired)
}
if (-not (Test-VirtioBundleInstalled)) { throw 'VirtIO guest tools bundle installation verification failed.' }
if (-not (Get-Service -Name 'qemu-ga' -ErrorAction SilentlyContinue)) {
throw 'The VirtIO guest tools installation did not create the QEMU Guest Agent service.'
}
Set-Service -Name 'qemu-ga' -StartupType Automatic
Write-TemplateStage -Stage 'VirtioGuestToolsInstall' -Message 'Virtio-win-guest-tools installed, including QEMU Guest Agent.'
if ($rebootRequired) {
Write-TemplateStage -Stage 'SoftwareReboot' -Message 'Installer requested a reboot; imaging will resume after restart.'
exit 1005
}
exit 0
}
catch {
Write-Error $_ -ErrorAction Continue
exit 1
}