private/Expand-WinPEDriverPackageIso.ps1
|
#Requires -PSEdition Core function Expand-WinPEDriverPackageIso { <# .SYNOPSIS Expands an ISO image to a destination directory .DESCRIPTION Validates that the source ISO exists, creates the destination directory when needed, mounts the image, and copies its contents to the destination. The function dismounts an image that it successfully mounted even when copying fails. A mount, volume discovery, or copy failure causes a terminating error. .PARAMETER Path Specifies the path to the ISO image. The path must resolve before the destination directory is created. .PARAMETER DestinationPath Specifies the directory that receives the ISO contents. The function creates the directory when it does not exist. .EXAMPLE PS> Expand-WinPEDriverPackageIso -Path 'C:\Drivers\WinPE.iso' -DestinationPath 'C:\Drivers\WinPE' Mounts WinPE.iso, copies its contents to C:\Drivers\WinPE, dismounts the image, and returns the destination directory. .INPUTS None. This function does not accept pipeline input. .OUTPUTS System.IO.DirectoryInfo. Returns the destination directory after the ISO contents are copied successfully. .NOTES Author: David Segura Company: Recast Software Version: 1.0.0 Date: 2026-08-28 Dependencies: PowerShell Modules: Storage 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 whether mounting succeeded so cleanup does not attempt to dismount an unrelated image. $diskImage = $null try { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Mounting ISO: $Path" $diskImage = Mount-DiskImage -ImagePath $Path -PassThru -ErrorAction Stop $driveLetter = ($diskImage | Get-Volume).DriveLetter # A mounted image without a volume cannot provide a filesystem source to copy. if (-not $driveLetter) { throw "Could not determine drive letter for mounted ISO '$Path'." } $sourceRoot = "${driveLetter}:\" Write-Verbose "[$($MyInvocation.MyCommand.Name)] Copying ISO contents from '$sourceRoot' to '$DestinationPath'" Copy-Item -Path "${sourceRoot}*" -Destination $DestinationPath -Recurse -Force Write-Verbose "[$($MyInvocation.MyCommand.Name)] ISO extraction complete: $DestinationPath" Get-Item -Path $DestinationPath } catch { $PSCmdlet.ThrowTerminatingError( [System.Management.Automation.ErrorRecord]::new( [System.InvalidOperationException]::new( "ISO expansion failed for '$Path': $($_.Exception.Message)" ), 'IsoExpandFailed', [System.Management.Automation.ErrorCategory]::InvalidResult, $Path ) ) } finally { # Always release a successfully mounted image, including after copy failures. if ($diskImage) { Dismount-DiskImage -ImagePath $Path -ErrorAction SilentlyContinue | Out-Null Write-Verbose "[$($MyInvocation.MyCommand.Name)] Dismounted ISO: $Path" } } } |