pf-WinInstaller.ps1
function Get-Uninstall { # paths: x86 and x64 registry keys are different if ([IntPtr]::Size -eq 4) { $path = 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*' } else { $path = @( 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*' 'HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*' ) } Get-ItemProperty $path } function Install-Msi ($file, $arguments, [Switch]$quiet, [Switch]$Repair) { $file = Resolve-Path $file | Get-Path Write-Host "Installing '$file'" $fileFolder = Split-Path $file -Parent $filename = [System.Io.Path]::GetFileName($file); New-Folder_EnsureExists $logFolder $logFile = "$logFolder\$filename.log" $logFileInQuotes = $logFile | Update-String_Enclose '"' -conditional $fileInQuotes = $file | Update-String_Enclose '"' -conditional Write-Host "Log in $logFileInQuotes" $flag = if ($Repair) { '/fa' } else { '/i' } $msiargs = @($flag, $fileInQuotes, '/l*v', $logFileInQuotes) if ( $quiet ) { $msiargs = @("/qn") + $msiargs } $msiargs = $msiargs + $arguments $msiBat = "$file.bat" try { $msiargsTxt = $msiargs -join ' ' # Batch file generated just to quickly reproduce errors "msiexec $msiargsTxt " | Out-File -Encoding ascii -FilePath $msiBat Apply-Item_Conditional -path $file -action { Stop-Powershell_Other Invoke-InLocation -path $fileFolder -script { try { Get-Process | Where-Object name -eq 'msiexec' | Stop-Process -Force -Verbose $ps = Start-Process -Verb runAs -Wait -FilePath msiexec -ArgumentList $msiArgs -WorkingDirectory $fileFolder -PassThru if ( $ps.ExitCode -ne 0) { throw "Failed : $file" } } finally { Invoke-Dispose([ref]$ps) } } } Remove-Item $msiBat } catch { $lastError = $_ Write-Verbose $lastError $shortLogError = Get-MsiError -logFile $logFile $errMessage = ( @("MSI INSTALL '$file' failed", $arguments ) + $shortLogError ) -join "`n" throw $errMessage } } function Update-FromCompiledMsi { $msi = Get-ChildItem -path $src -Filter *.msi -Recurse | Sort-Object LastWriteTime | Where-Object DirectoryName -NE $src | Get-Path $InstallersOverride = $src New-Folder_EnsureExists $InstallersOverride $msi | Copy-Item -Destination $InstallersOverride -Force -Verbose } |