[c#] How can I get the application's path in a .NET console application?

How do I find the application's path in a console application?

In Windows Forms, I can use Application.StartupPath to find the current path, but this doesn't seem to be available in a console application.

This question is related to c# .net console console-application

The answer is


Another solution is using relative paths pointing to the current path:

Path.GetFullPath(".")

The answer above was 90% of what I needed, but returned a Uri instead of a regular path for me.

As explained in the MSDN forums post, How to convert URI path to normal filepath?, I used the following:

// Get normal filepath of this assembly's permanent directory
var path = new Uri(
    System.IO.Path.GetDirectoryName(
        System.Reflection.Assembly.GetExecutingAssembly().CodeBase)
    ).LocalPath;

Probably a bit late but this is worth a mention:

Environment.GetCommandLineArgs()[0];

Or more correctly to get just the directory path:

System.IO.Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]);

Edit:

Quite a few people have pointed out that GetCommandLineArgs is not guaranteed to return the program name. See The first word on the command line is the program name only by convention. The article does state that "Although extremely few Windows programs use this quirk (I am not aware of any myself)". So it is possible to 'spoof' GetCommandLineArgs, but we are talking about a console application. Console apps are usually quick and dirty. So this fits in with my KISS philosophy.


I have used

System.AppDomain.CurrentDomain.BaseDirectory

when I want to find a path relative to an applications folder. This works for both ASP.Net and winform applications. It also does not require any reference to System.Web assemblies.


There are many ways to get executable path, which one we should use it depends on our needs here is a link which discuss different methods.

Different ways to get Application Executable Path


You may be looking to do this:

System.IO.Path.GetDirectoryName(
    System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)

You can simply add to your project references System.Windows.Forms and then use the System.Windows.Forms.Application.StartupPath as usual .

So, not need for more complicated methods or using the reflection.


Try this simple line of code:

 string exePath = Path.GetDirectoryName( Application.ExecutablePath);

Here is a reliable solution that works with 32bit and 64bit applications.

Add these references:

using System.Diagnostics;

using System.Management;

Add this method to your project:

public static string GetProcessPath(int processId)
{
    string MethodResult = "";
    try
    {
        string Query = "SELECT ExecutablePath FROM Win32_Process WHERE ProcessId = " + processId;

        using (ManagementObjectSearcher mos = new ManagementObjectSearcher(Query))
        {
            using (ManagementObjectCollection moc = mos.Get())
            {
                string ExecutablePath = (from mo in moc.Cast<ManagementObject>() select mo["ExecutablePath"]).First().ToString();

                MethodResult = ExecutablePath;

            }

        }

    }
    catch //(Exception ex)
    {
        //ex.HandleException();
    }
    return MethodResult;
}

Now use it like so:

int RootProcessId = Process.GetCurrentProcess().Id;

GetProcessPath(RootProcessId);

Notice that if you know the id of the process, then this method will return the corresponding ExecutePath.

Extra, for those interested:

Process.GetProcesses() 

...will give you an array of all the currently running processes, and...

Process.GetCurrentProcess()

...will give you the current process, along with their information e.g. Id, etc. and also limited control e.g. Kill, etc.*


You have two options for finding the directory of the application, which you choose will depend on your purpose.

// to get the location the assembly is executing from
//(not necessarily where the it normally resides on disk)
// in the case of the using shadow copies, for instance in NUnit tests, 
// this will be in a temp directory.
string path = System.Reflection.Assembly.GetExecutingAssembly().Location;

//To get the location the assembly normally resides on disk or the install directory
string path = System.Reflection.Assembly.GetExecutingAssembly().CodeBase;

//once you have the path you get the directory with:
var directory = System.IO.Path.GetDirectoryName(path);

in VB.net

My.Application.Info.DirectoryPath

works for me (Application Type: Class Library). Not sure about C#... Returns the path w/o Filename as string


you can use this one instead.

System.Environment.CurrentDirectory

For Console Applications, you can try this:

System.IO.Directory.GetCurrentDirectory();

Output (on my local machine):

