From cb72b553b8c34b5eec59d31c70db64ba677b25ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Bere=C5=BCa=C5=84ski?= Date: Sun, 26 Sep 2021 18:24:51 +0200 Subject: [PATCH] chocolatey-visualstudio.extension: update VS Installer to the highest version required by installed VS products The VS Installer checks all channels of already installed VS products to determine if it needs to be updated, not only the channel of the product being currently installed/modified. The extension should do that, too, to maintain control over the VS Installer processes (when the VS Installer self-updates, it does not respect --wait). The extension will not check the other channels if --noWeb is passed in package parameters (to avoid going online). Channel uris stored in the installed VS product metadata are used (so the same that the VS Installer would use). If a VS product was installed with updates turned off (by passing a blank channelUri to the installer), it is skipped. As before, passing --noUpdateInstaller turns off all VS Installer update logic in the extension. Related issue: GH-97 --- .../CHANGELOG.md | 1 + .../chocolatey-visualstudio.extension.nuspec | 2 +- .../extensions/Assert-VSInstallerUpdated.ps1 | 62 +++++++++++++++++-- 3 files changed, 58 insertions(+), 7 deletions(-) diff --git a/chocolatey-visualstudio.extension/CHANGELOG.md b/chocolatey-visualstudio.extension/CHANGELOG.md index d315e1cd..62644961 100644 --- a/chocolatey-visualstudio.extension/CHANGELOG.md +++ b/chocolatey-visualstudio.extension/CHANGELOG.md @@ -2,6 +2,7 @@ ## Version 1.10.0 +- When checking if the Visual Studio Installer needs update, channels of other installed Visual Studio products are also used to determine the highest required installer version. This aligns with the native Visual Studio Installer behavior and prevents the Installer from exiting early to perform a self-update when, for example, installing or upgrading Visual Studio 2017 on a machine with Visual Studio 2019 installed ([GH-97](https://github.com/jberezanski/ChocolateyPackages/issues/97)). - Fixed uninstallation of modern versions of the Visual Studio Installer. - During an update operation, if the package author did not provide DesiredProductVersion, the version is automatically determined from the channel manifest. This lights up two features: - The update process is short-circuited if the installed product version is already DesiredProductVersion or higher. diff --git a/chocolatey-visualstudio.extension/chocolatey-visualstudio.extension.nuspec b/chocolatey-visualstudio.extension/chocolatey-visualstudio.extension.nuspec index 89eeb6f0..03f98346 100644 --- a/chocolatey-visualstudio.extension/chocolatey-visualstudio.extension.nuspec +++ b/chocolatey-visualstudio.extension/chocolatey-visualstudio.extension.nuspec @@ -3,7 +3,7 @@ chocolatey-visualstudio.extension - 1.10.0-preview3 + 1.10.0-preview4 https://github.com/jberezanski/ChocolateyPackages/tree/master/chocolatey-visualstudio.extension jberezanski Chocolatey Visual Studio servicing extensions diff --git a/chocolatey-visualstudio.extension/extensions/Assert-VSInstallerUpdated.ps1 b/chocolatey-visualstudio.extension/extensions/Assert-VSInstallerUpdated.ps1 index 81c8518e..c4558f12 100644 --- a/chocolatey-visualstudio.extension/extensions/Assert-VSInstallerUpdated.ps1 +++ b/chocolatey-visualstudio.extension/extensions/Assert-VSInstallerUpdated.ps1 @@ -18,10 +18,60 @@ function Assert-VSInstallerUpdated return } - $requiredVersionInfo = Get-VSRequiredInstallerVersion -PackageParameters $PackageParameters -ChannelReference $ChannelReference -UseInstallChannelUri:$UseInstallChannelUri - Install-VSInstaller ` - -DoNotInstallIfNotPresent ` - -RequiredInstallerVersion $requiredVersionInfo.Version ` - -RequiredEngineVersion $requiredVersionInfo.EngineVersion ` - @PSBoundParameters + Write-Verbose 'Checking installer version required by the package' + $packageRequiredVersionInfo = Get-VSRequiredInstallerVersion -PackageParameters $PackageParameters -ChannelReference $ChannelReference -UseInstallChannelUri:$UseInstallChannelUri ` + | Add-Member -PassThru -NotePropertyMembers @{ ForPackage = $true; Source = 'package' } + + # If there are other VS products installed (e.g. we are installing/updating VS 2017 and a 2019 product is installed), + # the VS Installer will also check other channels for installer update requirement. + $installedProductsUpdateableChannels = Get-WillowInstalledProducts ` + | ForEach-Object { New-VSChannelReference -ChannelId $_.channelId -ChannelUri $_.channelUri } ` + | Where-Object { -not [string]::IsNullOrEmpty($_.ChannelUri) <# may be empty to disable updates #> } ` + | Sort-Object -Property ChannelId, ChannelUri -Unique + $otherChannelsToCheck = $installedProductsUpdateableChannels | Where-Object { $null -eq $ChannelReference -or $ChannelReference.ChannelId -ne $_.ChannelId } + $otherRequiredVersionInfos = @() + if (($otherChannelsToCheck | Measure-Object).Count -gt 0) + { + if (-not $PackageParameters.ContainsKey('noWeb')) + { + Write-Verbose 'Checking installer version required by installed Visual Studio product(s) from other channel(s)' + $otherRequiredVersionInfos = @($otherChannelsToCheck ` + | ForEach-Object { + Get-VSRequiredInstallerVersion -ChannelReference $_ -PackageParameters @{} ` + | Add-Member -PassThru -NotePropertyMembers @{ ForPackage = $false; Source = "channel $($_.ChannelId)"; ChannelReference = $_ } + }) + } + else + { + Write-Verbose 'Not checking installer version required by installed Visual Studio product(s) from other channel(s) because --noWeb was passed in package parameters.' + } + } + + $allRequiredVersionInfos = @($packageRequiredVersionInfo) + $otherRequiredVersionInfos + $requiredVersionInfo = $allRequiredVersionInfos | Sort-Object -Property Version,EngineVersion -Descending | Select-Object -First 1 + Write-Verbose "Highest required installer version: $($requiredVersionInfo.Version) (engine: $($requiredVersionInfo.EngineVersion)); requirement source: $($requiredVersionInfo.Source)" + + if ($requiredVersionInfo.ForPackage) + { + # Installing the VS Installer update from the channel of this package, + # so supporting all normal features (offline layout, explicit bootstrapper path etc). + Install-VSInstaller ` + -DoNotInstallIfNotPresent ` + -RequiredInstallerVersion $requiredVersionInfo.Version ` + -RequiredEngineVersion $requiredVersionInfo.EngineVersion ` + @PSBoundParameters + } + else + { + # Installing the VS Installer update from a different channel than this package, + # so using the default manifest source for the other channel + # and the default bootstrapper location from the channel manifest. + Install-VSInstaller ` + -DoNotInstallIfNotPresent ` + -RequiredInstallerVersion $requiredVersionInfo.Version ` + -RequiredEngineVersion $requiredVersionInfo.EngineVersion ` + -ChannelReference $requiredVersionInfo.ChannelReference ` + -PackageName $PackageName ` + -PackageParameters @{} + } }