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
    }
}