Skip to content

Instantly share code, notes, and snippets.

@ozskywalker
Last active February 18, 2021 05:17
Show Gist options
  • Save ozskywalker/13a2cde8e82751ae366c2a5c95709045 to your computer and use it in GitHub Desktop.
Save ozskywalker/13a2cde8e82751ae366c2a5c95709045 to your computer and use it in GitHub Desktop.
MSI Installer
# TODO: change variable expansion method for newer approach ({0}, etc.)
# Exitcodes ($lastexitcode)
# 0: Success
# 1: MSI doesn't exist
# 2: Not our first time
# All other codes (=>13): see https://docs.microsoft.com/en-us/windows/win32/msi/error-codes
# Vars
$workingdir = "C:\\working"
$touchFile = "do_not_retry_LAPS.touch"
$installer = "LAPS.x64.msi"
$childNametoCheck = "{EA8CB806-C109-4700-96B4-F1F268E5036C}"
# Child Names will either be GUID (MSFT standard), or equivalent to DisplayName
# LAPS Identifiying Number
# {EA8CB806-C109-4700-96B4-F1F268E5036C}
function ExitWithCode
{
param($exitcode)
$host.SetShouldExit($exitcode)
exit $exitcode
}
function Get-InstalledPrograms-ChildName()
{
$regLocations = (
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\",
"HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\",
"HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\"
)
Get-ChildItem ($regLocations | Where { Test-Path $_ } ) |
Get-ItemProperty |
Where {
( (Get-Member -InputObject $_ -Name DisplayName) -and $_.DisplayName -ne $Null) -and
(!(Get-Member -InputObject $_ -Name SystemComponent) -or $_.SystemComponent -ne "1") -and
(!(Get-Member -InputObject $_ -Name ParentKeyName) -or $_.ParentKeyName -eq $Null)
} |
Select PSChildName
}
# Step 1: Get Working directory in order
New-Item -Path $workingdir -ItemType Directory -ErrorAction SilentlyContinue
if ( -not (Test-Path "$workingdir\$installer" -PathType Leaf) ) {
Write-Host "MSI $installer does not exist in working directory $workingdir. Failing script."
ExitWithCode -exitcode 1
}
# Step 2: Check conditions to allow MSI install
# 1. MSI must not be installed
# 2. This must be our first attempt, evidenced by stop file in $
#
# NB: We are deliberately NOT using Get-WmiObject Win32_Product because it may modify the Guest OS if it finds errors
# within the installer database. Avoiding this by looking to Uninstall registry keys.
if ( @(Get-InstalledPrograms-ChildName | Where-Object { $_.PSChildName -eq $childNametoCheck }).Count -ge 1) {
Write-Host "Package found, ignore"
ExitWithCode -exitcode 0
} else {
if ( -not (Test-Path "$workingdir\$touchFile" -PathType Leaf) ) {
# Step 3: Install MSI
Write-Host "Package not found, and this is our first time installing. Proceeding with install"
$DataStamp = Get-Date -Format yyyyMMddTHHmmss
$logFile = "$workingdir\$installer-$DataStamp.log"
$MSIArguments = @("/i", ("$workingdir\$installer"), "/qn", "/norestart", "/L*v", $logFile)
# Create touch file so we never can run this branch again
Out-File -FilePath "$workingdir\$touchFile"
# Start installation
$status = (Start-Process "msiexec.exe" -ArgumentList $MSIArguments -Wait -NoNewWindow -Passthru).ExitCode
if ($status -ge 1) {
Write-Host "MSI install failed"
} else {
Write-Host "MSI passed 0 - success"
}
# Pass exit code back
ExitWithCode -exitcode $status
} else {
Write-Host "Package not found, and this is NOT our first time. Failing."
ExitWithCode -exitcode 2
}
}
Write-Host "We should not reach here."
ExitWithCode -exitcode 127
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment