From ba9792a083a7d9409dfd3dd08ba15d9c2eec8003 Mon Sep 17 00:00:00 2001 From: Matthew John Cheetham Date: Thu, 25 Feb 2021 12:46:42 +0000 Subject: [PATCH] program: fix computation of app path with single file When publishing GCM as a 'single file' application, the computed path to the entry executable is no longer correct. On .NET Core 3.1, using Assembly.Location resolves to the temporary extracted DLL file path. On .NET 5 Assembly.Location always returns the empty string. Since .NET 5, published single-file apps no longer use the self- extraction model, and are real single file with all assemblies and native libraries statically linked/bundled. We now use the Environment.GetCommandLineArgs() method to get the raw underlying "argv" arguments, which argv[0] is the absolute file path to the entry executable. --- src/shared/Git-Credential-Manager/Program.cs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/shared/Git-Credential-Manager/Program.cs b/src/shared/Git-Credential-Manager/Program.cs index 4329dc65ae..5d12e80e31 100644 --- a/src/shared/Git-Credential-Manager/Program.cs +++ b/src/shared/Git-Credential-Manager/Program.cs @@ -3,6 +3,7 @@ using System; using System.IO; using System.Reflection; +using System.Runtime.InteropServices; using Atlassian.Bitbucket; using GitHub; using Microsoft.AzureRepos; @@ -36,16 +37,17 @@ public static void Main(string[] args) private static string GetApplicationPath() { - Assembly entryAssembly = Assembly.GetExecutingAssembly(); - if (entryAssembly is null) - { - throw new InvalidOperationException(); - } + // Assembly::Location always returns an empty string if the application was published as a single file + bool isSingleFile = string.IsNullOrEmpty(Assembly.GetEntryAssembly()?.Location); - string candidatePath = entryAssembly.Location; + // Use "argv[0]" to get the full path to the entry executable - this is consistent across + // .NET Framework and .NET >= 5 when published as a single file. + string[] args = Environment.GetCommandLineArgs(); + string candidatePath = args[0]; - // Strip the .dll from assembly name on Mac and Linux - if (!PlatformUtils.IsWindows() && Path.HasExtension(candidatePath)) + // If we have not been published as a single file on .NET 5 then we must strip the ".dll" file extension + // to get the default AppHost/SuperHost name. + if (!isSingleFile && Path.HasExtension(candidatePath)) { return Path.ChangeExtension(candidatePath, null); }