Public/MSCatalog.ps1

function Convert-PNPDeviceIDtoGuid {
    [CmdLetBinding()]
    param (
        [Parameter(Mandatory = $true)]
        [string]$PNPDeviceID
    )

    #$GuidPattern = '{[-0-9A-F]+?}'
    #($DeviceID | Select-String -Pattern $GuidPattern -AllMatches | Select-Object -ExpandProperty Matches | Select-Object -ExpandProperty Value)

    $GuidPattern = '\{?(([0-9a-f]){8}-([0-9a-f]){4}-([0-9a-f]){4}-([0-9a-f]){4}-([0-9a-f]){12})\}?'
    ($PNPDeviceID | Select-String -Pattern $GuidPattern -AllMatches | Select-Object -ExpandProperty Matches | Select-Object -ExpandProperty Value)
}
function Get-SystemFirmwareDevice {
    [CmdLetBinding()]
    param ()

    Get-CimInstance -ClassName Win32_PnpEntity | Where-Object ClassGuid -eq '{f2e7dd72-6468-4e36-b6f1-6488f42c1b52}' | Where-Object Caption -match 'System'
}

function Get-SystemFirmwareResource {
    [CmdLetBinding()]
    param ()

    $UefiFirmwareDevice = Get-SystemFirmwareDevice

    if ($UefiFirmwareDevice) {
        Convert-PNPDeviceIDtoGuid -PNPDeviceID $UefiFirmwareDevice.PNPDeviceID
    }
}
function Get-SystemFirmwareUpdate {
    #=======================================================================
    # 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
    }

    Block-PSModuleNotInstalled -ModuleName MSCatalog

    Get-MSCatalogUpdate -Search (Get-SystemFirmwareResource) -SortBy LastUpdated -Descending | Select-Object LastUpdated,Title,Version,Size,Guid -First 1 -ErrorAction Ignore
}
function Save-SystemFirmwareUpdate {
    [CmdLetBinding()]
    param (
        [String] $DestinationDirectory = "$env:TEMP\SystemFirmwareUpdate"
    )
    #=======================================================================
    # 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
    }
    #=======================================================================
    # Block
    #=======================================================================
    Block-PSModuleNotInstalled -ModuleName MSCatalog
    #=======================================================================
    # Get-SystemFirmwareUpdate

