- 
      
- 
        Save likamrat/cae833a6e5b3461709f14c093c21c293 to your computer and use it in GitHub Desktop. 
| Write-Information "This script needs be run on Windows Server 2019 or 2022" | |
| If ($PSVersionTable.PSVersion.Major -ge 7){ Write-Error "This script needs be run by version of PowerShell prior to 7.0" } | |
| # Define environment variables | |
| $downloadDir = "C:\WinGet" | |
| $gitRepo = "microsoft/winget-cli" | |
| $msiFilenamePattern = "*.msixbundle" | |
| $licenseFilenamePattern = "*.xml" | |
| $releasesUri = "https://api.github.com/repos/$gitRepo/releases/latest" | |
| # Preparing working directory | |
| New-Item -Path $downloadDir -ItemType Directory | |
| Push-Location $downloadDir | |
| # Downloaing artifacts | |
| function Install-Package { | |
| param ( | |
| [string]$PackageFamilyName | |
| ) | |
| Write-Host "Querying latest $PackageFamilyName version and its dependencies..." | |
| $response = Invoke-WebRequest ` | |
| -Uri "https://store.rg-adguard.net/api/GetFiles" ` | |
| -Method "POST" ` | |
| -ContentType "application/x-www-form-urlencoded" ` | |
| -Body "type=PackageFamilyName&url=$PackageFamilyName&ring=RP&lang=en-US" -UseBasicParsing | |
| Write-Host "Parsing response..." | |
| $regex = '<td><a href=\"([^\"]*)\"[^\>]*\>([^\<]*)<\/a>' | |
| $packages = (Select-String $regex -InputObject $response -AllMatches).Matches.Groups | |
| $result = $true | |
| for ($i = $packages.Count - 1; $i -ge 0; $i -= 3) { | |
| $url = $packages[$i - 1].Value; | |
| $name = $packages[$i].Value; | |
| $extCheck = @(".appx", ".appxbundle", ".msix", ".msixbundle") | % { $x = $false } { $x = $x -or $name.EndsWith($_) } { $x } | |
| $archCheck = @("x64", "neutral") | % { $x = $false } { $x = $x -or $name.Contains("_$($_)_") } { $x } | |
| if ($extCheck -and $archCheck) { | |
| # Skip if package already exists on system | |
| $currentPackageFamilyName = (Select-String "^[^_]+" -InputObject $name).Matches.Value | |
| $installedVersion = (Get-AppxPackage "$currentPackageFamilyName*").Version | |
| $latestVersion = (Select-String "_(\d+\.\d+.\d+.\d+)_" -InputObject $name).Matches.Value | |
| if ($installedVersion -and ($installedVersion -ge $latestVersion)) { | |
| Write-Host "${currentPackageFamilyName} is already installed, skipping..." -ForegroundColor "Yellow" | |
| continue | |
| } | |
| try { | |
| Write-Host "Downloading package: $name" | |
| $tempPath = "$(Get-Location)\$name" | |
| Invoke-WebRequest -Uri $url -Method Get -OutFile $tempPath | |
| Add-AppxPackage -Path $tempPath | |
| Write-Host "Successfully installed:" $name | |
| } catch { | |
| $result = $false | |
| } | |
| } | |
| } | |
| return $result | |
| } | |
| Write-Host "`n" | |
| function Install-Package-With-Retry { | |
| param ( | |
| [string]$PackageFamilyName, | |
| [int]$RetryCount | |
| ) | |
| for ($t = 0; $t -le $RetryCount; $t++) { | |
| Write-Host "Attempt $($t + 1) out of $RetryCount..." -ForegroundColor "Cyan" | |
| if (Install-Package $PackageFamilyName) { | |
| return $true | |
| } | |
| } | |
| return $false | |
| } | |
| $licenseDownloadUri = ((Invoke-RestMethod -Method GET -Uri $releasesUri).assets | Where-Object name -like $licenseFilenamePattern ).browser_download_url | |
| $licenseFilename = ((Invoke-RestMethod -Method GET -Uri $releasesUri).assets | Where-Object name -like $licenseFilenamePattern ).name | |
| $licenseJoinPath = Join-Path -Path $downloadDir -ChildPath $licenseFilename | |
| Invoke-WebRequest -Uri $licenseDownloadUri -OutFile ( New-Item -Path $licenseJoinPath -Force ) | |
| $result = @("Microsoft.DesktopAppInstaller_8wekyb3d8bbwe") | ForEach-Object { $x = $true } { $x = $x -and (Install-Package-With-Retry $_ 3) } { $x } | |
| $msiFilename = ((Get-ChildItem -Path $downloadDir) | Where-Object name -like $msiFilenamePattern ).name | |
| $msiJoinPath = Join-Path -Path $downloadDir -ChildPath $msiFilename | |
| # Installing winget | |
| Add-ProvisionedAppPackage -Online -PackagePath $msiJoinPath -LicensePath $licenseJoinPath -Verbose | |
| Write-Host "`n" | |
| # Test if winget has been successfully installed | |
| if ($result -and (Test-Path -Path "$env:LOCALAPPDATA\Microsoft\WindowsApps\winget.exe")) { | |
| Write-Host "Congratulations! Windows Package Manager (winget) $(winget --version) installed successfully" -ForegroundColor "Green" | |
| } else { | |
| Write-Host "Oops... Failed to install Windows Package Manager (winget)" -ForegroundColor "Red" | |
| } | |
| # Cleanup | |
| Push-Location $HOME | |
| Remove-Item $downloadDir -Recurse -Force | 
you might want to use start-bitstransfer instead of invoke-webrequest for better performance.
i am currently working on a "side quest" to enable a customer with Windows Server 2022 and winget and so far the best automation experience for this unsupported scenario is undoubtly this project:
My summary:
# Create download directory
if (-not $(Test-Path -Path "C:\WinGet")) {
    New-Item -Path "C:" -Name "WinGet" -ItemType Directory -Force
}
# Dependencies
## Microsoft.UI.Xaml
$UIXamlPath = "C:\WinGet\Microsoft.UI.Xaml.zip"
$downloadUIXamlUri = "https://www.nuget.org/api/v2/package/Microsoft.UI.Xaml/2.8.6"
(New-Object System.Net.WebClient).DownloadFile($downloadUIXamlUri, $UIXamlPath)
Unblock-File -Path $UIXamlPath
Expand-Archive -Path $UIXamlPath -DestinationPath "C:\WinGet\Microsoft.UI.Xaml.2.8.6"
$UIXamlAppxPath = "C:\WinGet\Microsoft.UI.Xaml.2.8.6\tools\AppX\x64\Release\Microsoft.UI.Xaml.2.8.appx"
Add-AppxPackage -Path $UIXamlAppxPath
## Microsoft.VCLibs.x64.14.00.Desktop
$VCLibsPath = "C:\WinGet\Microsoft.VCLibs.x64.14.00.Desktop.appx"
$downloadVClibsUri = "https://aka.ms/Microsoft.VCLibs.x64.14.00.Desktop.appx"
(New-Object System.Net.WebClient).DownloadFile($downloadVClibsUri, $VCLibsPath)
Unblock-File -Path $VCLibsPath
Add-AppxPackage -Path $VCLibsPath
# Main Package
# Get the newest WinGet's version the download URL
$assetPattern = "*Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle"
$releasesUri = "https://api.github.com/repos/microsoft/winget-cli/releases/latest"
$asset = (Invoke-RestMethod -Uri $releasesUri -Method Get -ErrorAction stop).assets | Where-Object name -like $assetPattern
$downloadAssetUri = $asset.browser_download_url
# Download newest version of WinGet
$installerPath = "C:\WinGet\$($asset.name)"
(New-Object System.Net.WebClient).DownloadFile($downloadAssetUri, $installerPath)
Unblock-File -Path $installerPath
# Get the newest WinGet's license file download URL
$licensePattern = "*_License1.xml"
$license = (Invoke-RestMethod -Uri $releasesUri -Method Get -ErrorAction stop).assets | Where-Object name -like $licensePattern
$downloadLicenseUri = $license.browser_download_url
# Download license file
$licensePath = "C:\WinGet\$($license.name)"
(New-Object System.Net.WebClient).DownloadFile($downloadLicenseUri, $licensePath)
Unblock-File -Path $licensePath
# Install Package
Add-AppxPackage $installerPath
# Register Package with License
Try {
    Add-AppxProvisionedPackage -Online -PackagePath $installerPath -LicensePath $licensePath -Verbose -LogPath "C:\WinGet\DesktopAppInstaller_Install.log" #-DependencyPackagePath "$UIXamlAppxPath", "$VCLibsPath"
}
Catch {
    try {
        Add-AppxPackage -Path $installerPath -DependencyPath "$UIXamlAppxPath", "$VCLibsPath" -InstallAllResources
    }
    catch {
        Write-Output $_.Exception.Message
        Write-Output $Error[0]
    }
}
# Fix Permissions (S-1-5-32-544) Local Administrators Group (Language independent)
TAKEOWN /F "C:\Program Files\WindowsApps" /R /A /D Y
ICACLS "C:\Program Files\WindowsApps" /grant "*S-1-5-32-544:(F)" /T
# Add Environment Path
$ResolveWingetPath = Resolve-Path "C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe"
if ($ResolveWingetPath) {
    $WingetPath = $ResolveWingetPath[-1].Path
}
$ENV:PATH += ";$WingetPath"
$SystemEnvPath = [System.Environment]::GetEnvironmentVariable('PATH', [System.EnvironmentVariableTarget]::Machine)
$SystemEnvPath += ";$WingetPath;"
not sure if all of this is really required. Can you check your approach with the one done with the linked GitHub @cquresphere
The most recent versions of powershell don't work well with .DownloadFile() so I had to resort to 'Invoke-WebRequest'
# inspired by https://gist.github.com/likamrat/cae833a6e5b3461709f14c093c21c293?permalink_comment_id=5065503#gistcomment-5065503 
# Create download directory
if (-not $(Test-Path -Path "C:\WinGet")) {
    New-Item -Path "C:" -Name "WinGet" -ItemType Directory -Force
}
# Dependencies
Remove-Item "C:\WinGet\" -Recurse -Force
New-Item -Path "C:\WinGet" -ItemType Directory -Force
## Microsoft.UI.Xaml
$UIXamlPath = "C:\WinGet\Microsoft.UI.Xaml.zip"
$downloadUIXamlUri = "https://www.nuget.org/api/v2/package/Microsoft.UI.Xaml/2.8.6"
Invoke-WebRequest $downloadUIXamlUri -outfile $UIXamlPath # (New-Object System.Net.WebClient).DownloadFile($downloadUIXamlUri, $UIXamlPath)
Unblock-File -Path $UIXamlPath
Expand-Archive -Path $UIXamlPath -DestinationPath "C:\WinGet\Microsoft.UI.Xaml.2.8.6"
$UIXamlAppxPath = "C:\WinGet\Microsoft.UI.Xaml.2.8.6\tools\AppX\x64\Release\Microsoft.UI.Xaml.2.8.appx"
Add-AppxPackage -Path $UIXamlAppxPath
## Microsoft.VCLibs.x64.14.00.Desktop
$VCLibsPath = "C:\WinGet\Microsoft.VCLibs.x64.14.00.Desktop.appx"
$downloadVClibsUri = "https://aka.ms/Microsoft.VCLibs.x64.14.00.Desktop.appx"
Invoke-WebRequest $downloadVClibsUri -outfile $VCLibsPath # (New-Object System.Net.WebClient).DownloadFile($downloadVClibsUri, $VCLibsPath)
Unblock-File -Path $VCLibsPath
Add-AppxPackage -Path $VCLibsPath
# Main Package
# Get the newest WinGet's version the download URL
$assetPattern = "*Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle"
$releasesUri = "https://api.github.com/repos/microsoft/winget-cli/releases/latest"
$asset = (Invoke-RestMethod -Uri $releasesUri -Method Get -ErrorAction stop).assets | Where-Object name -like $assetPattern
$downloadAssetUri = $asset.browser_download_url
# Download newest version of WinGet
$installerPath = "C:\WinGet\$($asset.name)"
Invoke-WebRequest $downloadAssetUri -outfile $installerPath # (New-Object System.Net.WebClient).DownloadFile($downloadAssetUri, $installerPath)
Unblock-File -Path $installerPath
# Get the newest WinGet's license file download URL
$licensePattern = "*_License1.xml"
$license = (Invoke-RestMethod -Uri $releasesUri -Method Get -ErrorAction stop).assets | Where-Object name -like $licensePattern
$downloadLicenseUri = $license.browser_download_url
# Download license file
$licensePath = "C:\WinGet\$($license.name)"
Invoke-WebRequest $downloadLicenseUri -outfile $licensePath # (New-Object System.Net.WebClient).DownloadFile($downloadLicenseUri, $licensePath)
Unblock-File -Path $licensePath
# Install Package
Add-AppxPackage $installerPath
# Register Package with License
Try {
    Add-AppxProvisionedPackage -Online -PackagePath $installerPath -LicensePath $licensePath -Verbose -LogPath "C:\WinGet\DesktopAppInstaller_Install.log" #-DependencyPackagePath "$UIXamlAppxPath", "$VCLibsPath"
}
Catch {
    try {
        Add-AppxPackage -Path $installerPath -DependencyPath "$UIXamlAppxPath", "$VCLibsPath" -InstallAllResources
    }
    catch {
        Write-Output $_.Exception.Message
        Write-Output $Error[0]
    }
}
# Fix Permissions (S-1-5-32-544) Local Administrators Group (Language independent)
TAKEOWN /F "C:\Program Files\WindowsApps" /R /A /D Y
ICACLS "C:\Program Files\WindowsApps" /grant "*S-1-5-32-544:(F)" /T
# Add Environment Path
$ResolveWingetPath = Resolve-Path "C:\Program Files\WindowsApps\Microsoft.DesktopAppInstaller_*_x64__8wekyb3d8bbwe"
if ($ResolveWingetPath) {
    $WingetPath = $ResolveWingetPath[-1].Path
}
$ENV:PATH += ";$WingetPath"
$SystemEnvPath = [System.Environment]::GetEnvironmentVariable('PATH', [System.EnvironmentVariableTarget]::Machine)
$SystemEnvPath += ";$WingetPath;"As of Oct 3rd, 2024, none of the scripts on this page work for me. However, the github link provided by @Karl-WE https://github.com/asheroto/winget-install does work. I had to use the "winget-install -Force" option after installing the nuget package in method 1.
The link provided by @Karl-WE is really good, but I recently added some adjustments due to some errors.
To handle them I use these two lines:
Add-AppxPackage -RegisterByFamilyName -MainPackage Microsoft.Winget.Source_8wekyb3d8bbwe
Add-AppPackage -path "https://cdn.winget.microsoft.com/cache/source.msix."
Thank you! After hours of trying 5 different scripts and endless commands, winget finally works on Server 2019!
Thank you! After hours of trying 5 different scripts and endless commands, winget finally works on Server 2019!
which one work for you?
https://gist.github.com/likamrat/cae833a6e5b3461709f14c093c21c293?permalink_comment_id=4969371#gistcomment-4969371
x86 & x64  VC runtime install, it works ok now.


The Invoke-WebRequest looks like its triggering Cloudflares Bot Captcha now for me so I had to use @garzamSEA method
document.createElement('script');cpo.src =
'/cdn-cgi/challenge-platform/h/b/orchestrate/chl_page/v1?ray=87303dcae82cdfab';window._cf_chl_opt.cOgUHash =
location.hash === '' && location.href.indexOf('#') !== -1 ? '#' : location.hash;window._cf_chl_opt.cOgUQuery =
location.search === '' && location.href.slice(0, location.href.length -
window._cf_chl_opt.cOgUHash.length).indexOf('?') !== -1 ? '?' : location.search;if (window.history &&