From 5a075a956d6d2885b4254d5537a7fd46116a7ee1 Mon Sep 17 00:00:00 2001 From: Peter Sabath <31621424+peter-sabath@users.noreply.github.com> Date: Wed, 24 Sep 2025 16:36:07 +0200 Subject: [PATCH] Updated to VS2022 runtimes & changed Start/Install order Updated VisualCppPrerequisite to use the VS 2022 Runtime Running the application is not tried before checking for missing Prerequisites to catch cases where an installed .NET runtime is accepted, but not the desired one --- .../BootstrapperBase.cs | 46 ++++++++----------- .../Prerequisites/VisualCppPrerequisite.cs | 21 +++++++-- 2 files changed, 34 insertions(+), 33 deletions(-) diff --git a/DotnetRuntimeBootstrapper.AppHost.Core/BootstrapperBase.cs b/DotnetRuntimeBootstrapper.AppHost.Core/BootstrapperBase.cs index f485043..17f77a3 100644 --- a/DotnetRuntimeBootstrapper.AppHost.Core/BootstrapperBase.cs +++ b/DotnetRuntimeBootstrapper.AppHost.Core/BootstrapperBase.cs @@ -111,38 +111,28 @@ IPrerequisite[] missingPrerequisites private int Run(TargetAssembly targetAssembly, string[] args) { - try - { - // Hot path: attempt to run the target first without any checks - return targetAssembly.Run(args); - } - // Possible exception causes: - // - .NET host not found (DirectoryNotFoundException) - // - .NET host failed to initialize (BootstrapperException) - catch - { - // Check for missing prerequisites and install them - var missingPrerequisites = targetAssembly.GetMissingPrerequisites(); - if (missingPrerequisites.Any()) - { - var isReadyToRun = PromptAndInstall(targetAssembly, missingPrerequisites); + // need to check the prerequisites first, otherwise the application may start but fail later + // e.g. VS runtime 2019 are installed, but app needs 2022 + // e.g. .NET 8.0.4 is installed but 8.0.20 is desired + // both conditions does not prevent starting the app, but is not what the dev desired. - // User did not accept the installation or reboot is required - if (!isReadyToRun) - return 0xB007; + // Check for missing prerequisites and install them + var missingPrerequisites = targetAssembly.GetMissingPrerequisites(); + if (!missingPrerequisites.Any()) + return targetAssembly.Run(args); - // Reset the environment to update PATH and other variables - // that may have been changed by the installation process. - EnvironmentEx.RefreshEnvironmentVariables(); + var isReadyToRun = PromptAndInstall(targetAssembly, missingPrerequisites); - // Attempt to run the target again - return targetAssembly.Run(args); - } + // User did not accept the installation or reboot is required + if (!isReadyToRun) + return 0xB007; - // There are no missing prerequisites to install, meaning that the - // app failed to run for reasons unrelated to the bootstrapper. - throw; - } + // Reset the environment to update PATH and other variables + // that may have been changed by the installation process. + EnvironmentEx.RefreshEnvironmentVariables(); + + // Attempt to run the target + return targetAssembly.Run(args); } public int Run(string[] args) diff --git a/DotnetRuntimeBootstrapper.AppHost.Core/Prerequisites/VisualCppPrerequisite.cs b/DotnetRuntimeBootstrapper.AppHost.Core/Prerequisites/VisualCppPrerequisite.cs index 690552b..18ae614 100644 --- a/DotnetRuntimeBootstrapper.AppHost.Core/Prerequisites/VisualCppPrerequisite.cs +++ b/DotnetRuntimeBootstrapper.AppHost.Core/Prerequisites/VisualCppPrerequisite.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.InteropServices; using DotnetRuntimeBootstrapper.AppHost.Core.Platform; using DotnetRuntimeBootstrapper.AppHost.Core.Utils; using DotnetRuntimeBootstrapper.AppHost.Core.Utils.Extensions; @@ -8,25 +9,35 @@ namespace DotnetRuntimeBootstrapper.AppHost.Core.Prerequisites; internal class VisualCppPrerequisite : IPrerequisite { - public string DisplayName => "Visual C++ Redistributable 2015-2019"; + public string DisplayName => "Visual C++ Redistributable 2015-2022"; - public bool IsInstalled() => - Registry.LocalMachine.ContainsSubKey( + public bool IsInstalled() + { + var registryKey = Registry.LocalMachine.OpenSubKey( ( OperatingSystemEx.ProcessorArchitecture.Is64Bit() ? "SOFTWARE\\Wow6432Node\\" : "SOFTWARE\\" ) + "Microsoft\\VisualStudio\\14.0\\VC\\Runtimes\\" - + OperatingSystemEx.ProcessorArchitecture.GetMoniker() + + OperatingSystemEx.ProcessorArchitecture.GetMoniker(), + false ); + if (registryKey == null) + return false; + + // than check if the minor version is ok for 2022 + var minorVersion = Convert.ToInt32(registryKey.GetValue("Minor", 0)); + return minorVersion >= 44; + } + public IPrerequisiteInstaller DownloadInstaller(Action? handleProgress) { var fileName = $"VC_redist.{OperatingSystemEx.ProcessorArchitecture.GetMoniker()}.exe"; var filePath = FileEx.GenerateTempFilePath(fileName); - Http.DownloadFile($"https://aka.ms/vs/16/release/{fileName}", filePath, handleProgress); + Http.DownloadFile($"https://aka.ms/vs/17/release/{fileName}", filePath, handleProgress); return new ExecutablePrerequisiteInstaller(this, filePath); }