Skip to content

Commit f4d8cc2

Browse files
committed
(#3228) Throw earlier if .Net 4.8 is not present
There are instances where .Net is not installed in a way that allows Chocolatey CLI to function. In these scenarios, the version in the registry seems to be very old. This commit accounts for this by wrapping the container registration in a try cath, and displaying a descriptive error in that case. Additionally, this changes the check to use Registry64 instead of Registry32, as on 64 bit systems the 64 bit registry is the one that determines the .Net version. And the lookup on 32 bit systems gracefully falls back to the 32 bit registry.
1 parent fa27b13 commit f4d8cc2

File tree

1 file changed

+53
-19
lines changed

1 file changed

+53
-19
lines changed

src/chocolatey.console/Program.cs

Lines changed: 53 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,17 @@
4444
using Console = System.Console;
4545
using Environment = System.Environment;
4646
using IFileSystem = chocolatey.infrastructure.filesystem.IFileSystem;
47+
using System.Runtime.CompilerServices;
4748

4849
namespace chocolatey.console
4950
{
5051
public sealed class Program
5152
{
53+
// We can't use chocolatey.StringResources as it is in both Chocolatey.PowerShell and chocolatey. This message is only reused within this class, so we're setting it here.
54+
private const string DotNetDownload = @"
55+
Please install .NET Framework 4.8 manually and reboot the system.
56+
Download at 'https://download.visualstudio.microsoft.com/download/pr/2d6bb6b2-226a-4baa-bdec-798822606ff1/8494001c276a4b96804cde7829c04d7f/ndp48-x86-x64-allos-enu.exe'";
57+
5258
private static void Main(string[] args)
5359
{
5460
ChocolateyConfiguration config = null;
@@ -69,7 +75,27 @@ private static void Main(string[] args)
6975
Bootstrap.Initialize();
7076
Bootstrap.Startup();
7177
license = License.ValidateLicense();
72-
var container = SimpleInjectorContainer.Container;
78+
Container container = null;
79+
80+
try
81+
{
82+
container = SimpleInjectorContainer.Container;
83+
}
84+
catch
85+
{
86+
// We have encountered an irrecoverable error before program information would be displayed. So we're going to display it as best we can. Regardless of if they wanted regular output or not, they're getting it.
87+
DisplayProgramInformation(
88+
true,
89+
args,
90+
VersionInformation.GetCurrentInformationalVersion(), // We don't have a configuration object yet. This is the same way that ConfigurationBuilder generates this version.
91+
license
92+
);
93+
"chocolatey".Log().Error(ChocolateyLoggers.Important, @"Container registration encountered an irrecoverable error.
94+
It could be that .NET 4.8 may be corrupted, or may be a really old version.{0}".FormatWith(DotNetDownload));
95+
96+
// rethrow the original exception.
97+
throw;
98+
}
7399

74100
"LogFileOnly".Log().Info(() => "".PadRight(60, '='));
75101

@@ -112,18 +138,12 @@ private static void Main(string[] args)
112138

113139
TrapExitScenarios();
114140

115-
if (config.RegularOutput)
116-
{
117-
#if DEBUG
118-
"chocolatey".Log().Info(ChocolateyLoggers.Important, () => "{0} v{1}{2} (DEBUG BUILD)".FormatWith(ApplicationParameters.Name, config.Information.ChocolateyProductVersion, license.IsLicensedVersion() ? " {0}".FormatWith(license.LicenseType) : string.Empty));
119-
#else
120-
"chocolatey".Log().Info(ChocolateyLoggers.Important, () => "{0} v{1}{2}".FormatWith(ApplicationParameters.Name, config.Information.ChocolateyProductVersion, license.IsLicensedVersion() ? " {0}".FormatWith(license.LicenseType) : string.Empty));
121-
#endif
122-
if (args.Length == 0)
123-
{
124-
"chocolatey".Log().Info(ChocolateyLoggers.Important, () => "Please run 'choco --help' or 'choco <command> --help' for help menu.");
125-
}
126-
}
141+
DisplayProgramInformation(
142+
config.RegularOutput,
143+
args,
144+
config.Information.ChocolateyProductVersion,
145+
license
146+
);
127147

128148
ThrowIfNotDotNet48();
129149

@@ -328,18 +348,32 @@ private static void ThrowIfNotDotNet48()
328348
const int net48ReleaseBuild = 528040;
329349
const string regKey = @"SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\";
330350

331-
using (var ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32).OpenSubKey(regKey))
351+
// Use 64 bit hive as it will read the 32 bit hive on 32 bit system: https://learn.microsoft.com/en-us/dotnet/api/microsoft.win32.registryview
352+
using (var ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64).OpenSubKey(regKey))
332353
{
333354
if (ndpKey == null || ndpKey.GetValue("Release") == null || (int)ndpKey.GetValue("Release") < net48ReleaseBuild)
334355
{
335-
throw new ApplicationException(
336-
@".NET 4.8 is not installed or may need a reboot to complete installation.
337-
Please install .NET Framework 4.8 manually and reboot the system.
338-
Download at 'https://download.visualstudio.microsoft.com/download/pr/2d6bb6b2-226a-4baa-bdec-798822606ff1/8494001c276a4b96804cde7829c04d7f/ndp48-x86-x64-allos-enu.exe'"
339-
.FormatWith(Environment.NewLine));
356+
throw new ApplicationException(".NET 4.8 is not installed or may need a reboot to complete installation.{0}".FormatWith(DotNetDownload));
340357
}
341358
}
342359
}
343360
}
361+
362+
private static void DisplayProgramInformation(bool configRegularOutput, string[] args, string chocolateyVersion, ChocolateyLicense license)
363+
{
364+
if (configRegularOutput)
365+
{
366+
var buildType = string.Empty;
367+
#if DEBUG
368+
buildType = " (DEBUG BUILD)";
369+
#endif
370+
"chocolatey".Log().Info(ChocolateyLoggers.Important, () => "{0} v{1}{2}{3}".FormatWith(ApplicationParameters.Name, chocolateyVersion, license.IsLicensedVersion() ? " {0}".FormatWith(license.LicenseType) : string.Empty, buildType));
371+
372+
if (args.Length == 0)
373+
{
374+
"chocolatey".Log().Info(ChocolateyLoggers.Important, () => "Please run 'choco --help' or 'choco <command> --help' for help menu.");
375+
}
376+
}
377+
}
344378
}
345379
}

0 commit comments

Comments
 (0)