Romanitho / Winget-AutoUpdate

WAU daily updates apps as system and notify connected users. (Allowlist and Blocklist support)
MIT License
1.18k stars 141 forks source link

[Bug]: VCLibs Version Dependencies are too high in Winget #761

Open unclesam87 opened 1 week ago

unclesam87 commented 1 week ago

The problem

I am usuing part of ur code to build my "own" winget installer, while doing i recongized that the newst winget version is requiring an vclib of 14.0.33728.0 as the one u can download on microsoft website is only an 14.0.33228.0 - so i did an short deep dive and found an quite different solution to solve the problem:

function Install-VCLibs {
    try {
        # Check if Microsoft.VCLibs.140.00.UWPDesktop is installed
        Write-Logfile "Install-Winget-Pre: Checking Microsoft.VCLibs.140.00.UWPDesktop..."
        $VCLLibsVersion = Get-AppxPackage -Name 'Microsoft.VCLibs.140.00.UWPDesktop' -AllUsers | Select-Object -ExpandProperty Version -First 1
        $wingetdependenciesjson = "https://github.com/microsoft/winget-cli/releases/download/v$WinGetAvailableVersion/DesktopAppInstaller_Dependencies.json"
        $jsonContent = Invoke-WebRequest -Uri $wingetdependenciesjson -UseBasicParsing | ConvertFrom-Json
        $requiredVCLibsVersion = $jsonContent.Dependencies | Where-Object { $_.Name -eq "Microsoft.VCLibs.140.00.UWPDesktop" } | Select-Object -ExpandProperty Version -First 1
        $requiredVersion = [Version]$requiredVCLibsVersion
        Write-Logfile "Required Microsoft.VCLibs.140.00.UWPDesktop version: $($requiredVersion.ToString())"
    } catch {
        Write-Logfile "Install-Winget-Pre: Failed to check Microsoft.VCLibs.140.00.UWPDesktop Version Numbers Error: $($_.Exception.Message)" "Red"
    }
    try {
        if (-not $VCLLibsVersion) {
            Write-Logfile "Install-Winget-Pre: Microsoft.VCLibs.140.00.UWPDesktop is not installed"
            Install-VCLibsPackage
        } elseif ([Version]$VCLLibsVersion -lt $requiredVersion) {
            Write-Logfile "Install-Winget-Pre: Installed version ($VCLLibsVersion) is lower than required version ($($requiredVersion.ToString()))"
            Install-VCLibsPackage
        } else {
            Write-Logfile "Install-Winget-Pre: Microsoft.VCLibs.140.00.UWPDesktop is already installed and up to date"
        }
    } catch {
        Write-Logfile "Install-Winget-Pre: Failed to compare Microsoft.VCLibs.140.00.UWPDesktop Version Error: $($_.Exception.Message)" "Red"
    }
}
function Install-VCLibsPackage {
    try {
        # Download
        $VCLibsUrl = "https://github.com/microsoft/winget-cli/releases/download/v$WinGetAvailableVersion/DesktopAppInstaller_Dependencies.zip"
        $Dependiencies = "$folder\DesktopAppInstaller_Dependencies.zip"
        Write-Logfile "Install-Winget-Pre: Downloading the Dependencies directly from winget"
        Invoke-WebRequest -Uri $VCLibsUrl -OutFile $Dependiencies -UseBasicParsing
        Expand-Archive -Path $Dependiencies -DestinationPath $folder\WingetDependencies -Force
        $vcldirectorypath = "$folder\WingetDependencies\x64"
        $VCLibsfile = Get-ChildItem -Path $vcldirectoryPath -Filter "Microsoft.VCLibs.140.00.UWPDesktop_*x64.appx" | Select-Object -First 1
        $VCLibsactualfile = $VCLibsfile.FullName
    } catch {
        Write-Logfile "Install-Winget-Pre: Failed to download Microsoft.VCLibs.140.00.UWPDesktop..." "Red"
    } 
    try {
        # Install
        Write-Logfile "-> Installing Microsoft.VCLibs.140.00.UWPDesktop..."
        Add-AppxProvisionedPackage -Online -PackagePath $VCLibsactualfile -SkipLicense | Out-Null
        Write-Logfile "Install-Winget-Pre: Microsoft.VCLibs.140.00.UWPDesktop installed successfully." "Green"
    } catch {
        Write-Logfile "Install-Winget-Pre: Failed to install Microsoft.VCLibs.140.00.UWPDesktop..." "Red"
    } 
}

as u see i used two functions: one to pull from the newst winget release the dependecy json and then compare that to my installed version - when it isnt their or to old it will download out of the winget release the appx and install that - not quite sure if it is good code (as i am just returning to write my own stuff - so i am pretty open for ideas to improve;)) - but maybe this will help others too

ah and u need this function too to get the winget lastet version

function Get-WingetLatestVersion {
    try {
        #Get latest WinGet info
        $WinGeturl = 'https://api.github.com/repos/microsoft/winget-cli/releases/latest'
        $WinGetAvailableVersion = ((Invoke-WebRequest $WinGeturl -UseBasicParsing | ConvertFrom-Json)[0].tag_name).Replace("v", "")
        Write-Logfile "Install-Winget: Latest WinGet version is $WinGetAvailableVersion"
        return $WinGetAvailableVersion
    } catch {
        #if fail set version to the latest version as of 2024-10-15
        $WinGetAvailableVersion = "1.8.1911"
        Write-Logfile "Install-Winget: Failed to get latest WinGet version. Using $WinGetAvailableVersion"
        return $WinGetAvailableVersion
    } 
}