<# Write-Host -ForegroundColor DarkGray "UEFI Firmware PNPDeviceID: $($SystemFirmwareUpdate.PNPDeviceID)"
 
    $PNPDeviceGuid = Convert-PNPDeviceIDtoGuid -PNPDeviceID $SystemFirmwareUpdate.PNPDeviceID
    Write-Host -ForegroundColor DarkGray "UEFI Firmware Guid: $PNPDeviceGuid"
 
    $CatalogUpdate = Get-MSCatalogUpdate -Search $PNPDeviceGuid -SortBy LastUpdated -Descending |`
    Select-Object LastUpdated,Title,Version,Size,Guid -First 1 -ErrorAction Ignore #>

    #=======================================================================
    $SystemFirmwareUpdate = Get-SystemFirmwareUpdate

    if ($SystemFirmwareUpdate.Guid) {
        Write-Host -ForegroundColor DarkGray "$($SystemFirmwareUpdate.Title) version $($SystemFirmwareUpdate.Version)"
        Write-Host -ForegroundColor DarkGray "Version $($SystemFirmwareUpdate.Version) Size: $($SystemFirmwareUpdate.Size)"
        Write-Host -ForegroundColor DarkGray "Last Updated $($SystemFirmwareUpdate.LastUpdated)"
        Write-Host -ForegroundColor DarkGray "UpdateID: $($SystemFirmwareUpdate.Guid)"
        Write-Host -ForegroundColor DarkGray ""
    }

    if ($SystemFirmwareUpdate) {
        $SystemFirmwareUpdateFile = Save-UpdateCatalog -Guid $SystemFirmwareUpdate.Guid -DestinationDirectory $DestinationDirectory
        if ($SystemFirmwareUpdateFile) {
            expand.exe "$($SystemFirmwareUpdateFile.FullName)" -F:* "$DestinationDirectory"
            Remove-Item $SystemFirmwareUpdateFile.FullName | Out-Null
            if ($env:SystemDrive -eq 'X:') {
                #Write-Host -ForegroundColor DarkGray "You can install the firmware by running the following command"
                #Write-Host -ForegroundColor DarkGray "Add-WindowsDriver -Path C:\ -Driver $DestinationDirectory"
            }
            else {
                #Write-Host -ForegroundColor DarkGray "Make sure Bitlocker is suspended first before installing the Firmware Driver"
                if (Test-Path "$DestinationDirectory\firmware.inf") {
                    #Write-Host -ForegroundColor DarkGray "Right click on $DestinationDirectory\firmware.inf and Install"
                }
            }
        }
        else {
            Write-Warning "Could not find a UEFI Firmware update for this HardwareID"
        }
    }
    else {
        Write-Warning "Could not find a UEFI Firmware HardwareID"
    }
}
function Save-MsUp {
    [CmdLetBinding()]
    param (
        [ValidateSet('Windows 10','Windows Server','Windows Server 2016','Windows Server 2019')]
        [Alias('OperatingSystem')]
        [string]$OS = 'Windows 10',

        [ValidateSet('x64','x86')]
        [Alias('Architecture')]
        [string]$Arch = 'x64',

        [ValidateSet('21H1','20H2',2004,1909,1903,1809,1803,1709,1703,1607,1511,1507)]
        [string]$Build = '21H1',

        [ValidateSet('LCU','SSU','DotNetCU')]
        [string]$Category = 'LCU',

        [ValidateSet('Preview')]
        [string[]]$Include,

        [string]$DestinationDirectory = "$env:TEMP\MSCUpdate",

        [switch]$Latest
    )
    #=======================================================================
    # 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
    }
    #=======================================================================
    # Block
    #=======================================================================
    Block-PSModuleNotInstalled -ModuleName MSCatalog
    #=======================================================================
    # Details
    #=======================================================================
    Write-Host -ForegroundColor DarkGray "OperatingSystem: $OS"
    Write-Host -ForegroundColor DarkGray "Architecture: $Arch"
    Write-Host -ForegroundColor DarkGray "Category: $Category"
    #=======================================================================
    # Category
    #=======================================================================
    if ($Category -eq 'LCU') {
        $SearchString = "Cumulative Update $OS"
    }
    if ($Category -eq 'SSU') {
        $SearchString = "Servicing Stack Update $OS"
    }
    if ($Category -eq 'DotNetCU') {
        $SearchString = "Framework $OS"
    }
    if ($OS -eq 'Windows 10') {
        Write-Host -ForegroundColor DarkGray "Build: $Build"
        $SearchString = "$SearchString $Build $Arch"
    }
    elseif ($OS -eq 'Windows Server') {
        Write-Host -ForegroundColor DarkGray "Build: $Build"
        $SearchString = "$SearchString $Build $Arch"
    }
    else {
        $SearchString = "$SearchString $Arch"
    }
    #=======================================================================
    # Go
    #=======================================================================
    $CatalogUpdate = Get-MSCatalogUpdate -Search $SearchString -SortBy "Title" -AllPages -Descending |`
    Sort-Object LastUpdated -Descending |`
    Select-Object LastUpdated,Classification,Title,Size,Products,Guid
    #=======================================================================
    # Exclude
    #=======================================================================
    $CatalogUpdate = $CatalogUpdate | Where-Object {$_.Title -notmatch 'arm64'}
    $CatalogUpdate = $CatalogUpdate | Where-Object {$_.Title -notmatch 'Dynamic'}
    #=======================================================================
    # OperatingSystem
    #=======================================================================
    if ($OS -eq 'Windows 10') {
        $CatalogUpdate = $CatalogUpdate | Where-Object {$_.Title -match 'Windows 10'}
        $CatalogUpdate = $CatalogUpdate | Where-Object {$_.Products -notmatch 'Windows Server'}
        if ($Category -eq 'LCU') {
            $CatalogUpdate = $CatalogUpdate | Where-Object {$_.Title -match "Cumulative Update for Windows 10 Version $Build"}
        }
        if ($Category -eq 'SSU') {
            $CatalogUpdate = $CatalogUpdate | Where-Object {$_.Title -match "Servicing Stack Update for Windows 10 Version $Build"}
        }
    }
    if ($OS -eq 'Windows Server') {
        $CatalogUpdate = $CatalogUpdate | Where-Object {$_.Products -eq 'Windows Server, version 1903 and later'}
    }
    if ($OS -eq 'Windows Server 2016') {
        $CatalogUpdate = $CatalogUpdate | Where-Object {$_.Products -eq 'Windows Server 2016'}
    }
    if ($OS -eq 'Windows Server 2019') {
        $CatalogUpdate = $CatalogUpdate | Where-Object {$_.Products -eq 'Windows Server 2019'}
    }
    #=======================================================================
    # Category
    #=======================================================================
    if ($Category -eq 'LCU') {
        $CatalogUpdate = $CatalogUpdate | Where-Object {$_.Title -notmatch '.NET'}
    }
    if ($Category -eq 'DotNetCU') {
        $CatalogUpdate = $CatalogUpdate | Where-Object {$_.Title -match "Framework"}
    }
    if ($Include -contains 'Preview') {
        Write-Host -ForegroundColor DarkGray "Include Preview Updates: True"
    }
    else {
        Write-Host -ForegroundColor DarkGray "Include Preview Updates: False"
        $CatalogUpdate = $CatalogUpdate | Where-Object {$_.Title -notmatch 'Preview'}
    }
    #=======================================================================
    # Select
    #=======================================================================
    if ($Latest.IsPresent) {
        $CatalogUpdate = $CatalogUpdate | Select-Object -First 1
    }
    else {
        $CatalogUpdate = $CatalogUpdate | Out-GridView -Title 'Select a Microsoft Update to download' -PassThru
    }
    #=======================================================================
    # Download
    #=======================================================================
    foreach ($Update in $CatalogUpdate) {
        Save-UpdateCatalog -Guid $Update.Guid -DestinationDirectory $DestinationDirectory
    }
    
<# if ($CatalogUpdate) {
        explorer.exe $DestinationDirectory
    } #>

    #=======================================================================
}