Implement New Winget Install Method (#1738)

- Removed Get-LatestHash from Install-WinUtilWinget.ps1, replaced by Get-WinUtilWingetLatest.ps1.
- Added new Winget Install method in case of choco failing to install. Environment refresh line included.
- Get-WinUtilWingetPrerequisites added: Downloads the prerequisites required for the latest version of Winget.
- Get-WinUtilWingetLatest added: Uses the GitHub API to find the latest version of Winget and download it along with the accompanied License1.xml file.

Fixes:
- Removed --scope=machine from winget install command in Install-WinUtilProgramWinget. Non-UWP Apps fail to install if scope is set to machine. Error code: 0x80070005. More information commented in file.
This commit is contained in:
Rux 2024-03-28 08:45:15 -07:00 committed by GitHub
parent c0b6a45fcc
commit 8c91bfca2d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 84 additions and 21 deletions

View File

@ -0,0 +1,23 @@
function Get-WinUtilWingetLatest {
<#
.SYNOPSIS
Uses GitHub API to check for the latest release of Winget.
.DESCRIPTION
This function grabs the latest version of Winget and returns the download path to Install-WinUtilWinget for installation.
#>
Try{
# Grabs the latest release of Winget from the Github API for the install process.
$response = Invoke-RestMethod -Uri "https://api.github.com/repos/microsoft/Winget-cli/releases/latest" -Method Get -ErrorAction Stop
$latestVersion = $response.tag_name #Stores version number of latest release.
$licenseWingetUrl = $response.assets.browser_download_url[0] #Index value for License file.
Write-Host "Latest Version:`t$($latestVersion)`n"
$assetUrl = $response.assets.browser_download_url[2] #Index value for download URL.
Invoke-WebRequest -Uri $licenseWingetUrl -OutFile $ENV:TEMP\License1.xml
# The only pain is that the msixbundle for winget-cli is 246MB. In some situations this can take a bit, with slower connections.
Invoke-WebRequest -Uri $assetUrl -OutFile $ENV:TEMP\Microsoft.DesktopAppInstaller.msixbundle
}
Catch{
throw [WingetFailedInstall]::new('Failed to get latest Winget release and license')
}
}

View File

@ -0,0 +1,29 @@
function Get-WinUtilWingetPrerequisites {
<#
.SYNOPSIS
Downloads the Winget Prereqs.
.DESCRIPTION
Downloads Prereqs for Winget. Version numbers are coded as variables and can be updated as uncommonly as Microsoft updates the prereqs.
#>
# I don't know of a way to detect the prereqs automatically, so if someone has a better way of defining these, that would be great.
# Microsoft.VCLibs version rarely changes, but for future compatibility I made it a variable.
$versionVCLibs = "14.00"
$fileVCLibs = "https://aka.ms/Microsoft.VCLibs.x64.${versionVCLibs}.Desktop.appx"
# Write-Host "$fileVCLibs"
# Microsoft.UI.Xaml version changed recently, so I made the version numbers variables.
$versionUIXamlMinor = "2.8"
$versionUIXamlPatch = "2.8.6"
$fileUIXaml = "https://github.com/microsoft/microsoft-ui-xaml/releases/download/v${versionUIXamlPatch}/Microsoft.UI.Xaml.${versionUIXamlMinor}.x64.appx"
# Write-Host "$fileUIXaml"
Try{
Write-Host "Downloading Microsoft.VCLibs Dependency..."
Invoke-WebRequest -Uri $fileVCLibs -OutFile $ENV:TEMP\Microsoft.VCLibs.x64.Desktop.appx
Write-Host "Downloading Microsoft.UI.Xaml Dependency...`n"
Invoke-WebRequest -Uri $fileUIXaml -OutFile $ENV:TEMP\Microsoft.UI.Xaml.x64.appx
}
Catch{
throw [WingetFailedInstall]::new('Failed to install prerequsites')
}
}

View File

@ -30,7 +30,10 @@ Function Install-WinUtilProgramWinget {
Write-Progress -Activity "$manage Applications" -Status "$manage $Program $($x + 1) of $count" -PercentComplete $($x/$count*100)
if($manage -eq "Installing"){
Start-Process -FilePath winget -ArgumentList "install -e --accept-source-agreements --accept-package-agreements --scope=machine --silent $Program" -NoNewWindow -Wait
# --scope=machine when installing non-UWP apps with winget fails with error code 0x80070005.
# Removed argument while testing new Winget install method.
# Open issue on winget-cli github repo: https://github.com/microsoft/winget-cli/issues/3936
Start-Process -FilePath winget -ArgumentList "install -e --accept-source-agreements --accept-package-agreements --silent $Program" -NoNewWindow -Wait
}
if($manage -eq "Uninstalling"){
Start-Process -FilePath winget -ArgumentList "uninstall -e --accept-source-agreements --purge --force --silent $Program" -NoNewWindow -Wait

View File

@ -1,26 +1,16 @@
function Get-LatestHash {
$shaUrl = ((Invoke-WebRequest $apiLatestUrl -UseBasicParsing | ConvertFrom-Json).assets | Where-Object { $_.name -match '^Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.txt$' }).browser_download_url
$shaFile = Join-Path -Path $tempFolder -ChildPath 'Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.txt'
$WebClient.DownloadFile($shaUrl, $shaFile)
Get-Content $shaFile
}
function Install-WinUtilWinget {
<#
.SYNOPSIS
Installs Winget if it is not already installed
Installs Winget if it is not already installed.
.DESCRIPTION
This function will download the latest version of winget and install it. If winget is already installed, it will do nothing.
This function will download the latest version of Winget and install it. If Winget is already installed, it will do nothing.
#>
Try{
Write-Host "Checking if Winget is Installed..."
if (Test-WinUtilPackageManager -winget) {
# Checks if winget executable exists and if the Windows Version is 1809 or higher
if (Test-WinUtilPackageManager -Winget) {
# Checks if Winget executable exists and if the Windows Version is 1809 or higher
Write-Host "Winget Already Installed"
return
}
@ -34,17 +24,35 @@ function Install-WinUtilWinget {
}
if (($ComputerInfo.WindowsVersion) -lt "1809") {
# Checks if Windows Version is too old for winget
# Checks if Windows Version is too old for Winget
Write-Host "Winget is not supported on this version of Windows (Pre-1809)"
return
}
Write-Host "Running Alternative Installer and Direct Installing"
Start-Process -Verb runas -FilePath powershell.exe -ArgumentList "choco install winget"
Write-Host "Winget Installed"
if((Get-Command -Name choco -ErrorAction Ignore)) {
# Checks if Chocolatey is present (In case it didn't install properly), and installs Winget with choco, if so.
Write-Host "Chocolatey detected. Installing Winget via Chocolatey"
Start-Process -Verb runas -FilePath powershell.exe -ArgumentList "choco install winget-cli"
Write-Host "Winget Installed"
Write-Output "Refreshing Environment Variables...`n"
$ENV:PATH = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
}
Else {
# If Chocolatey doesn't exist, it will install Winget through more manual means.
# Used part of my own script with some modification: ruxunderscore/windows-initialization
Write-Host "Downloading Winget Prerequsites"
Get-WinUtilWingetPrerequisites
Write-Host "Downloading Winget and License File"
Get-WinUtilWingetLatest
Write-Host "Installing Winget w/ Prerequsites"
Add-AppxProvisionedPackage -Online -PackagePath $ENV:TEMP\Microsoft.DesktopAppInstaller.msixbundle -DependencyPackagePath $ENV:TEMP\Microsoft.VCLibs.x64.Desktop.appx, $ENV:TEMP\Microsoft.UI.Xaml.x64.appx -LicensePath $ENV:TEMP\License1.xml
Write-Host "Winget Installed"
# Winget only needs a refresh of the environment variables to be used.
Write-Output "Refreshing Environment Variables...`n"
$ENV:PATH = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
}
}
Catch{
throw [WingetFailedInstall]::new('Failed to install')
}
}
}