Skip to content

Conversation

@lzw29107
Copy link
Contributor

No description provided.

@9840751500
Copy link

👌

@lzw29107 lzw29107 changed the title Windows 10 22H2 December Refresh Add Windows 11 Version 24H2 Oct 3, 2024
@lzw29107
Copy link
Contributor Author

lzw29107 commented Oct 3, 2024

Update

@yauhenbarysik
Copy link

Can this branch be used to update from 23H2 to 24H2 Win11 Pro version?

@Raudrobot
Copy link

Raudrobot commented Oct 30, 2024 via email

@Raudrobot
Copy link

Propably

@Cobra11Murderer
Copy link

why not use flyby11 ? it worked perfectly for me something to check out if this isnt updated

@nondetect nondetect mentioned this pull request Nov 28, 2024
@StijnBousard
Copy link

why not use flyby11 ? it worked perfectly for me something to check out if this isnt updated

That was a good idea. I've used Flyby11 now, and the update went well! Thanks Cobra11Murderer.
source: https://github.com/builtbybel/Flyby11

@nondetect nondetect mentioned this pull request Jan 30, 2025
@lzw29107 lzw29107 mentioned this pull request Feb 27, 2025
Copy link

@evilking-76 evilking-76 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

@3p1st3m1c
Copy link

Hopefully this will be GOLD soon! We only have until October 2025 for Windows 10 23H2 and November 2025 for Windows 11 23H2! After that, no more updates.

As a side note, using this tool to upgrade to Windows 11 23H2 was perfect but the computer cannot do updates to 24H2. It does not come as an option for Windows Update since it is not hardware compliant.

Thank you for all you do. I speak for all that utilize your tool.

@nirit100
Copy link

@AveYo Is this project dead or what?

@x9nico
Copy link

x9nico commented Oct 7, 2025

Hey, maybe you could make an update for 25H2 ? :)

@lzw29107
Copy link
Contributor Author

lzw29107 commented Oct 18, 2025

Starting from 25H2, the official MCT now dynamically retrieves the link of products.cab from the update server, which requires more changes. I don't want to maintain an independent fork, so I will explain the request logic of MCT, but I may not continue to update.

Firstly, Send a POST request to https://fe3.delivery.mp.microsoft.com/UpdateMetadataService/updates/search/v1/bydeviceinfo ,with attributes like this:
{"Products":"PN=Windows.Products.Cab.amd64&V=26100.0.0.0","DeviceAttributes":"BuildFlighting=1;AttrDataVer=331;OSArchitecture=AMD64;App=Setup360;InstallationType=Client;CurrentBranch=ge_release;OSSKUId=48;DUScan=1;DUInternal=0;IsoCountryShortCode=US;HotPatchEligible=0;AppVer=10.0;MediaBranch=ge_release;OSVersion=10.0.26100.1;CompositionEditionId=Professional;EditionId=Professional;OfflineAttributesOnly=0;FlightRing=External;LCUVersion=10.0.26100.1;MediaVersion=10.0.26100.1;PreviewBuilds=1;FlightingBranchName=CanaryChannel"}
Then it responses like this:
[{"UpdateIds":["b0e9e618-4f45-4000-bf3d-dbc0f234ba15"],"FileLocations":[{"FileName":"products.cab","Size":43679,"Language":null,"Digest":"...","ContentType":"Metadata","Url":"http://tlu.dl.delivery.mp.microsoft.com/filestreamingservice/files/..."}]}]

And we can download products.cab from the metatdata url. We can also use this update id to get the full update information:
Send a GET request to https://fe3.delivery.mp.microsoft.com/UpdateMetadataService/updates/v1/{updateId}

It responses like this:
{"UpdateIdentity":{"UpdateId":"b0e9e618-4f45-4000-bf3d-dbc0f234ba15","RevisionNumber":1},"UpdateType":"Software","DeferralPolicy":"QualityUpdate","CreationDate":"2025-10-13T17:29:13.595Z","SupportUrl":null,"KnowledgebaseArticleId":"5066838","EulaId":null,"RequiresReacceptanceOfEula":false,"LocalizedProperties":[{"Language":"en","Title":"2025-10 Products.cab Update for Windows 11, version 25H2 (KB5066838)","Description":"Install this update to resolve issues in Windows. For a complete listing of the issues that are included in this update, see the associated Microsoft Knowledge Base article for more information. After you install this item, you may have to restart your computer.","MoreInfoUrl":"https://support.microsoft.com/help/5066838"}],"Prerequisites":[{"IsCategory":true,"UpdateId":"cd5ffd1e-e932-4e3a-bf74-18bf0b1bbd83","RevisionNumber":1}],"BundledUpdates":[],"EulaFiles":[]}

