How to get the path of a "SelfContained" and "PublishSingleFile" exe?

Viewed 1256

I have a directory which contains a self-contained "exe" and a config file. The exe has to read this config file. But the problem is that the exe can not get the right path of this config file.

Let me first talk about how I did it.

  1. Create a NET5.0 project in VS2019

enter image description here

  1. Add codes
using System;
using System.IO;
using System.Reflection;

namespace TestFile {
    class Program {
        static void Main(string[] args) {
            string assemblyLocation = Assembly.GetEntryAssembly().Location;
            Console.WriteLine($"assemblyLocation=\"{assemblyLocation}\"");
            string configFile = Path.Combine((new FileInfo(assemblyLocation)).DirectoryName, "test.conf");
            Console.WriteLine($"configFile=\"{configFile}\"");
            File.ReadAllText(configFile);
        }
    }
}
  1. Publish this project to a "SelfContained" and "PublishSingleFile" exe

enter image description here

enter image description here

  1. Add file "test.conf" in the directory where the exe locates

enter image description here

  1. Run this exe

enter image description here

How can I get the right path of this config file?

2 Answers

Take a look at this question: How can I get my .NET Core 3 single file app to find the appsettings.json file?

.NET Core 3.1

Self-contained .NET Core applications are automatically extracted into a temporary folder. So the path of the published executable is different from the path of the executed assembly.

That's way you have to use this: Path.GetDirectoryName(Process.GetCurrentProcess().MainModule)

.NET 5 and onwards

With .NET 5, this became easier: now you can simply place appsettings.json beside the EXE. By adding var config = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build(); the file will be read and the config can be accessed.

For other files, you can use AppDomain.CurrentDomain.BaseDirectory.

I had read the recommended way was Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName), however this returned null for me (.NET 6). I suspect it's because the code was within a DLL from another project. In either case, a more robust method seems to be AppContext.BaseDirectory. It's used by .NET to search for assembly dependencies, and will point to the base application directory. Pretty easy to remember and will give you the directory rather than a filename right away!

Related