c:\users\xxxxxxx\documents\visual studio 2012\Projects\ImageHandler\GetDir\bin\Debug

Or you can try (there's an additional backslash in the end):

AppDomain.CurrentDomain.BaseDirectory

Output:

c:\users\xxxxxxx\documents\visual studio 2012\Projects\ImageHandler\GetDir\bin\Debug\


If you are looking for a .NET Core compatible way, use

System.AppContext.BaseDirectory

This was introduced in .NET Framework 4.6 and .NET Core 1.0 (and .NET Standard 1.3). See: AppContext.BaseDirectory Property.

According to this page,

This is the prefered replacement for AppDomain.CurrentDomain.BaseDirectory in .NET Core


Following line will give you an application path:

var applicationPath = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName)

Above solution is working properly in the following situations:

  • simple app
  • in another domain where Assembly.GetEntryAssembly() would return null
  • DLL is loaded from Embedded resources as a byte array and loaded to AppDomain as Assembly.Load(byteArrayOfEmbeddedDll)
  • with Mono's mkbundle bundles (no other methods work)

I have used this code and get the solution.

AppDomain.CurrentDomain.BaseDirectory

Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName) Is the only one that has worked for me in every case I have tried.


You can create a folder name as Resources within the project using Solution Explorer,then you can paste a file within the Resources.

private void Form1_Load(object sender, EventArgs e) {
    string appName = Environment.CurrentDirectory;
    int l = appName.Length;
    int h = appName.LastIndexOf("bin");
    string ll = appName.Remove(h);                
    string g = ll + "Resources\\sample.txt";
    System.Diagnostics.Process.Start(g);
}

I mean, why not a p/invoke method?

    using System;
    using System.IO;
    using System.Runtime.InteropServices;
    using System.Text;
    public class AppInfo
    {
            [DllImport("kernel32.dll", CharSet = CharSet.Auto, ExactSpelling = false)]
            private static extern int GetModuleFileName(HandleRef hModule, StringBuilder buffer, int length);
            private static HandleRef NullHandleRef = new HandleRef(null, IntPtr.Zero);
            public static string StartupPath
            {
                get
                {
                    StringBuilder stringBuilder = new StringBuilder(260);
                    GetModuleFileName(NullHandleRef, stringBuilder, stringBuilder.Capacity);
                    return Path.GetDirectoryName(stringBuilder.ToString());
                }
            }
    }

You would use it just like the Application.StartupPath:

    Console.WriteLine("The path to this executable is: " + AppInfo.StartupPath + "\\" + System.Diagnostics.Process.GetCurrentProcess().ProcessName + ".exe");

I didn't see anyone convert the LocalPath provided by .Net Core reflection into a usable System.IO path so here's my version.

public static string GetApplicationRoot()
{
   var exePath = new Uri(System.Reflection.
   Assembly.GetExecutingAssembly().CodeBase).LocalPath;

   return new FileInfo(exePath).DirectoryName;
       
}

This will return the full C:\\xxx\\xxx formatted path to where your code is.


AppDomain.CurrentDomain.BaseDirectory

Will resolve the issue to refer the 3rd party reference files with installation packages.


None of these methods work in special cases like using a symbolic link to the exe, they will return the location of the link not the actual exe.

So can use QueryFullProcessImageName to get around that:

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Diagnostics;

internal static class NativeMethods
{
    [DllImport("kernel32.dll", SetLastError = true)]
    internal static extern bool QueryFullProcessImageName([In]IntPtr hProcess, [In]int dwFlags, [Out]StringBuilder lpExeName, ref int lpdwSize);

    [DllImport("kernel32.dll", SetLastError = true)]
    internal static extern IntPtr OpenProcess(
        UInt32 dwDesiredAccess,
        [MarshalAs(UnmanagedType.Bool)]
        Boolean bInheritHandle,
        Int32 dwProcessId
    );
}

public static class utils
{

    private const UInt32 PROCESS_QUERY_INFORMATION = 0x400;
    private const UInt32 PROCESS_VM_READ = 0x010;

