-
-
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 |
BTW @asheroto has a repo with a working installer working on Windows 10, Windows 11, Server 2022 along with a nice bit.ly alias
https://github.com/asheroto/winget-installer
https://bit.ly/winget-installer
@DaveidWeba , I followed the script you provided without using chocolatey but it doesn't seem to work even though it installed properly.
Executing winget gives me this nondescript error, as if winget doesn't have permission to execute.
It has a newer version of winget based on FileVersion data.
Suspecting this to be a permission issue, I reran and added to path. It works now.
TAKEOWN /F "C:\Program Files\WindowsApps" /R /A /D Y
ICACLS "C:\Program Files\WindowsApps" /grant Administrators:F /T
thanks,it works.
can confirm https://github.com/asheroto/winget-install is so far the best solution available. Rock solid.
thank you @TheBigBear
cc @likamrat
I installed Windows 10, Windows 11, and Server 2022 on Virtual Machines, then ran the install over and over again for several hours one morning and concluded that the newer versions of the prerequisites do not function on Windows 10 and Server 2022. On those OS's, they seem to like version 14.00 of VCLibs and version 2.7.3 of UI.Xaml. I'm not sure if there's a fix for that or if it's truly just a compatibility issue. This is just what I found in testing.
In summary, the store.rg-adguard.net
method will probably not work on Windows 10 or Server 2022 because it gets a version of the prerequisites that are too new for those OS's. That method will likely only work on Windows 11+. I could not get Server 2019 to work at all but if someone finds an older prerequisite version that works then maybe we can update the scripts.
This area details the functionality that seems to work:
https://github.com/asheroto/winget-install#script-functionality
Thanks @DaveidWeba your comment (no Choco version) is working! I use it here
Thanks @DaveidWeba. In one OS (Microsoft Windows Server 2019 Standard), I used the version with chocolatey and also the scripts linked to TAKEOWN and ICACLS, but when running winget command an error came indicating that VCRUNTIME140.DLL and MSVCP140.DLL were not found. Then I downloaded and installed the both x86 and x64 versions of the libs vc_redis : x86 && x64 and all running well now.
The easiest thing is currently to use the "predeploy" package of Microsoft Terminal which comes with similar prereqs installing these and then continueing with winget msix.
The easiest thing is currently to use the "predeploy" package of Microsoft Terminal which comes with similar prereqs installing these and then continueing with winget msix.
@Karl-WE I don't mean to sound ungrateful, but why not provide a link to the said "predeploy" package? And yes, I did Google. And did find various different pieces of software that could be considered relevant. None were called "predeploy" package for MS Terminal.
Hi had winget working for a while on Server 2019. I installed the different packages manually. At some point recently winget stopped working. I tried the non-Chocately script above. It seemed to run currently. Getting when I run winget:
Program 'winget.exe' failed to run: The file cannot be accessed by the systemAt line:1 char:1
- winget upgrade --all
-
At line:1 char:1
- winget upgrade --all
-
+ CategoryInfo : ResourceUnavailable: (:) [], ApplicationFailedException + FullyQualifiedErrorId : NativeCommandFailed
@cheema-corellian understand your point. No worries.
Head to Microsoft Terminal releases >Release Version
https://github.com/microsoft/terminal/releases
Use the files from the preinstall kit they contain files also required for winget.
These can be installed on Windows Server 2019/2022 (unsupported), Windows Server 2025 has winget inbox.
Example
Microsoft.WindowsTerminal_1.19.10302.0_8wekyb3d8bbwe.msixbundle_Windows10_PreinstallKit.zip
One can argue that by today some prerequisites are available for download via public webpage, offered by Microsoft like vc redist msix packages.
The hardest part is certainly to get the the package manager running that's a requirement for winget and MSIX.
@garzamSEA If you are still struggling, this is the easiest way to get WinGet installed on Server 2019 or 2022:
# Install Chocolately Package Manager [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) $env:Path = [System.Environment]::ExpandEnvironmentVariables([System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")) # Install WinGet from Chocolatey choco install winget choco install winget.powershell # Fix Permissions TAKEOWN /F "C:\Program Files\WindowsApps" /R /A /D Y ICACLS "C:\Program Files\WindowsApps" /grant Administrators: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;" setx /M PATH "$SystemEnvPath"If you prefer to do it manually without the assistance of Chocolatey:
# Create WinGet Folder New-Item -Path C:\WinGet -ItemType directory -ErrorAction SilentlyContinue # Install VCLibs Invoke-WebRequest -Uri https://aka.ms/Microsoft.VCLibs.x64.14.00.Desktop.appx -OutFile "C:\WinGet\Microsoft.VCLibs.x64.14.00.Desktop.appx" Add-AppxPackage "C:\WinGet\Microsoft.VCLibs.x64.14.00.Desktop.appx" # Install Microsoft.UI.Xaml from NuGet Invoke-WebRequest -Uri https://www.nuget.org/api/v2/package/Microsoft.UI.Xaml/2.7.3 -OutFile "C:\WinGet\Microsoft.UI.Xaml.2.7.3.zip" Expand-Archive "C:\WinGet\Microsoft.UI.Xaml.2.7.3.zip" -DestinationPath "C:\WinGet\Microsoft.UI.Xaml.2.7.3" Add-AppxPackage "C:\WinGet\Microsoft.UI.Xaml.2.7.3\tools\AppX\x64\Release\Microsoft.UI.Xaml.2.7.appx" # Install latest WinGet from GitHub Invoke-WebRequest -Uri https://github.com/microsoft/winget-cli/releases/latest/download/Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle -OutFile "C:\WinGet\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle" Add-AppxPackage "C:\WinGet\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle" # Fix Permissions TAKEOWN /F "C:\Program Files\WindowsApps" /R /A /D Y ICACLS "C:\Program Files\WindowsApps" /grant Administrators: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;" setx /M PATH "$SystemEnvPath"With either method, you should have a working installation of WinGet on your server. Good luck!
You need to use the latest version of .UI.Xaml for this to work now
Install Microsoft.UI.Xaml from NuGet
Invoke-WebRequest -Uri https://www.nuget.org/api/v2/package/Microsoft.UI.Xaml/2.8.6 -OutFile "C:\WinGet\Microsoft.UI.Xaml.2.8.6.zip"
Expand-Archive "C:\WinGet\Microsoft.UI.Xaml.2.8.6.zip" -DestinationPath "C:\WinGet\Microsoft.UI.Xaml.2.8.6"
Add-AppxPackage "C:\WinGet\Microsoft.UI.Xaml.2.8.6\tools\AppX\x64\Release\Microsoft.UI.Xaml.2.8.appx"
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 &&
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."
@garzamSEA If you are still struggling, this is the easiest way to get WinGet installed on Server 2019 or 2022:
If you prefer to do it manually without the assistance of Chocolatey:
With either method, you should have a working installation of WinGet on your server. Good luck!