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
}