2

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?

TylerH
  • 20,799
  • 66
  • 75
  • 101
  • 1
    Try to mark `test.conf` with *Build Action = Content* and *Copy to Output Directory = Always* – mu88 Nov 18 '20 at 10:55
  • 1
    Other option would be to pass path to `test.conf` as command-line argument and extract it within `Main()` – mu88 Nov 18 '20 at 10:57
  • Neither of these two options. Is there another way? –  Nov 18 '20 at 11:13
  • Could you please describe what does not work with the two options? – mu88 Nov 18 '20 at 12:02
  • 1, The config file should be modified for different users. 2, Later i will add "Worker Service" in this project and then this exe will be used as a windows service. –  Nov 18 '20 at 12:12
  • 1
    Maybe try this: https://stackoverflow.com/questions/58307558/how-can-i-get-my-net-core-3-single-file-app-to-find-the-appsettings-json-file – mu88 Nov 18 '20 at 12:17
  • thanks, Path.GetDirectoryName(Process.GetCurrentProcess().MainModule) works well. –  Nov 18 '20 at 12:32
  • I'm glad this helps! If it's okay for you, I'll post an answer so that we can close this question – mu88 Nov 18 '20 at 12:35

2 Answers2

4

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.

mu88
  • 4,156
  • 1
  • 23
  • 47
  • Note that this no longer works on .NET 5 unless you use the IncludeAllContentForSelfExtract flag, which reverts behavior to .NET Core 3 style self contained – Mgamerz May 04 '21 at 17:37
  • What if I have another type of file that I need to access in .Net 6? not the settings file? Can I find the path for it? – pauloya Jul 11 '22 at 22:26
  • 1
    @pauloya I've updated my answer. [See also here](https://github.com/mu88/Project28/blob/main/src/Persistence/Impl/Storage.cs#L48) for an example. – mu88 Jul 12 '22 at 15:33
1

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!

Jonas
  • 1,172
  • 1
  • 16
  • 26