From 00b26e3e9baa5b367386b0d18603d35230c10858 Mon Sep 17 00:00:00 2001 From: ChrisTitusTech Date: Thu, 28 Mar 2024 15:45:41 +0000 Subject: [PATCH] Compile Winutil --- winutil.ps1 | 103 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 83 insertions(+), 20 deletions(-) diff --git a/winutil.ps1 b/winutil.ps1 index d2efe764..d4e366a7 100644 --- a/winutil.ps1 +++ b/winutil.ps1 @@ -608,6 +608,58 @@ function Get-WinUtilVariables { } return $keys } +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') + } +} +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') + } +} function Install-WinUtilChoco { <# @@ -669,7 +721,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 @@ -681,29 +736,19 @@ Function Install-WinUtilProgramWinget { Write-Progress -Activity "$manage Applications" -Status "Finished" -Completed } -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 } @@ -717,15 +762,33 @@ 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')