Skip to content

Commit

Permalink
Use CSharpier
Browse files Browse the repository at this point in the history
  • Loading branch information
Tyrrrz committed Aug 22, 2023
1 parent 2fd3ca4 commit 7c713ce
Show file tree
Hide file tree
Showing 62 changed files with 467 additions and 390 deletions.
26 changes: 19 additions & 7 deletions DotnetRuntimeBootstrapper.AppHost.Cli/Bootstrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,14 @@ protected override void ReportError(string message)

protected override bool Prompt(
TargetAssembly targetAssembly,
IPrerequisite[] missingPrerequisites)
IPrerequisite[] missingPrerequisites
)
{
using (ConsoleEx.WithForegroundColor(ConsoleColor.DarkRed))
{
Console.Error.WriteLine($"Your system is missing runtime components required by {targetAssembly.Name}:");
Console.Error.WriteLine(
$"Your system is missing runtime components required by {targetAssembly.Name}:"
);

foreach (var prerequisite in missingPrerequisites)
Console.Error.WriteLine($" - {prerequisite.DisplayName}");
Expand All @@ -54,7 +57,9 @@ protected override void ReportError(string message)
// When not running in interactive mode, instruct the user to set the environment variable instead
else
{
Console.Error.Write("To install the missing components automatically, set the environment variable ");
Console.Error.Write(
"To install the missing components automatically, set the environment variable "
);

using (ConsoleEx.WithForegroundColor(ConsoleColor.DarkCyan))
Console.Error.Write(AcceptPromptEnvironmentVariable);
Expand Down Expand Up @@ -85,7 +90,8 @@ protected override void ReportError(string message)

protected override bool Install(
TargetAssembly targetAssembly,
IPrerequisite[] missingPrerequisites)
IPrerequisite[] missingPrerequisites
)
{
using (ConsoleEx.WithForegroundColor(ConsoleColor.White))
Console.Out.WriteLine($"{targetAssembly.Name}: installing prerequisites");
Expand All @@ -101,7 +107,11 @@ protected override void ReportError(string message)
Console.Out.Write($"Downloading {prerequisite.DisplayName}... ");

// Only write progress if running in interactive mode
using (var progress = new ConsoleProgress(ConsoleEx.IsInteractive ? Console.Out : TextWriter.Null))
using (
var progress = new ConsoleProgress(
ConsoleEx.IsInteractive ? Console.Out : TextWriter.Null
)
)
{
var installer = prerequisite.DownloadInstaller(progress.Report);
installers.Add(installer);
Expand Down Expand Up @@ -141,7 +151,9 @@ protected override void ReportError(string message)
if (isRebootRequired)
{
using (ConsoleEx.WithForegroundColor(ConsoleColor.DarkYellow))
Console.Out.WriteLine($"You need to restart Windows before you can run {targetAssembly.Name}.");
Console.Out.WriteLine(
$"You need to restart Windows before you can run {targetAssembly.Name}."
);

// Only prompt for reboot if running in interactive mode
if (ConsoleEx.IsInteractive)
Expand All @@ -163,4 +175,4 @@ protected override void ReportError(string message)
}

public static int Main(string[] args) => new Bootstrapper().Run(args);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="CSharpier.MsBuild" Version="0.25.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="all" />
<PackageReference Include="PolyShim" Version="1.5.0" PrivateAssets="all" />
<PackageReference Include="QuickJson" Version="1.1.0" PrivateAssets="all" />
Expand Down
10 changes: 5 additions & 5 deletions DotnetRuntimeBootstrapper.AppHost.Cli/Utils/ConsoleEx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ namespace DotnetRuntimeBootstrapper.AppHost.Cli.Utils;
internal static class ConsoleEx
{
public static bool IsInteractive =>
NativeMethods.GetConsoleWindow() != 0 &&
NativeMethods.GetFileType(NativeMethods.GetStdHandle(-10)) == 2 &&
NativeMethods.GetFileType(NativeMethods.GetStdHandle(-11)) == 2 &&
NativeMethods.GetFileType(NativeMethods.GetStdHandle(-12)) == 2;
NativeMethods.GetConsoleWindow() != 0
&& NativeMethods.GetFileType(NativeMethods.GetStdHandle(-10)) == 2
&& NativeMethods.GetFileType(NativeMethods.GetStdHandle(-11)) == 2
&& NativeMethods.GetFileType(NativeMethods.GetStdHandle(-12)) == 2;

public static IDisposable WithForegroundColor(ConsoleColor color)
{
var lastColor = Console.ForegroundColor;
Console.ForegroundColor = color;
return Disposable.Create(() => Console.ForegroundColor = lastColor);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ private void Write(string text)
public void Report(double progress) => Write($"{progress:P1}");

public void Dispose() => EraseLast();
}
}
29 changes: 12 additions & 17 deletions DotnetRuntimeBootstrapper.AppHost.Core/BootstrapperBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ public abstract class BootstrapperBase
protected const string LegacyAcceptPromptEnvironmentVariable = "DOTNET_INSTALL_PREREQUISITES";
protected const string AcceptPromptEnvironmentVariable = "DOTNET_ENABLE_BOOTSTRAPPER";

protected BootstrapperConfiguration Configuration { get; } = BootstrapperConfiguration.Resolve();
protected BootstrapperConfiguration Configuration { get; } =
BootstrapperConfiguration.Resolve();

protected virtual void ReportError(string message)
{
Expand All @@ -25,8 +26,7 @@ protected virtual void ReportError(string message)
var applicationName = Path.GetFileName(applicationFilePath);
var bootstrapperVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString(3);

var content =
$"""
var content = $"""
Description: Bootstrapper for a .NET application has failed.
Application: {applicationName}
Path: {applicationFilePath}
Expand Down Expand Up @@ -54,31 +54,26 @@ IPrerequisite[] missingPrerequisites

private bool PromptAndInstall(
TargetAssembly targetAssembly,
IPrerequisite[] missingPrerequisites)
IPrerequisite[] missingPrerequisites
)
{
// Install prompt can be disabled in bootstrap configuration or via environment variable
var isPromptPreAccepted =
!Configuration.IsPromptRequired
||
string.Equals(
|| string.Equals(
Environment.GetEnvironmentVariable(AcceptPromptEnvironmentVariable),
"true",
StringComparison.OrdinalIgnoreCase
)
||
string.Equals(
|| string.Equals(
Environment.GetEnvironmentVariable(LegacyAcceptPromptEnvironmentVariable),
"true",
StringComparison.OrdinalIgnoreCase
);

var isPromptAccepted =
isPromptPreAccepted ||
Prompt(targetAssembly, missingPrerequisites);
var isPromptAccepted = isPromptPreAccepted || Prompt(targetAssembly, missingPrerequisites);

return
isPromptAccepted &&
Install(targetAssembly, missingPrerequisites);
return isPromptAccepted && Install(targetAssembly, missingPrerequisites);
}

private int Run(TargetAssembly targetAssembly, string[] args)
Expand Down Expand Up @@ -126,8 +121,8 @@ public int Run(string[] args)
{
var targetAssembly = TargetAssembly.Resolve(
Path.Combine(
Path.GetDirectoryName(EnvironmentEx.ProcessPath) ??
AppDomain.CurrentDomain.BaseDirectory,
Path.GetDirectoryName(EnvironmentEx.ProcessPath)
?? AppDomain.CurrentDomain.BaseDirectory,
Configuration.TargetFileName
)
);
Expand All @@ -140,4 +135,4 @@ public int Run(string[] args)
return 0xDEAD;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ public partial class BootstrapperConfiguration
{
public static BootstrapperConfiguration Resolve()
{
var data = Assembly.GetExecutingAssembly().GetManifestResourceString(nameof(BootstrapperConfiguration));
var data = Assembly
.GetExecutingAssembly()
.GetManifestResourceString(nameof(BootstrapperConfiguration));
var parsed = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

foreach (var line in data.Split('\n'))
Expand All @@ -34,12 +36,11 @@ public static BootstrapperConfiguration Resolve()
return new BootstrapperConfiguration
{
TargetFileName = parsed[nameof(TargetFileName)],

IsPromptRequired = string.Equals(
parsed[nameof(IsPromptRequired)],
"true",
StringComparison.OrdinalIgnoreCase
)
};
}
}
}
44 changes: 23 additions & 21 deletions DotnetRuntimeBootstrapper.AppHost.Core/Dotnet/DotnetHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,19 @@ internal partial class DotnetHost : IDisposable
);

private InitializeForCommandLineFn GetInitializeForCommandLineFn() =>
_hostResolverLibrary.GetFunction<InitializeForCommandLineFn>("hostfxr_initialize_for_dotnet_command_line");
_hostResolverLibrary.GetFunction<InitializeForCommandLineFn>(
"hostfxr_initialize_for_dotnet_command_line"
);

[UnmanagedFunctionPointer(CallingConvention.Cdecl, SetLastError = true)]
private delegate int RunAppFn(nint handle);

private RunAppFn GetRunAppFn() =>
_hostResolverLibrary.GetFunction<RunAppFn>("hostfxr_run_app");
private RunAppFn GetRunAppFn() => _hostResolverLibrary.GetFunction<RunAppFn>("hostfxr_run_app");

[UnmanagedFunctionPointer(CallingConvention.Cdecl, SetLastError = true)]
private delegate int CloseFn(nint handle);

private CloseFn GetCloseFn() =>
_hostResolverLibrary.GetFunction<CloseFn>("hostfxr_close");
private CloseFn GetCloseFn() => _hostResolverLibrary.GetFunction<CloseFn>("hostfxr_close");

private nint Initialize(string targetFilePath, string[] args)
{
Expand All @@ -72,9 +72,8 @@ private nint Initialize(string targetFilePath, string[] args)

if (status != 0)
{
var error = errorBuffer.Length > 0
? errorBuffer.ToString()
: "No error messages reported.";
var error =
errorBuffer.Length > 0 ? errorBuffer.ToString() : "No error messages reported.";

throw new ApplicationException(
$"""
Expand Down Expand Up @@ -102,10 +101,10 @@ private int Run(nint handle)
// Unfortunately, there is no way to get the original exception or its message.
// https://github.com/Tyrrrz/DotnetRuntimeBootstrapper/issues/23
throw new ApplicationException(
"Application crashed with an unhandled exception. " +
"Unfortunately, it was not possible to retrieve the exception message or its stacktrace. " +
"Please check the Windows Event Viewer to see if the runtime logged any additional information. " +
"If you are the developer of the application, consider adding a global exception handler to provide a more detailed error message to the user.",
"Application crashed with an unhandled exception. "
+ "Unfortunately, it was not possible to retrieve the exception message or its stacktrace. "
+ "Please check the Windows Event Viewer to see if the runtime logged any additional information. "
+ "If you are the developer of the application, consider adding a global exception handler to provide a more detailed error message to the user.",
ex
);
}
Expand Down Expand Up @@ -146,9 +145,15 @@ private static string GetHostResolverFilePath()
// 1. Find the hostfxr directory containing versioned subdirectories
// 2. Get the hostfxr.dll from the subdirectory with the highest version number

var hostResolverRootDirPath = PathEx.Combine(DotnetInstallation.GetDirectoryPath(), "host", "fxr");
var hostResolverRootDirPath = PathEx.Combine(
DotnetInstallation.GetDirectoryPath(),
"host",
"fxr"
);
if (!Directory.Exists(hostResolverRootDirPath))
throw new DirectoryNotFoundException("Could not find directory containing hostfxr.dll.");
throw new DirectoryNotFoundException(
"Could not find directory containing hostfxr.dll."
);

var hostResolverFilePath = (
from dirPath in Directory.GetDirectories(hostResolverRootDirPath)
Expand All @@ -160,12 +165,9 @@ where File.Exists(filePath)
select filePath
).FirstOrDefault();

return
hostResolverFilePath ??
throw new FileNotFoundException("Could not find hostfxr.dll.");
return hostResolverFilePath
?? throw new FileNotFoundException("Could not find hostfxr.dll.");
}

public static DotnetHost Load() => new(
NativeLibrary.Load(GetHostResolverFilePath())
);
}
public static DotnetHost Load() => new(NativeLibrary.Load(GetHostResolverFilePath()));
}
27 changes: 15 additions & 12 deletions DotnetRuntimeBootstrapper.AppHost.Core/Dotnet/DotnetInstallation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ internal static class DotnetInstallation
private static string? TryGetDirectoryPathFromRegistry()
{
var dotnetRegistryKey = Registry.LocalMachine.OpenSubKey(
(OperatingSystemEx.ProcessorArchitecture.Is64Bit()
? "SOFTWARE\\Wow6432Node\\"
: "SOFTWARE\\") +
"dotnet\\Setup\\InstalledVersions\\" +
OperatingSystemEx.ProcessorArchitecture.GetMoniker(),
(
OperatingSystemEx.ProcessorArchitecture.Is64Bit()
? "SOFTWARE\\Wow6432Node\\"
: "SOFTWARE\\"
)
+ "dotnet\\Setup\\InstalledVersions\\"
+ OperatingSystemEx.ProcessorArchitecture.GetMoniker(),
false
);

Expand All @@ -31,9 +33,9 @@ internal static class DotnetInstallation
// if the apphost is running in x86 mode on an x64 system, so we rely
// on an environment variable instead.
var programFilesDirPath =
Environment.GetEnvironmentVariable("PROGRAMFILES") ??
Environment.GetEnvironmentVariable("ProgramW6432") ??
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
Environment.GetEnvironmentVariable("PROGRAMFILES")
?? Environment.GetEnvironmentVariable("ProgramW6432")
?? Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);

var dotnetDirPath = Path.Combine(programFilesDirPath, "dotnet");

Expand All @@ -46,8 +48,9 @@ internal static class DotnetInstallation
// https://github.com/dotnet/designs/blob/main/accepted/2020/install-locations.md
public static string GetDirectoryPath() =>
// Try to resolve location from registry (covers both custom and default locations)
TryGetDirectoryPathFromRegistry() ??
TryGetDirectoryPathFromRegistry()
??
// Try to resolve location from program files (default location)
TryGetDirectoryPathFromEnvironment() ??
throw new DirectoryNotFoundException("Could not find .NET installation directory.");
}
TryGetDirectoryPathFromEnvironment()
?? throw new DirectoryNotFoundException("Could not find .NET installation directory.");
}
Loading

0 comments on commit 7c713ce

Please sign in to comment.