    public static string getfolder()
    {
        Int32 pid = Process.GetCurrentProcess().Id;
        int capacity = 2000;
        StringBuilder sb = new StringBuilder(capacity);
        IntPtr proc;

        if ((proc = NativeMethods.OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, pid)) == IntPtr.Zero)
            return "";

        NativeMethods.QueryFullProcessImageName(proc, 0, sb, ref capacity);

        string fullPath = sb.ToString(0, capacity);

        return Path.GetDirectoryName(fullPath) + @"\";
    }
}

Assembly.GetEntryAssembly().Location or Assembly.GetExecutingAssembly().Location

Use in combination with System.IO.Path.GetDirectoryName() to get only the directory.

The paths from GetEntryAssembly() and GetExecutingAssembly() can be different, even though for most cases the directory will be the same.

With GetEntryAssembly() you have to be aware that this can return null if the entry module is unmanaged (ie C++ or VB6 executable). In those cases it is possible to use GetModuleFileName from the Win32 API:

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetModuleFileName(HandleRef hModule, StringBuilder buffer, int length);

For anyone interested in asp.net web apps. Here are my results of 3 different methods

protected void Application_Start(object sender, EventArgs e)
{
  string p1 = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
  string p2 = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath;
  string p3 = this.Server.MapPath("");
  Console.WriteLine("p1 = " + p1);
  Console.WriteLine("p2 = " + p2);
  Console.WriteLine("p3 = " + p3);
}

result

p1 = C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\a897dd66\ec73ff95\assembly\dl3\ff65202d\29daade3_5e84cc01
p2 = C:\inetpub\SBSPortal_staging\
p3 = C:\inetpub\SBSPortal_staging

the app is physically running from "C:\inetpub\SBSPortal_staging", so the first solution is definitely not appropriate for web apps.


I use this if the exe is supposed to be called by double clicking it

var thisPath = System.IO.Directory.GetCurrentDirectory();

You can use the following code to get the current application directory.

AppDomain.CurrentDomain.BaseDirectory

Examples related to c#

How can I convert this one line of ActionScript to C#? Microsoft Advertising SDK doesn't deliverer ads How to use a global array in C#? How to correctly write async method? C# - insert values from file into two arrays Uploading into folder in FTP? Are these methods thread safe? dotnet ef not found in .NET Core 3 HTTP Error 500.30 - ANCM In-Process Start Failure Best way to "push" into C# array

Examples related to .net

You must add a reference to assembly 'netstandard, Version=2.0.0.0 How to use Bootstrap 4 in ASP.NET Core No authenticationScheme was specified, and there was no DefaultChallengeScheme found with default authentification and custom authorization .net Core 2.0 - Package was restored using .NetFramework 4.6.1 instead of target framework .netCore 2.0. The package may not be fully compatible Update .NET web service to use TLS 1.2 EF Core add-migration Build Failed What is the difference between .NET Core and .NET Standard Class Library project types? Visual Studio 2017 - Could not load file or assembly 'System.Runtime, Version=4.1.0.0' or one of its dependencies Nuget connection attempt failed "Unable to load the service index for source" Token based authentication in Web API without any user interface

Examples related to console

Error in MySQL when setting default value for DATE or DATETIME Where can I read the Console output in Visual Studio 2015 Chrome - ERR_CACHE_MISS Swift: print() vs println() vs NSLog() Datatables: Cannot read property 'mData' of undefined How do I write to the console from a Laravel Controller? Cannot read property 'push' of undefined when combining arrays Very simple log4j2 XML configuration file using Console and File appender Console.log not working at all Chrome: console.log, console.debug are not working

Examples related to console-application

How to run .NET Core console app from the command line ASP.NET Core configuration for .NET Core console application How to keep console window open How to navigate a few folders up? How to stop C# console applications from closing automatically? Could not load file or assembly ... An attempt was made to load a program with an incorrect format (System.BadImageFormatException) Can I write into the console in a unit test? If yes, why doesn't the console window open? What is the command to exit a Console application in C#? Can't specify the 'async' modifier on the 'Main' method of a console app Why is the console window closing immediately once displayed my output?