By the way, these ids are as the same as other updates in Microsoft update server, like UUP/legacy WU.

Hey, maybe you could make an update for 25H2 ? :)

@geissbuehler
Copy link

@lzw29107: I do not understand how to deal with the new MCT update logic ;) I have added experimental 25H2 support to my fork of your fork by adding a products.xml to the repository that was downloaded using the MediaCreationTool.exe. Also the URL for the MCT looks different than for 24H2 and I'm not sure how long this link will work. Can you have a quick look at my changes?

PS: I believe that AveYo is no more maintaining this project and I propose that you take the lead with your fork.

Thanks a lot!

@lzw29107
Copy link
Contributor Author

lzw29107 commented Oct 25, 2025

@lzw29107: I do not understand how to deal with the new MCT update logic ;) I have added experimental 25H2 support to my fork of your fork by adding a products.xml to the repository that was downloaded using the MediaCreationTool.exe. Also the URL for the MCT looks different than for 24H2 and I'm not sure how long this link will work. Can you have a quick look at my changes?

PS: I believe that AveYo is no more maintaining this project and I propose that you take the lead with your fork.

Thanks a lot!

https://download.microsoft.com/download/eb1cc454-1c9a-4c94-adf8-b30c7f3d03d1/products.xml

@starchivore
Copy link

@abbodi1406 posted this:

https://forums.mydigitallife.net/threads/windows-11-esd-repository.83747/page-17#post-1892276

Generate link for 25H2 products.cab

Command Prompt:

set _u=https://fe3.delivery.mp.microsoft.com/UpdateMetadataService/updates/search/v1/bydeviceinfo/
set _h=-H "Accept: application/json" -H "Content-Type: application/json"
set _j={"Products":"PN=Windows.Products.Cab.amd64^&V=0.0.0.0","DeviceAttributes":"DUScan=1;OSVersion=10.0.26100.1"}
curl.exe -k %_h% -d "%_j:"=\"%" "%_u%"

Windows Powershell:

$url = 'https://fe3.delivery.mp.microsoft.com/UpdateMetadataService/updates/search/v1/bydeviceinfo/'
$hdr = [ordered]@{'Accept' = "application/json"; 'Content-Type' = "application/json"}
$bdy = @"
{"Products":"PN=Windows.Products.Cab.amd64&V=0.0.0.0","DeviceAttributes":"DUScan=1;OSVersion=10.0.26100.1"}
"@

$resp = Invoke-RestMethod -UseBasicParsing -Method POST -Uri $url -Headers $hdr -Body $bdy
$resp.FileLocations

yes, you can add the infamous DUInternal attribute to get info about future releases
https://fe3.delivery.mp.microsoft.c...dates/v1/e51f9774-53f9-4bbe-8828-668bf06db449


@atplsx shared getproducts.ps1:

https://forums.mydigitallife.net/threads/windows-11-esd-repository.83747/page-18#post-1893509

Thanks to @abbodi1406
I adapted the script he provided, adding a more functional interactive menu.

[CmdletBinding()]
param()