What version of WAU has the issue?

2.0.0

What version of Windows are you using (ex. Windows 11 22H2)?

Windows 10 to Windows 11 24H2

What version of winget are you using?

v1.9.25180

Log information

No response

Additional information

No response

AndrewDemski-ad-gmail-com commented 1 week ago

@unclesam87 , That is a neat piece of code. The idea seems to be good.

I'd love to hear what @KnifMelti and @Romanitho think about that modification. (Proposed logic will replace pulling from static uri with JSON declarationf from github)

https://github.com/Romanitho/Winget-AutoUpdate/blob/e31afa874900d581003fa3c15bbda71dc20d3f6b/Sources/Winget-AutoUpdate/functions/Install-Prerequisites.ps1#L48

As much as I like it, I do not trust MS. Tl;dr: We would need to protect ourselves from MS errors in tags

# pseudocode
$WinGeturl = 'https://api.github.com/repos/microsoft/winget-cli/releases/latest'
$WinGetRelese = Invoke-WebRequest $WinGeturl -UseBasicParsing | ConvertFrom-Json

? {$WinGetRelese.prerelease -ne $false}
? {$WinGetRelese.draft -ne $false}

in the meantime we could reuse the same body of web response from initial web request to get the list of dependencies.

$browser_download_url = $WinGetRelese.assets | ? {$_.name -ilike "DesktopAppInstaller_Dependencies.json"} | Select-Object -ExpandProperty 'browser_download_url'
$wingetdependenciesjson = Invoke-WebRequest -Uri $browser_download_url -UseBasicParsing | ConvertFrom-Json
$wingetdependenciesjson.Dependencies | fl

output:

Name    : Microsoft.VCLibs.140.00.UWPDesktop
Version : 14.0.33728.0

Name    : Microsoft.UI.Xaml.2.8
Version : 8.2310.30001.0

Functions should declare all parameters, that will make testing easier in the future (with Pester in mind). The icing on the cake would be try-catching rare conditions like http statuses indicating problems with accessing api.github.com.

KnifMelti commented 1 week ago

It looks really nice, but when it comes to coding I'm a novice and this repo was my first try when it comes to PS (coming from CMD, VB, etc...) as a dinosaur at the age of 61. 😁 I'll leave it up to you all, as long as it gets better!

"../the newst winget version is requiring an vclib of 14.0.33728.0/.." - doesn't really add up. I'm running v14.0.29231.0 of Microsoft.VCLibs.140.00.UWPDesktop and v1.9.25180 of WinGet

unclesam87 commented 6 days ago

It looks really nice, but when it comes to coding I'm a novice and this repo was my first try when it comes to PS (coming from CMD, VB, etc...) as a dinosaur at the age of 61. 😁 I'll leave it up to you all, as long as it gets better!

"../the newst winget version is requiring an vclib of 14.0.33728.0/.." - doesn't really add up. I'm running v14.0.29231.0 of Microsoft.VCLibs.140.00.UWPDesktop and v1.9.25180 of WinGet

hey - yeah i had this problem on freshly installed win 10 and win 11 machines i am using to test that winget installation crashed when it wasnt their - my own machine is also running an older version of vclibs so i am guessing that they just need it for installation?

Functions should declare all parameters, that will make testing easier in the future (with Pester in mind). The icing on the cake would be try-catching rare conditions like http statuses indicating problems with accessing api.github.com.

what do u mean by declare all parameters? i am very intressted to get better in my coding and to publish it so it every hint to improve is more then welcome - that recommended try and catch is a nice idea - maybe i will try to involve that in my function - i am close to publish my whole code (installation script with many functions as installing winget, winget-autoupdate and installing apps, adding windows features and activating bitlocker, updating machines) - maybe it could be helpfull when i show u the whole code i using right now to get winget to install (as i learned from the many machines we installed in the last 1,5 years with versions of that script, isnt allways an easy way - at least when u trying it with powershell...)

AndrewDemski-ad-gmail-com commented 6 days ago

I can guesstimate, that VC redists in APPX container are nothing new and these are our good old vcredists 20xx in a different wrapper. winget should and will work with visual c++ runtime installed the old way.

Q2. what do u mean by declare all parameters?

A2. by moving all parameters to definition of all functions

F ex:

$var1 = "sth declared outside of function block"

Function DoSomethingWithVar1 {
    param (
        [string]$_v
    )
    $_v
}

DoSomethingWithVar1 -_v $var1

instead of

Function DoSomethingWithVar1directly {
    $var1
}

DoSomethingWithVar1directly 

Both produce same output. Second option looks easier and more tempting (the principle of "keep it simple, stupid"), but the first one makes more sense in the longer perspective. Once all functions receive own testing logic, it will be much easier to pinpoint problems in each release.

f.ex.

[bool]$testOK = $var1 -eq (DoSomethingWithVar1 -_v $var1)

Thanks to that granular control of all tests (not only static linting) we will be able to continue iterative and incremental development.

unclesam87 commented 6 days ago

ttp statuses

it does without any problems - but my problem came up on installing it on an fresh machine as it was then crashing - but i will take this issue to the winget devs itself.

to ur programming advise - im not quite sure if i get it right but in may exmaple u would move the variable $VCLLibsVersion outside of the function?

AndrewDemski-ad-gmail-com commented 6 days ago

Sure, I will do that this week ~Thu-Fri. I have a weird schedule this week. Apologies for the delay.

BR AD

Romanitho commented 18 hours ago

I'm OK to everything that could improve features, code, ... :)