Reputation: 188
I published a .NET Core console app with '/p:PublishSingleFile=true' option, but now assembly path is the temporary path where it inflated to.
Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)
now returns:
C:\Users\DEFUSER\AppData\Local\Temp\.net\myApp\3dzfa4fp.353\_myApp.json
originally:
C:\devel\myApp\bin\publish\_myApp.json
How can I get the original path of where i put the exe file originally?
thanks in advance!
Upvotes: 11
Views: 4001
Reputation: 141565
Docs for single-file deployment and executable mention that some Assembly
APIs will not work in this mode, including Location
, which will return an empty string:
API | Note |
---|---|
Assembly.CodeBase |
Throws System.PlatformNotSupportedException . |
Assembly.EscapedCodeBase |
Throws System.PlatformNotSupportedException . |
Assembly.GetFile |
Throws System.IO.IOException . |
Assembly.GetFiles |
Throws System.IO.IOException . |
Assembly.Location |
Returns an empty string. |
AssemblyName.CodeBase |
Returns null . |
AssemblyName.EscapedCodeBase |
Returns null . |
Module.FullyQualifiedName |
Returns a string with the value of <Unknown> or throws an exception. |
Marshal.GetHINSTANCE |
Returns -1. |
Module.Name |
Returns a string with the value of <Unknown> . |
There are some workarounds mentioned:
To access files next to the executable, use System.AppContext.BaseDirectory
To find the file name of the executable, use the first element of System.Environment.GetCommandLineArgs
, or starting with .NET 6, use the file name from System.Environment.ProcessPath
.
So based on this you can use Environment.ProcessPath
(since .NET 6) or Environment.GetCommandLineArgs()[0]
(since .NET 5, can be preferable in cases when the executable is distributed and run in different ways, i.e. via single file, .exe or via dotnet
command).
From Environment.GetCommandLineArgs
remarks:
The first element in the array contains the file name of the executing program. If the file name is not available, the first element is equal to String.Empty. The remaining elements contain any additional tokens entered on the command line.
In .NET 5 and later versions, for single-file publishing, the first element is the name of the host executable.
Upvotes: 6
Reputation: 23208
There is a new .NET 6.0 property Environment.ProcessPath
added exactly for that reason
Returns the path of the executable that started the currently executing process
Design notes can be found here
Upvotes: 7
Reputation: 2803
Based on https://github.com/dotnet/coreclr/issues/25623, which was also confirmed by Scott Hanselman a year later:
Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName)
AppContext.BaseDirectory
.Upvotes: 23