From 57e72364b865ffcdf22d9050eb711b6b873b3277 Mon Sep 17 00:00:00 2001 From: Samuel Lucas <63159663+samuel-lucas6@users.noreply.github.com> Date: Sun, 11 Aug 2024 15:38:00 +0100 Subject: [PATCH] Program.cs: Hide vcruntime140.dll from the user on Windows. Instead of extracting the DLL to the same directory as the executable, this extracts it to the .NET created directory where libsodium.dll lives. This is unfortunately quite complicated because there are multiple directories that could be being used. The user can also avoid the default %TEMP%/.net directory by setting the DOTNET_BUNDLE_EXTRACT_BASE_DIR environment variable. See here: https://learn.microsoft.com/en-us/dotnet/core/deploying/single-file/overview?tabs=cli#native-libraries --- src/Kryptor/Program.cs | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/src/Kryptor/Program.cs b/src/Kryptor/Program.cs index b7a66d0..e720d54 100644 --- a/src/Kryptor/Program.cs +++ b/src/Kryptor/Program.cs @@ -70,7 +70,7 @@ public class Program [Option("-r|--recover", "recover your public key from your private key", CommandOptionType.NoValue)] private bool RecoverPublicKey { get; } - + [Option("-m|--modify", "change your private key passphrase", CommandOptionType.NoValue)] private bool ChangePrivateKeyPassphrase { get; } @@ -99,7 +99,9 @@ public class Program private int OnExecute() { - ExtractVisualCRuntime(); + if (OperatingSystem.IsWindows()) { + ExtractVisualCRuntime(); + } Globals.Overwrite = Overwrite; Globals.EncryptFileNames = EncryptFileNames; Globals.TotalCount = FilePaths?.Length ?? 0; @@ -144,20 +146,30 @@ private int OnExecute() } return Environment.ExitCode; } - + private static void ExtractVisualCRuntime() { - try - { - string vcruntimeFilePath = Path.Combine(Path.GetDirectoryName(Environment.ProcessPath), "vcruntime140.dll"); - if (!OperatingSystem.IsWindows() || File.Exists(vcruntimeFilePath)) { - return; + try { + const string environmentVariable = "DOTNET_BUNDLE_EXTRACT_BASE_DIR"; + string executableFileName = Path.GetFileNameWithoutExtension(Environment.ProcessPath); + // The environment variables take priority in this order + string environmentDirectory = Environment.GetEnvironmentVariable(environmentVariable, EnvironmentVariableTarget.Process) ?? Environment.GetEnvironmentVariable(environmentVariable, EnvironmentVariableTarget.User) ?? Environment.GetEnvironmentVariable(environmentVariable, EnvironmentVariableTarget.Machine); + if (!string.IsNullOrWhiteSpace(environmentDirectory)) { + environmentDirectory = Path.Combine(environmentDirectory, executableFileName); } - if (Environment.Is64BitOperatingSystem) { - File.WriteAllBytes(vcruntimeFilePath, Properties.Resources.vcruntime140x64); - return; + string defaultDirectory = Path.Combine(Path.GetTempPath(), ".net", executableFileName); + string[] subdirectories = Directory.GetDirectories(!Directory.Exists(environmentDirectory) ? defaultDirectory : environmentDirectory); + foreach (var directory in subdirectories) { + string vcruntimeFilePath = Path.Combine(directory, "vcruntime140.dll"); + if (File.Exists(vcruntimeFilePath)) { + continue; + } + if (Environment.Is64BitOperatingSystem) { + File.WriteAllBytes(vcruntimeFilePath, Properties.Resources.vcruntime140x64); + continue; + } + File.WriteAllBytes(vcruntimeFilePath, Properties.Resources.vcruntime140x86); } - File.WriteAllBytes(vcruntimeFilePath, Properties.Resources.vcruntime140x86); } catch (Exception ex) when (ExceptionFilters.FileAccess(ex)) { @@ -171,4 +183,4 @@ private static void ExtractVisualCRuntime() private static string GetSigningPrivateKey(string privateKeyPath) => string.IsNullOrEmpty(privateKeyPath) ? Constants.DefaultSigningPrivateKeyPath : privateKeyPath; public static string GetVersion() => Assembly.GetExecutingAssembly().GetName().Version?.ToString(fieldCount: 3); -} \ No newline at end of file +}