private/Expand-WinPEDriverPackageVMwareTools.ps1

#Requires -PSEdition Core

function Expand-WinPEDriverPackageVMwareTools {
    <#
    .SYNOPSIS
        Expands VMware Tools from an ISO image
 
    .DESCRIPTION
        Validates and mounts a VMware Tools ISO, then runs its root setup.exe as a quiet
        administrative installation into the destination directory. The function creates
        the destination when needed and dismounts an image that it successfully mounted,
        including after setup failures. Expansion failures cause a terminating error.
 
    .PARAMETER Path
        Specifies the path to the VMware Tools ISO image. The path must resolve before the
        destination directory is created.
 
    .PARAMETER DestinationPath
        Specifies the directory that receives the administrative installation. The
        function creates the directory when it does not exist.
 
    .EXAMPLE
        PS> Expand-WinPEDriverPackageVMwareTools -Path 'C:\Drivers\VMwareTools.iso' -DestinationPath 'C:\Drivers\VMwareTools'
 
        Mounts VMwareTools.iso, runs its setup.exe administrative installation, dismounts
        the image, and returns C:\Drivers\VMwareTools.
 
    .INPUTS
        None. This function does not accept pipeline input.
 
    .OUTPUTS
        System.IO.DirectoryInfo. Returns the destination directory after setup.exe exits
        successfully.
 
    .NOTES
        Author: David Segura
        Company: Recast Software
        Version: 1.0.0
        Date: 2026-08-28
 
        Dependencies:
          PowerShell Modules: Storage
          Executables: setup.exe from the mounted VMware Tools image
          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)) {
        $PSCmdlet.ThrowTerminatingError(
            [System.Management.Automation.ErrorRecord]::new(
                [System.IO.FileNotFoundException]::new("ISO file not found: $Path"),
                'IsoFileNotFound',
                [System.Management.Automation.ErrorCategory]::ObjectNotFound,
                $Path
            )
        )
    }

    if (-not (Test-Path -Path $DestinationPath)) {
        New-Item -ItemType Directory -Path $DestinationPath -Force | Out-Null
    }

    # Track mount success separately so the finally block only dismounts images mounted here.
    $diskImage = $null
    try {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Mounting ISO: $Path"
        $diskImage = Mount-DiskImage -ImagePath $Path -PassThru -ErrorAction Stop
        $driveLetter = ($diskImage | Get-Volume).DriveLetter
        # The administrative installer cannot be located until Windows assigns a volume letter.
        if (-not $driveLetter) {
            throw "Could not determine drive letter for mounted ISO '$Path'."
        }

        $setupExe = "${driveLetter}:\setup.exe"
        # VMware Tools media is expected to expose setup.exe at the ISO root.
        if (-not (Test-Path -Path $setupExe)) {
            throw "setup.exe not found on mounted ISO at '$setupExe'."
        }

        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Running administrative install: $setupExe /a `"$DestinationPath`" /s /v/qn"
        $process = Start-Process -FilePath $setupExe -ArgumentList "/a `"$DestinationPath`" /s /v/qn" -Wait -PassThru -NoNewWindow -ErrorAction Stop

        if ($process.ExitCode -ne 0) {
            throw "VMware Tools administrative install exited with code $($process.ExitCode)."
        }

        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Administrative install completed to '$DestinationPath'"
        Get-Item -Path $DestinationPath
    }
    catch {
        $PSCmdlet.ThrowTerminatingError(
            [System.Management.Automation.ErrorRecord]::new(
                [System.InvalidOperationException]::new(
                    "VMware Tools ISO expansion failed for '$Path': $($_.Exception.Message)"
                ),
                'VmwareIsoExpandFailed',
                [System.Management.Automation.ErrorCategory]::InvalidResult,
                $Path
            )
        )
    }
    finally {
        # Release the mounted media even when setup fails or returns a nonzero exit code.
        if ($diskImage) {
            Dismount-DiskImage -ImagePath $Path -ErrorAction SilentlyContinue | Out-Null
            Write-Verbose "[$($MyInvocation.MyCommand.Name)] Dismounted ISO: $Path"
        }
    }
}