if ($PSVersionTable.PSVersion.Major -le 5) {
    [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
    [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
}

$script:OSVersion = '10.0.26100.1'
$script:MediaVersion = '10.0.26200.6899'
$script:Products = 'PN=Windows.Products.Cab.amd64&V=26100.0.0.0'
$script:EditionId = 'Professional'
$script:OSArchitecture = 'AMD64'
$script:IsoCountry = 'US'
$script:BaseUrl = 'https://fe3.delivery.mp.microsoft.com/UpdateMetadataService'

function Test-ArrayOrSingle {
    [CmdletBinding()]
    [OutputType([object])]
    param(
        [Parameter(Mandatory)]
        [AllowNull()]
        [object]$InputObject
    )

    if ($null -eq $InputObject) {
        return $null
    }

    if ($InputObject -is [array] -and $InputObject.Count -gt 0) {
        return $InputObject[0]
    }

    return $InputObject
}

function Show-Menu {
    [CmdletBinding()]
    param()

    Clear-Host
    Write-Information -MessageData "`n============ Products.cab Update Tool ============" -InformationAction Continue
    Write-Information -MessageData "`nCurrent Settings:" -InformationAction Continue
    Write-Information -MessageData "  OSVersion      : $script:OSVersion" -InformationAction Continue
    Write-Information -MessageData "  MediaVersion   : $script:MediaVersion" -InformationAction Continue
    Write-Information -MessageData "  Products       : $script:Products" -InformationAction Continue
    Write-Information -MessageData "  EditionId      : $script:EditionId" -InformationAction Continue
    Write-Information -MessageData "  OSArchitecture : $script:OSArchitecture" -InformationAction Continue
    Write-Information -MessageData "  IsoCountry     : $script:IsoCountry" -InformationAction Continue
    Write-Information -MessageData "`nMenu:" -InformationAction Continue
    Write-Information -MessageData '  1: Search for updates' -InformationAction Continue
    Write-Information -MessageData '  2: Change OS/Media version' -InformationAction Continue
    Write-Information -MessageData '  3: Change product query' -InformationAction Continue
    Write-Information -MessageData '  4: Change edition and architecture' -InformationAction Continue
    Write-Information -MessageData '  5: Change country code' -InformationAction Continue
    Write-Information -MessageData '  6: Get products.cab file' -InformationAction Continue
    Write-Information -MessageData '  7: Reset to defaults' -InformationAction Continue
    Write-Information -MessageData '  Q: Quit' -InformationAction Continue
    Write-Information -MessageData '==================================================' -InformationAction Continue
}

function Get-ProductsCabUpdate {
    [CmdletBinding()]
    [OutputType([string], [void])]
    param(
        [Parameter()]
        [switch]$ReturnUrl
    )

    try {
        if (-not $ReturnUrl) {
            Write-Information -MessageData "`n[1/3] Searching..." -InformationAction Continue
        }

        $searchUrl = "$script:BaseUrl/updates/search/v1/bydeviceinfo"
        $searchHeaders = @{
            'Content-Type' = 'application/json'
            'Accept'       = '*/*'
        }

        $deviceAttrs = @(
            "MediaVersion=$script:MediaVersion"
            'MediaBranch=ge_release'
            'CompositionEditionId=Enterprise'
            "OSVersion=$script:OSVersion"
            'HotPatchEligible=0'
            'AttrDataVer=331'
            "EditionId=$script:EditionId"
            'DUScan=1'
            'OfflineAttributesOnly=0'
            'InstallationType=Client'
            'App=Setup360'
            'BuildFlighting=0'
            'CurrentBranch=ge_release'
            'DUInternal=0'
            'OSSKUId=48'
            'FlightRing=Retail'
            'AppVer=10.0'
            'PreviewBuilds=0'
            "OSArchitecture=$script:OSArchitecture"
            "LCUVersion=$script:MediaVersion"
            "IsoCountryShortCode=$script:IsoCountry"
        ) -join ';'

        $searchBodyObj = @{
            Products         = $script:Products
            DeviceAttributes = $deviceAttrs
        }

        $searchBody = $searchBodyObj | ConvertTo-Json -Compress

        $invokeParams = @{
            Method      = 'POST'
            Uri         = $searchUrl
            Headers     = $searchHeaders
            Body        = $searchBody
            ErrorAction = 'Stop'
        }

        if ($PSVersionTable.PSVersion.Major -ge 7) {
            $invokeParams['SkipCertificateCheck'] = $true
        }

        $searchResponse = Invoke-RestMethod @invokeParams

        if (-not $searchResponse) {
            if (-not $ReturnUrl) {
                Write-Warning 'No updates found.'
            }
            return $null
        }

        $firstResult = Test-ArrayOrSingle -InputObject $searchResponse

        if (-not $firstResult -or -not $firstResult.UpdateIds) {
            if (-not $ReturnUrl) {
                Write-Warning 'No UpdateIds returned.'
            }
            return $null
        }

        $updateId = Test-ArrayOrSingle -InputObject $firstResult.UpdateIds

        if (-not $updateId) {
            if (-not $ReturnUrl) {
                Write-Warning 'UpdateId is null.'
            }
            return $null
        }

        if (-not $firstResult.FileLocations) {
            if (-not $ReturnUrl) {
                Write-Warning 'No FileLocations returned.'
            }
            return $null
        }

        $fileLocation = Test-ArrayOrSingle -InputObject $firstResult.FileLocations

        if (-not $fileLocation) {
            if (-not $ReturnUrl) {
                Write-Warning 'FileLocation is null.'
            }
            return $null
        }

        if (-not $ReturnUrl) {
            Write-Information -MessageData "UpdateId     : $updateId" -InformationAction Continue
            Write-Information -MessageData "FileName     : $($fileLocation.FileName)" -InformationAction Continue
            Write-Information -MessageData "Size         : $($fileLocation.Size) bytes" -InformationAction Continue
            Write-Information -MessageData "ContentType  : $($fileLocation.ContentType)" -InformationAction Continue
            Write-Information -MessageData "Digest       : $($fileLocation.Digest)" -InformationAction Continue
            Write-Information -MessageData "`n[2/3] Fetching details..." -InformationAction Continue
        }

        $detailUrl = "$script:BaseUrl/updates/v1/$updateId"
        $detailHeaders = @{ 'Accept' = '*/*' }

        $detailParams = @{
            Method      = 'GET'
            Uri         = $detailUrl
            Headers     = $detailHeaders
            ErrorAction = 'Stop'
        }

        if ($PSVersionTable.PSVersion.Major -ge 7) {
            $detailParams['SkipCertificateCheck'] = $true
        }

        $detailResponse = Invoke-RestMethod @detailParams

        if (-not $ReturnUrl) {
            $localizedProp = $null

            if ($detailResponse.LocalizedProperties) {
                $localizedProp = Test-ArrayOrSingle -InputObject $detailResponse.LocalizedProperties
            }

            Write-Information -MessageData "UpdateId          : $($detailResponse.UpdateIdentity.UpdateId)" -InformationAction Continue
            Write-Information -MessageData "RevisionNumber    : $($detailResponse.UpdateIdentity.RevisionNumber)" -InformationAction Continue
            Write-Information -MessageData "UpdateType        : $($detailResponse.UpdateType)" -InformationAction Continue
            Write-Information -MessageData "CreationDate      : $($detailResponse.CreationDate)" -InformationAction Continue
            Write-Information -MessageData "KB Article        : $($detailResponse.KnowledgebaseArticleId)" -InformationAction Continue

            if ($localizedProp) {
                Write-Information -MessageData "Title             : $($localizedProp.Title)" -InformationAction Continue
                Write-Information -MessageData "Description       : $($localizedProp.Description)" -InformationAction Continue
                Write-Information -MessageData "MoreInfoUrl       : $($localizedProp.MoreInfoUrl)" -InformationAction Continue
            }

            Write-Information -MessageData "`n[3/3] HEAD request..." -InformationAction Continue
        }

        if (-not $fileLocation.Url) {
            if (-not $ReturnUrl) {
                Write-Warning 'Download URL is null.'
            }
            return $null
        }

        $downloadUrl = $fileLocation.Url

        $prevProgressPreference = $ProgressPreference
        $ProgressPreference = 'SilentlyContinue'

        try {
            $headParams = @{
                Method      = 'Head'
                Uri         = $downloadUrl
                ErrorAction = 'Stop'
            }

            if ($PSVersionTable.PSVersion.Major -ge 7) {
                $headParams['SkipCertificateCheck'] = $true
            }

            $headResponse = Invoke-WebRequest @headParams

            if (-not $ReturnUrl) {
                Write-Information -MessageData "Status Code       : $($headResponse.StatusCode) $($headResponse.StatusDescription)" -InformationAction Continue

                $contentType = Test-ArrayOrSingle -InputObject $headResponse.Headers['Content-Type']
                if ($contentType) {
                    Write-Information -MessageData "Content-Type      : $contentType" -InformationAction Continue
                }

                $contentLength = Test-ArrayOrSingle -InputObject $headResponse.Headers['Content-Length']
                if ($contentLength) {
                    Write-Information -MessageData "Content-Length    : $contentLength bytes" -InformationAction Continue
                }

                $lastModified = Test-ArrayOrSingle -InputObject $headResponse.Headers['Last-Modified']
                if ($lastModified) {
                    Write-Information -MessageData "Last-Modified     : $lastModified" -InformationAction Continue
                }

                $etag = Test-ArrayOrSingle -InputObject $headResponse.Headers['ETag']
                if ($etag) {
                    Write-Information -MessageData "ETag              : $etag" -InformationAction Continue
                }

                Write-Information -MessageData "`nDownload URL:" -InformationAction Continue
                Write-Information -MessageData $downloadUrl -InformationAction Continue
                Write-Information -MessageData "`nCompleted." -InformationAction Continue
            }
        }
        finally {
            $ProgressPreference = $prevProgressPreference
        }

        if ($ReturnUrl) {
            return $downloadUrl
        }

    }
    catch {
        if (-not $ReturnUrl) {
            Write-Error "Error: $($_.Exception.Message)"

            if ($_.ErrorDetails.Message) {
                Write-Information -MessageData "Details: $($_.ErrorDetails.Message)" -InformationAction Continue
            }

            if ($_.Exception.Response) {
                Write-Information -MessageData "HTTP: $($_.Exception.Response.StatusCode.value__) - $($_.Exception.Response.StatusDescription)" -InformationAction Continue
            }
        }
        return $null
    }
}

function Receive-ProductsCab {
    [CmdletBinding()]
    param()

    try {
        Write-Information -MessageData "`nRetrieving download URL..." -InformationAction Continue
        $url = Get-ProductsCabUpdate -ReturnUrl

        if (-not $url) {
            Write-Warning 'Could not retrieve download URL.'
            return
        }

        $outputPath = Join-Path -Path $PWD -ChildPath 'products.cab'
        Write-Information -MessageData "Downloading to: $outputPath" -InformationAction Continue

        $prevProgressPreference = $ProgressPreference
        $ProgressPreference = 'SilentlyContinue'

        try {
            $downloadParams = @{
                Uri         = $url
                OutFile     = $outputPath
                ErrorAction = 'Stop'
            }

            if ($PSVersionTable.PSVersion.Major -ge 7) {
                $downloadParams['SkipCertificateCheck'] = $true
            }

            Invoke-WebRequest @downloadParams

            if (Test-Path -Path $outputPath) {
                $fileInfo = Get-Item -Path $outputPath
                Write-Information -MessageData 'Download completed.' -InformationAction Continue
                Write-Information -MessageData "Size: $($fileInfo.Length) bytes" -InformationAction Continue
                Write-Information -MessageData "Path: $($fileInfo.FullName)" -InformationAction Continue
            }
            else {
                Write-Error 'Download failed - file not found.'
            }
        }
        finally {
            $ProgressPreference = $prevProgressPreference
        }

    }
    catch {
        Write-Error "Download error: $($_.Exception.Message)"
    }
}

function Set-OSMediaVersion {
    [CmdletBinding(SupportsShouldProcess)]
    param()

    Write-Information -MessageData "`n--- Change OS/Media Version ---" -InformationAction Continue
    Write-Information -MessageData "Current OSVersion: $script:OSVersion" -InformationAction Continue
    $newOS = Read-Host 'New OSVersion (Enter to keep)'
    if ($newOS -and $PSCmdlet.ShouldProcess("OSVersion", "Update to $newOS")) {
        $script:OSVersion = $newOS
    }

    Write-Information -MessageData "Current MediaVersion: $script:MediaVersion" -InformationAction Continue
    $newMedia = Read-Host 'New MediaVersion (Enter to keep)'
    if ($newMedia -and $PSCmdlet.ShouldProcess("MediaVersion", "Update to $newMedia")) {
        $script:MediaVersion = $newMedia
    }

    Write-Information -MessageData "`nUpdated:" -InformationAction Continue
    Write-Information -MessageData "OSVersion    : $script:OSVersion" -InformationAction Continue
    Write-Information -MessageData "MediaVersion : $script:MediaVersion" -InformationAction Continue
}

function Set-ProductQuery {
    [CmdletBinding(SupportsShouldProcess)]
    param()

    Write-Information -MessageData "`n--- Change Product Query ---" -InformationAction Continue
    Write-Information -MessageData "Current: $script:Products" -InformationAction Continue
    Write-Information -MessageData 'Examples:' -InformationAction Continue
    Write-Information -MessageData '  PN=Windows.Products.Cab.amd64&V=26100.0.0.0' -InformationAction Continue
    Write-Information -MessageData '  PN=Windows.Products.Cab.arm64&V=26100.0.0.0' -InformationAction Continue
    $newProd = Read-Host 'New Products query (Enter to keep)'
    if ($newProd -and $PSCmdlet.ShouldProcess("Products", "Update to $newProd")) {
        $script:Products = $newProd
    }
    Write-Information -MessageData "Products: $script:Products" -InformationAction Continue
}

function Set-EditionArch {
    [CmdletBinding(SupportsShouldProcess)]
    param()

    Write-Information -MessageData "`n--- Change Edition and Architecture ---" -InformationAction Continue
    Write-Information -MessageData "Current EditionId: $script:EditionId" -InformationAction Continue
    $newEd = Read-Host 'New EditionId (Professional/Enterprise/Core) (Enter to keep)'
    if ($newEd -and $PSCmdlet.ShouldProcess("EditionId", "Update to $newEd")) {
        $script:EditionId = $newEd
    }

    Write-Information -MessageData "Current OSArchitecture: $script:OSArchitecture" -InformationAction Continue
    $newArch = Read-Host 'New OSArchitecture (AMD64/ARM64) (Enter to keep)'
    if ($newArch -and $PSCmdlet.ShouldProcess("OSArchitecture", "Update to $newArch")) {
        $script:OSArchitecture = $newArch
    }

    Write-Information -MessageData "`nUpdated:" -InformationAction Continue
    Write-Information -MessageData "EditionId      : $script:EditionId" -InformationAction Continue
    Write-Information -MessageData "OSArchitecture : $script:OSArchitecture" -InformationAction Continue
}

function Set-CountryCode {
    [CmdletBinding(SupportsShouldProcess)]
    param()

    Write-Information -MessageData "`n--- Change Country Code ---" -InformationAction Continue
    Write-Information -MessageData "Current IsoCountryShortCode: $script:IsoCountry" -InformationAction Continue
    $newCountry = Read-Host 'New IsoCountryShortCode (e.g. US/TR/DE) (Enter to keep)'
    if ($newCountry -and $PSCmdlet.ShouldProcess("IsoCountry", "Update to $newCountry")) {
        $script:IsoCountry = $newCountry
    }
    Write-Information -MessageData "IsoCountry: $script:IsoCountry" -InformationAction Continue
}

function Reset-Configuration {
    [CmdletBinding(SupportsShouldProcess)]
    param()

    if ($PSCmdlet.ShouldProcess("Configuration", "Reset to defaults")) {
        $script:OSVersion = '10.0.26100.1'
        $script:MediaVersion = '10.0.26200.6899'
        $script:Products = 'PN=Windows.Products.Cab.amd64&V=26100.0.0.0'
        $script:EditionId = 'Professional'
        $script:OSArchitecture = 'AMD64'
        $script:IsoCountry = 'US'
        Write-Information -MessageData "`nReset to defaults." -InformationAction Continue
    }
}

try {
    do {
        Show-Menu
        $selection = Read-Host "`nSelection"

        switch ($selection.ToUpper()) {
            '1' {
                Get-ProductsCabUpdate
                $null = Read-Host "`nPress Enter"
            }
            '2' {
                Set-OSMediaVersion
                $null = Read-Host "`nPress Enter"
            }
            '3' {
                Set-ProductQuery
                $null = Read-Host "`nPress Enter"
            }
            '4' {
                Set-EditionArch
                $null = Read-Host "`nPress Enter"
            }
            '5' {
                Set-CountryCode
                $null = Read-Host "`nPress Enter"
            }
            '6' {
                Receive-ProductsCab
                $null = Read-Host "`nPress Enter"
            }
            '7' {
                Reset-Configuration
                $null = Read-Host "`nPress Enter"
            }
            'Q' {
                Write-Information -MessageData "`nExiting." -InformationAction Continue
                break
            }
            default {
                Write-Warning 'Invalid selection.'
                Start-Sleep -Seconds 1
            }
        }
    } until ($selection -eq 'Q')
}
catch {
    Write-Error "Critical error: $($_.Exception.Message)"
    $null = Read-Host "`nPress Enter to exit"
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.