private/Find-MountedWindowsMedia.ps1
|
#Requires -Version 7.4 function Find-MountedWindowsMedia { <# .SYNOPSIS Finds Windows installation images on mounted media .DESCRIPTION Requires administrator privileges, then scans filesystem drives D through Z for install.wim and install.esd in Sources, x64\Sources, and x86\Sources directories. Each discovered file is projected with a MediaRoot property identifying the root that contains its Sources hierarchy. A warning is written and no objects are returned when the process is not elevated. .EXAMPLE PS> Find-MountedWindowsMedia Returns installation image rows discovered on mounted Windows media. .INPUTS None. This function does not accept pipeline input. .OUTPUTS System.Management.Automation.PSCustomObject. Returns zero or more projected file objects with MediaRoot and the properties of the source System.IO.FileInfo object. .NOTES Author: David Segura Company: Recast Software Version: 0.1.0 Date: 2026-08-28 Dependencies: Module Functions: Test-IsAdministrator DotNet Classes: System.Collections.Generic.List[System.Management.Automation.PSObject] #> [CmdletBinding()] param () if (-not (Test-IsAdministrator)) { Write-Warning "[$(Get-Date -Format s)] Must be run with Administrator privileges" return } Write-Verbose "[$($MyInvocation.MyCommand.Name)] Scanning PSDrives for Windows installation media" # Skip the system drive and non-drive filesystem providers to limit the scan to mounted media. $WindowsMediaDrives = Get-PSDrive -PSProvider 'FileSystem' | Where-Object { ($_.Name).Length -eq 1 } | Where-Object { $_.Name -match '^[D-Z]' } | Where-Object { $_.Root -match '^[D-Z]:\\' } Write-Verbose "[$($MyInvocation.MyCommand.Name)] Found $($WindowsMediaDrives.Count) candidate PSDrives" $WindowsMediaSources = [System.Collections.Generic.List[PSObject]]::new() foreach ($Drive in $WindowsMediaDrives) { # Multi-architecture media can place Sources below x64 or x86 instead of at its root. $searchPaths = @( "$($Drive.Root)Sources" "$($Drive.Root)x64\Sources" "$($Drive.Root)x86\Sources" ) foreach ($searchPath in $searchPaths) { if (Test-Path $searchPath) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Checking $searchPath" # Attach the media root because callers need both the image and its sibling media files. $found = Get-ChildItem "$searchPath\*" -Include install.wim, install.esd -ErrorAction SilentlyContinue | Select-Object -Property @{Name = 'MediaRoot'; Expression = { (Get-Item $_.Directory).Parent.FullName } }, * if ($found) { foreach ($item in $found) { $WindowsMediaSources.Add($item) } } } } } if ($WindowsMediaSources.Count -gt 0) { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Found $($WindowsMediaSources.Count) Windows media source(s)" return $WindowsMediaSources } else { Write-Verbose "[$($MyInvocation.MyCommand.Name)] No Windows installation media found" return $null } } |