Public/Functions/MicrosoftCatalog/Save-MsUpCatDriver.ps1

function Save-MsUpCatDriver {
    [CmdletBinding(DefaultParameterSetName = 'ByPNPClass')]
    param (
        [System.String]$DestinationDirectory,

        [Parameter(ParameterSetName = 'ByHardwareID')]
        [System.String[]]$HardwareID,

        [Parameter(ParameterSetName = 'ByPNPClass')]
        [ValidateSet('DiskDrive','Display','Net','SCSIAdapter','SecurityDevices','USB')]
        [System.String]$PNPClass
    )
    #=================================================
    if (!($DestinationDirectory)) {
        Write-Warning 'Set the DestinationDirectory parameter to download the Drivers'
    }
    else {
        if (!(Test-Path $DestinationDirectory)){
            New-Item -Path $DestinationDirectory -ItemType Directory -Force | Out-Null
        }
    }
    #Grab OSDCloud USB Flash Drive Info
    $OSDCloudUSB = Get-Volume.usb | Where-Object {($_.FileSystemLabel -match 'OSDCloud') -or ($_.FileSystemLabel -match 'BHIMAGE')} | Select-Object -First 1
    if ($OSDCloudUSB){
        $MSUpCatDriversOSDCloudUSBPath =  "$($OSDCloudUSB.DriveLetter):\OSDCloud\MsUpCatDrivers"
    }
    #=================================================
    # MSCatalog PowerShell Module
    # Ryan-Jan
    # https://github.com/ryan-jan/MSCatalog
    # This excellent work is a good way to gather information from MS
    # Catalog
    #=================================================
<# if (!(Get-Module -ListAvailable -Name MSCatalog)) {
        Install-Module MSCatalog -Force -ErrorAction Ignore
    } #>

    #=================================================
    #$HardwareIDPattern = 'VEN_([0-9a-f]){4}&DEV_([0-9a-f]){4}&SUBSYS_([0-9a-f]){8}'
    $HardwareIDPattern = 'v[ei][dn]_([0-9a-f]){4}&[pd][ie][dv]_([0-9a-f]){4}'
    $SurfaceIDPattern = 'mshw0[0-1]([0-9]){2}'

    if (Test-MicrosoftUpdateCatalog) {
        #=================================================
        # ByPNPClass
        #=================================================
        if ($PSCmdlet.ParameterSetName -eq 'ByPNPClass') {
            $Params = @{
                ClassName = 'Win32_PnpEntity' 
                Property = 'Name','Description','DeviceID','HardwareID','ClassGuid','Manufacturer','PNPClass'
            }
            $Devices = Get-CimInstance @Params

            if ($Devices) {
                if ($PNPClass -match 'Display') {
                    $Devices = $Devices | Where-Object {($_.Name -match 'Video') -or ($_.PNPClass -match 'Display')}
                }
                elseif ($PNPClass -match 'Net') {
                    $Devices = $Devices | Where-Object {($_.Name -match 'Network') -or ($_.PNPClass -match 'Net')}
                }
                elseif ($PNPClass) {
                    $Devices = $Devices | Where-Object {$_.PNPClass -match $PNPClass}
                }
                else {
                    #All Devices
                }
            }

            if ($Devices) {
                if ($PNPClass) {
                    Write-Host -ForegroundColor DarkGray "Devices were found for PNPClass $PNPClass"
                }
                
                foreach ($Item in $Devices) {
                    $FindHardwareID = $null
    
                    #See if DeviceID matches the pattern
                    Write-Host -ForegroundColor DarkGray "DeviceID: $($Item.DeviceID)"
                    $FindHardwareID = $Item.DeviceID | Select-String -Pattern $HardwareIDPattern -AllMatches | Select-Object -ExpandProperty Matches | Select-Object -ExpandProperty Value

                    if (-not ($FindHardwareID)) {
                        if ($Item.HardwareID) {
                            Write-Host -ForegroundColor DarkGray "HardwareID: $($Item.HardwareID[0])"
                            $FindHardwareID = $Item.HardwareID[0] | Select-String -Pattern $HardwareIDPattern -AllMatches | Select-Object -ExpandProperty Matches | Select-Object -ExpandProperty Value
                        }
                    }

                    if ($FindHardwareID) {
                        Write-Host -ForegroundColor Gray "Searching: $FindHardwareID"
                        $SearchString = "$FindHardwareID".Replace('&',"`%26")
                        try {
                            $WindowsUpdateDriver = Get-MsUpCat -Search "22H2+$PNPClass+$SearchString" -Descending | Select-Object LastUpdated,Title,Version,Size,Guid -First 1 -ErrorAction Ignore
                            
                            if (-not ($WindowsUpdateDriver)) {
                                $WindowsUpdateDriver = Get-MsUpCat -Search "21H2+$PNPClass+$SearchString" -Descending | Select-Object LastUpdated,Title,Version,Size,Guid -First 1 -ErrorAction Ignore
                            }
                            if (-not ($WindowsUpdateDriver)) {
                                $WindowsUpdateDriver = Get-MsUpCat -Search "Vibranium+$PNPClass+$SearchString" -Descending | Select-Object LastUpdated,Title,Version,Size,Guid -First 1 -ErrorAction Ignore
                            }
                            if (-not ($WindowsUpdateDriver)) {
                                $WindowsUpdateDriver = Get-MsUpCat -Search "1903+$PNPClass+$SearchString" -Descending | Select-Object LastUpdated,Title,Version,Size,Guid -First 1 -ErrorAction Ignore
                            }
                            if (-not ($WindowsUpdateDriver)) {
                                $WindowsUpdateDriver = Get-MsUpCat -Search "1809+$PNPClass+$SearchString" -Descending | Select-Object LastUpdated,Title,Version,Size,Guid -First 1 -ErrorAction Ignore
                            }
                            if (-not ($WindowsUpdateDriver)) {
                                $WindowsUpdateDriver = Get-MsUpCat -Search "$SearchString" -Descending | Select-Object LastUpdated,Title,Version,Size,Guid -First 1 -ErrorAction Ignore
                            }
        
                            if ($WindowsUpdateDriver.Guid) {
                                if ($Item.Name -and $Item.PNPClass) {
                                    Write-Host -ForegroundColor Cyan "$($Item.PNPClass) $($Item.Name)"
                                }
                                elseif ($Item.Name) {
                                    Write-Host -ForegroundColor Cyan "$($Item.Name)"
                                }
                                else {
                                    Write-Host -ForegroundColor Cyan $Item.DeviceID
                                }
                                Write-Host -ForegroundColor DarkGray "HardwareID: $FindHardwareID"
                                Write-Host -ForegroundColor DarkGray "SearchString: $SearchString"
            
                                Write-Host -ForegroundColor DarkGray "$($WindowsUpdateDriver.Title) version $($WindowsUpdateDriver.Version)"
                                Write-Host -ForegroundColor DarkGray "Version $($WindowsUpdateDriver.Version) Size: $($WindowsUpdateDriver.Size)"
                                Write-Host -ForegroundColor DarkGray "Last Updated $($WindowsUpdateDriver.LastUpdated)"
                                Write-Host -ForegroundColor DarkGray "UpdateID: $($WindowsUpdateDriver.Guid)"
            
                                if ($DestinationDirectory) {
                                    $DestinationPath = Join-Path $DestinationDirectory $WindowsUpdateDriver.Guid
                                    #If OSDCloud USB Attached, Check for Driver in Cache and Copy ro Local Cache
                                    if ($OSDCloudUSB){
                                        $USBCachePath = Join-Path $MSUpCatDriversOSDCloudUSBPath $WindowsUpdateDriver.Guid
                                        if (Test-Path $USBCachePath){
                                            Write-Host -ForegroundColor DarkGray "Driver already expanded at $USBCachePath, copying to $DestinationPath"
                                            Copy-Item -Path $USBCachePath -Destination $DestinationPath -Recurse -Force
                                        }
                                    }
                                    #Check if Driver is already Local Cache
                                    if (Test-Path $DestinationPath) {
                                        Write-Host -ForegroundColor DarkGray "Driver already expanded at $DestinationPath"
                                    }
                                    #Download if not already found in Local Cache
                                    else {
                                        Write-Host -ForegroundColor DarkGray "Downloading and expanding to $DestinationPath"
                                        $WindowsUpdateDriverFile = Save-UpdateCatalog -Guid $WindowsUpdateDriver.Guid -DestinationDirectory $DestinationPath
                                        if ($WindowsUpdateDriverFile) {
                                            expand.exe "$($WindowsUpdateDriverFile.FullName)" -F:* "$DestinationPath" | Out-Null
                                            Remove-Item $WindowsUpdateDriverFile.FullName | Out-Null
                                        }
                                        else {
                                            Write-Warning "Save-MsUpCatDriver: Could not find a Driver for this HardwareID"
                                        }
                                    }
                                }
                            }
                            else {
                                Write-Host -ForegroundColor Gray "No Results: $($Item.Name) $FindHardwareID"
                                #Write-Host -ForegroundColor DarkGray "HardwareID: $FindHardwareID"
                                #Write-Host -ForegroundColor DarkGray "SearchString: $SearchString"
                                #Write-Warning "Save-MsUpCatDriver: Could not find a Windows Update GUID"
                            }
                        }
                        catch{
                            Write-Host -ForegroundColor Gray "Unable to get Driver for Hardware component"
                        }   
                    }
                    else {
                        #Write-Host -ForegroundColor Gray "No Results: $FindHardwareID"
                    }
                }
            }
        }
        #=================================================
        # ByHardwareID
        #=================================================
        if ($PSCmdlet.ParameterSetName -eq 'ByHardwareID') {
            foreach ($Item in $HardwareID) {
                Write-Verbose "Save-MsUpCatDriver: ByHardwareID"
                Write-Verbose $Item

                $WindowsUpdateDriver = $null

                #See if DeviceID matches the pattern
                $FindHardwareID = $Item | Select-String -Pattern $HardwareIDPattern | Select-Object -ExpandProperty Matches | Select-Object -ExpandProperty Value

                if (-not ($FindHardwareID)) {
                    $FindHardwareID = $Item | Select-String -Pattern $SurfaceIDPattern | Select-Object -ExpandProperty Matches | Select-Object -ExpandProperty Value
                }
    
                if ($FindHardwareID) {
                    $SearchString = "$FindHardwareID".Replace('&', "`%26")

                    try {
                        Write-Verbose "Save-MsUpCatDriver Search: 23H2 $SearchString"
                        $WindowsUpdateDriver = Get-MsUpCat -Search "23H2+$SearchString" -Descending | Select-Object LastUpdated, Title, Version, Size, Guid -First 1 -ErrorAction Ignore
                    }
                    catch {
                        <#Do this if a terminating exception happens#>
                    }
                    if (-not ($WindowsUpdateDriver)) {
                        try {
                            Write-Verbose "Save-MsUpCatDriver Search: 22H2 $SearchString"
                            $WindowsUpdateDriver = Get-MsUpCat -Search "22H2+$SearchString" -Descending | Select-Object LastUpdated, Title, Version, Size, Guid -First 1 -ErrorAction Ignore
                        }
                        catch {
                            <#Do this if a terminating exception happens#>
                        }
                    }
                    if (-not ($WindowsUpdateDriver)) {
                        try {
                            Write-Verbose "Save-MsUpCatDriver Search: 21H2+$SearchString"
                            $WindowsUpdateDriver = Get-MsUpCat -Search "21H2+$SearchString" -Descending | Select-Object LastUpdated, Title, Version, Size, Guid -First 1 -ErrorAction Ignore
                        }
                        catch {
                            <#Do this if a terminating exception happens#>
                        }
                    }
                    if (-not ($WindowsUpdateDriver)) {
                        try {
                            Write-Verbose "Save-MsUpCatDriver Search: Vibranium+$SearchString"
                            $WindowsUpdateDriver = Get-MsUpCat -Search "Vibranium+$SearchString" -Descending | Select-Object LastUpdated, Title, Version, Size, Guid -First 1 -ErrorAction Ignore
                        }
                        catch {
                            <#Do this if a terminating exception happens#>
                        }
                    }
                    if (-not ($WindowsUpdateDriver)) {
                        try {
                            Write-Verbose "Save-MsUpCatDriver Search: 1903+$SearchString"
                            $WindowsUpdateDriver = Get-MsUpCat -Search "1903+$SearchString" -Descending | Select-Object LastUpdated, Title, Version, Size, Guid -First 1 -ErrorAction Ignore
                        }
                        catch {
                            <#Do this if a terminating exception happens#>
                        }
                    }
                    if (-not ($WindowsUpdateDriver)) {
                        try {
                            Write-Verbose "Save-MsUpCatDriver Search: 1809+$SearchString"
                            $WindowsUpdateDriver = Get-MsUpCat -Search "1809+$SearchString" -Descending | Select-Object LastUpdated, Title, Version, Size, Guid -First 1 -ErrorAction Ignore
                        }
                        catch {
                            <#Do this if a terminating exception happens#>
                        }
                    }

                    if ($WindowsUpdateDriver.Guid) {
                        Write-Host -ForegroundColor Cyan "$Item $($WindowsUpdateDriver.Title)"
                        Write-Host -ForegroundColor DarkGray "UpdateID: $($WindowsUpdateDriver.Guid)"
                        Write-Host -ForegroundColor DarkGray "Size: $($WindowsUpdateDriver.Size) Last Updated $($WindowsUpdateDriver.LastUpdated)"

                        #Write-Host -ForegroundColor DarkGray "HardwareID: $FindHardwareID"
                        #Write-Host -ForegroundColor DarkGray "SearchString: $SearchString"
    
                        #Write-Host -ForegroundColor DarkGray "$($WindowsUpdateDriver.Title) version $($WindowsUpdateDriver.Version)"
                        #Write-Host -ForegroundColor DarkGray "Version $($WindowsUpdateDriver.Version) Size: $($WindowsUpdateDriver.Size)"
                        #Write-Host -ForegroundColor DarkGray "Last Updated $($WindowsUpdateDriver.LastUpdated)"
    
                        if ($DestinationDirectory) {
                            $DestinationPath = Join-Path $DestinationDirectory $WindowsUpdateDriver.Guid
                            #If OSDCloud USB Attached, Check for Driver in Cache and Copy ro Local Cache
                            if ($OSDCloudUSB){
                                $USBCachePath = Join-Path $MSUpCatDriversOSDCloudUSBPath $WindowsUpdateDriver.Guid
                                if (Test-Path $USBCachePath){
                                    Write-Host -ForegroundColor DarkGray "Driver already expanded at $USBCachePath, copying to $DestinationPath"
                                    Copy-Item -Path $USBCachePath -Destination $DestinationPath -Recurse -Force
                                }
                            }
                            if (Test-Path $DestinationPath) {
                                Write-Host -ForegroundColor DarkGray "Driver already expanded at $DestinationPath"
                            }
                            else {
                                Write-Host -ForegroundColor DarkGray "Downloading and expanding to $DestinationPath"
                                $WindowsUpdateDriverFile = Save-UpdateCatalog -Guid $WindowsUpdateDriver.Guid -DestinationDirectory $DestinationPath
                                if ($WindowsUpdateDriverFile) {
                                    expand.exe "$($WindowsUpdateDriverFile.FullName)" -F:* "$DestinationPath" | Out-Null
                                    Remove-Item $WindowsUpdateDriverFile.FullName | Out-Null
                                }
                                else {
                                    Write-Warning "Save-MsUpCatDriver: Could not find a Driver for this HardwareID"
                                }
                            }
                        }
                    }
                    else {
                        Write-Host -ForegroundColor Gray "No Results: $FindHardwareID"
                    }
                }
                else {
                    Write-Host -ForegroundColor Gray "No Results: $FindHardwareID"
                }
            }
        }
        #=================================================
        # Sync Back to OSDCloudUSB
        #=================================================
        if ($Global:OSDCloud.SyncMSUpCatDriverUSB -eq $true){
            if ($OSDCloudUSB){
                #Get Size of Cached Drivers in Local Drive Cache
                if (Test-Path $DestinationDirectory){
                    $MsUpCatDriverCacheSizeGB = (Get-ChildItem $DestinationDirectory -Recurse | Measure-Object -Property Length -Sum).Sum /1GB
                    #Get Free Space on OSDCloud USB Drive (with buffer)
                    $OSDCloudUSBFree = ($OSDCloudUSB.SizeRemainingGB - 5) #Free Space with 5GB Buffer
                    #If enough Free Space, cache files on Flash Drive
                    if ($MsUpCatDriverCacheSizeGB -lt $OSDCloudUSBFree){
                        $Source      = $DestinationDirectory #Yes this can seem confusing, remember Destination is where the Drivers were downloaded orginially
                        $Destination = $MSUpCatDriversOSDCloudUSBPath #OSDCloud Flash Drive cache folder

                        Write-Host -ForegroundColor Cyan "Syncing MS Update Catalog Drivers to OSDCloud USB Cache"
                        Write-Host -ForegroundColor Gray "Transfering $([Math]::Round($MsUpCatDriverCacheSizeGB,2)) GB of MS Update Drivers to $Destination"
                        Invoke-Exe robocopy $Source $Destination *.* /s /ndl /nfl /njh /njs
                    }
                    else {
                        Write-Host -ForegroundColor Gray "Not enough Free Space on OSDCloudUSB to sync drivers"
                        Write-Host -ForegroundColor Gray "Requires $([Math]::Round(($MsUpCatDriverCacheSizeGB + 5),2)) GB, but only $($OSDCloudUSB.SizeRemainingGB) GB available"
                    }
                }
            }
            else {
                Write-Host -ForegroundColor Gray "OSDCloudUSB not detected to sync drivers back to, skipping sync"
            }
        }
    }
}