private/Expand-WinPEDriverPackageMsi.ps1
|
#Requires -PSEdition Core function Expand-WinPEDriverPackageMsi { <# .SYNOPSIS Expands an MSI package by using an administrative installation .DESCRIPTION Validates that the source MSI exists, creates the destination directory when needed, and invokes msiexec.exe in quiet administrative-install mode. A nonzero exit code causes a terminating error only when no files were extracted. .PARAMETER Path Specifies the path to the MSI package. The path must identify an existing file before the destination directory is created. .PARAMETER DestinationPath Specifies the directory that receives the extracted package files. The function creates the directory when it does not exist. .EXAMPLE PS> Expand-WinPEDriverPackageMsi -Path 'C:\Drivers\WinPE.msi' -DestinationPath 'C:\Drivers\WinPE' Performs a quiet administrative installation of WinPE.msi into C:\Drivers\WinPE and returns the destination directory when files are extracted. .INPUTS None. This function does not accept pipeline input. .OUTPUTS System.IO.DirectoryInfo. Returns the destination directory when extraction succeeds or produces files despite a nonzero msiexec.exe exit code. .NOTES Author: David Segura Company: Recast Software Version: 1.0.0 Date: 2026-08-28 Dependencies: Executables: msiexec.exe DotNet Classes: System.IO.DirectoryInfo, System.IO.FileNotFoundException, System.InvalidOperationException, System.Management.Automation.ErrorCategory, System.Management.Automation.ErrorRecord #> [CmdletBinding()] [OutputType([System.IO.DirectoryInfo])] param ( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$Path, [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$DestinationPath ) if (-not (Test-Path -Path $Path -PathType Leaf)) { $PSCmdlet.ThrowTerminatingError( [System.Management.Automation.ErrorRecord]::new( [System.IO.FileNotFoundException]::new("MSI file not found: $Path"), 'MsiFileNotFound', [System.Management.Automation.ErrorCategory]::ObjectNotFound, $Path ) ) } if (-not (Test-Path -Path $DestinationPath)) { New-Item -ItemType Directory -Path $DestinationPath -Force | Out-Null } Write-Verbose "[$($MyInvocation.MyCommand.Name)] Expanding MSI '$Path' to '$DestinationPath'" $process = Start-Process -FilePath 'msiexec.exe' ` -ArgumentList @('/a', "`"$Path`"", "targetdir=`"$DestinationPath`"", '/qn') ` -NoNewWindow -Wait -PassThru # Some vendor MSIs return a nonzero code after successfully laying down their files. if ($process.ExitCode -ne 0) { $expandedFiles = Get-ChildItem -Path $DestinationPath -Recurse -File -ErrorAction SilentlyContinue # Treat the exit code as fatal only when extraction produced no usable output. if (-not $expandedFiles) { $PSCmdlet.ThrowTerminatingError( [System.Management.Automation.ErrorRecord]::new( [System.InvalidOperationException]::new("MSI expansion failed for '$Path' with exit code $($process.ExitCode)."), 'MsiExpandFailed', [System.Management.Automation.ErrorCategory]::InvalidResult, $Path ) ) } } Get-Item -Path $DestinationPath } |