programming
filename
executable
coding
duplicate

How do I find the current executable filename?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Finding the current executable filename sounds simple, but the right API depends on what you actually need. In .NET and similar runtimes, there is an important difference between the process path, the entry assembly, and the currently executing assembly. If you pick the wrong one, the code may work in development and fail in tests, single-file deployments, or plugin scenarios.

Decide What “Current Executable” Means

There are three common interpretations:

  • the path of the running process executable
  • the assembly that started the application
  • the assembly containing the code currently executing

Those are often the same in a simple console app, but they diverge in libraries, unit tests, hosted applications, and plugin systems.

For a plain application, the process path is usually what people want.

Use Environment.ProcessPath on Modern .NET

In modern .NET, the clearest API is Environment.ProcessPath.

csharp
1using System;
2using System.IO;
3
4class Program
5{
6    static void Main()
7    {
8        string? fullPath = Environment.ProcessPath;
9        string? fileName = fullPath == null ? null : Path.GetFileName(fullPath);
10
11        Console.WriteLine(fullPath);
12        Console.WriteLine(fileName);
13    }
14}

This returns the actual process executable path. If all you need is the filename such as myapp.exe, wrap it with Path.GetFileName.

This is usually the best answer for .NET 6 and later because it states the intent directly and avoids assembly-related ambiguity.

Use Process.GetCurrentProcess() on Older Runtimes

If you are on .NET Framework or an older .NET runtime, Process.GetCurrentProcess().MainModule.FileName is a common fallback.

csharp
1using System;
2using System.Diagnostics;
3using System.IO;
4
5class Program
6{
7    static void Main()
8    {
9        using Process process = Process.GetCurrentProcess();
10        string fullPath = process.MainModule!.FileName;
11        string fileName = Path.GetFileName(fullPath);
12
13        Console.WriteLine(fullPath);
14        Console.WriteLine(fileName);
15    }
16}

This works well on Windows desktop applications. It is less elegant than Environment.ProcessPath, but it is widely understood and commonly used in older codebases.

Know When Assembly APIs Mean Something Else

Developers often reach for Assembly.GetExecutingAssembly() or Assembly.GetEntryAssembly(). Those APIs are useful, but they answer different questions.

csharp
1using System;
2using System.Reflection;
3
4class Program
5{
6    static void Main()
7    {
8        Console.WriteLine(Assembly.GetExecutingAssembly().Location);
9        Console.WriteLine(Assembly.GetEntryAssembly()?.Location);
10    }
11}

GetExecutingAssembly() returns the assembly that contains the currently running code. If this code is inside a shared library, that may be the DLL, not the application executable.

GetEntryAssembly() usually points to the application entry assembly, which is often closer to what you want in a normal app, but it can be null in some hosting scenarios.

That is why assembly APIs are fine when you specifically care about assemblies, but not ideal when the real question is “what executable is the process running?”

Getting Only the Filename

If the full path is more detail than you need, trim it cleanly:

csharp
1using System;
2using System.IO;
3
4class Program
5{
6    static void Main()
7    {
8        string? exePath = Environment.ProcessPath;
9        string? exeName = exePath == null ? null : Path.GetFileNameWithoutExtension(exePath);
10
11        Console.WriteLine(exeName);
12    }
13}

Use Path.GetFileName if you want myapp.exe, and Path.GetFileNameWithoutExtension if you want only myapp.

Pick the API for the Job

A good rule is:

  • use Environment.ProcessPath for the current process executable
  • use Assembly.GetEntryAssembly() when you explicitly care about the entry assembly
  • use Assembly.GetExecutingAssembly() when you need the assembly containing the current code

That distinction matters in tools, service hosts, test runners, and any application that loads plugins dynamically.

Common Pitfalls

A common mistake is using GetExecutingAssembly() in a helper library and assuming it points to the main application executable. In library code, it often points to the library DLL instead.

Another issue is assuming GetEntryAssembly() is always non-null. Some hosted or reflective execution contexts do not provide an entry assembly the way a normal console app does.

Developers also sometimes parse paths manually with string operations. That is fragile. Use Path.GetFileName and related APIs so path separators and extensions are handled correctly.

Finally, do not confuse the current working directory with the executable path. They can be completely different.

Summary

  • The best modern API for the current executable path is Environment.ProcessPath.
  • On older runtimes, Process.GetCurrentProcess().MainModule.FileName is a practical fallback.
  • 'GetExecutingAssembly() and GetEntryAssembly() answer assembly questions, not always process-path questions.'
  • Use Path.GetFileName or Path.GetFileNameWithoutExtension to extract the filename safely.
  • Be explicit about whether you need the running process, the entry assembly, or the currently executing library.

Course illustration
Course illustration

All Rights Reserved.