Question
In C#, how can I get the path of the assembly that contains the currently executing code, rather than the calling assembly?
I need this because a unit test library must load XML test files stored relative to the test DLL. The path should resolve correctly no matter how the tests are run, such as from TestDriven.NET, MbUnit GUI, or other runners.
For example, if the test library is located at:
C:\projects\myapplication\daotests\bin\Debug\daotests.dll
I want to get this directory path:
C:\projects\myapplication\daotests\bin\Debug\
Some approaches do not work reliably in this scenario:
Environment.CurrentDirectory
This may return the host application's working directory, such as:
C:\Program Files\MbUnit
System.Reflection.Assembly.GetAssembly(typeof(DaoTests)).Location
System.Reflection.Assembly.GetExecutingAssembly().Location
Under some test runners, these may return a shadow-copied path such as a temporary folder instead of the original build output directory.
Short Answer
By the end of this page, you will understand how assembly paths work in C#, why unit test runners can make them confusing, and how to choose the right API for finding either the executing assembly, its directory, or the application base directory.
Concept
In C#, there are several different "paths" you might mean when you ask for the assembly path:
- Current working directory: where the process is currently running from
- Assembly file location: the path to the loaded DLL or EXE
- Assembly code base: the original path the assembly was loaded from
- Application base directory: the base folder the runtime uses to resolve assemblies
These are not always the same.
This matters especially in unit tests, because test runners often do one or more of these things:
- launch your tests from their own installation folder
- change the current working directory
- shadow copy your test assembly into a temporary folder before loading it
That means code like Environment.CurrentDirectory or even Assembly.Location may not point to your original project output folder.
A commonly useful distinction is:
- Use
Assembly.Locationwhen you want the actual file path of the loaded assembly. - Use
AppDomain.CurrentDomain.BaseDirectorywhen you want the runtime's base folder for loading files. - Use
Assembly.CodeBaseorAssembly.GetName().CodeBaseonly when you specifically need the original source URI, keeping in mind it is a URI, not a normal file path.
For many test scenarios, the safest choice is not "the assembly that originally lived in bin\Debug" but rather . In modern code, that usually means copying test files to the output directory and reading them from or .
Mental Model
Think of your code as an actor performing on a stage.
There are several locations you could ask about:
- Where the theater building is → the host process folder
- Where the actor is standing right now → current working directory
- Which dressing room the actor was loaded from → assembly location
- Which theater the show uses as home base → app domain base directory
- Where the actor originally came from before being moved backstage → code base
A test runner may move your assembly to a temporary backstage area before running it. So if you ask, "Where is the DLL?" you may get the temporary shadow-copy folder, not your original bin\Debug folder.
That is why the right answer depends on what you actually need:
- original source location
- runtime location
- runtime base folder for test files
Syntax and Examples
The most common APIs are:
using System;
using System.IO;
using System.Reflection;
1. Get the loaded assembly's file path
string assemblyPath = Assembly.GetExecutingAssembly().Location;
string assemblyDirectory = Path.GetDirectoryName(assemblyPath);
This gives the path of the assembly containing the currently executing code.
2. Get the directory of a specific type's assembly
string assemblyPath = typeof(DaoTests).Assembly.Location;
string assemblyDirectory = Path.GetDirectoryName(assemblyPath);
This is often clearer than GetExecutingAssembly() because it explicitly refers to the assembly containing DaoTests.
3. Get the application base directory
string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
This is often the best choice for loading runtime files in tests or apps.
4. Get the original code base URI
string codeBase = (DaoTests).Assembly.CodeBase;
Uri uri = Uri(codeBase);
originalPath = uri.LocalPath;
originalDirectory = Path.GetDirectoryName(originalPath);
Step by Step Execution
Consider this code:
using System;
using System.IO;
using System.Reflection;
class Program
{
static void Main()
{
string location = typeof(Program).Assembly.Location;
string folder = Path.GetDirectoryName(location);
Console.WriteLine(location);
Console.WriteLine(folder);
}
}
Step by step
typeof(Program)gets metadata for theProgramclass..Assemblygets the assembly that contains that class..Locationreturns the full file path of the loaded assembly.- Example:
C:\projects\MyApp\bin\Debug\MyApp.dll
Path.GetDirectoryName(location)removes the file name.- Result:
C:\projects\MyApp\bin\Debug
Console.WriteLineprints both values.
What changes under a test runner?
If the runner shadow copies your DLL, step 3 may instead return something like:
Real World Use Cases
This concept appears in many everyday situations:
Loading configuration or data files
A desktop app may read a JSON or XML file stored next to the executable.
string configPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "appsettings.json");
Unit tests using sample files
Tests often need fixture files such as:
- XML payloads
- JSON samples
- CSV imports
- image files
Instead of relying on the project source folder, developers usually copy these files into the output directory and load them from the base directory.
Plugins and extensions
A plugin may need to locate files stored relative to its own DLL.
string pluginDir = Path.GetDirectoryName(typeof(MyPlugin).Assembly.Location);
Logging and exports
An application may write logs or generated files relative to its runtime folder.
Scripts and tools
Command-line tools often use the executable directory as a stable reference point for bundled resources.
Real Codebase Usage
In real projects, developers usually avoid hard-coding assumptions about bin\Debug paths.
Common patterns include:
1. Use the base directory for runtime resources
string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TestData", "input.xml");
This works well when files are copied to output during build.
2. Use typeof(SomeType).Assembly for clarity
string assemblyDir = Path.GetDirectoryName(typeof(DaoTests).Assembly.Location);
This is easier to understand than GetExecutingAssembly() when helper methods live in shared libraries.
3. Guard against nulls
string assemblyPath = typeof(DaoTests).Assembly.Location;
string assemblyDir = Path.GetDirectoryName(assemblyPath) ?? string.Empty;
4. Prefer deployment-friendly test assets
Instead of reading files from the original source tree, teams often:
- mark files as Content
- set Copy to Output Directory
- load them from the base directory
Common Mistakes
Mistake 1: Using Environment.CurrentDirectory as if it were the assembly folder
string path = Environment.CurrentDirectory;
This returns the process working directory, which may belong to the test runner, not your DLL.
How to avoid it:
- Use
AppDomain.CurrentDomain.BaseDirectoryfor runtime files. - Use
typeof(MyType).Assembly.Locationif you truly need the loaded assembly path.
Mistake 2: Assuming Location always points to the original bin\Debug folder
string path = typeof(DaoTests).Assembly.Location;
Under shadow copying, this may point to a temp directory.
How to avoid it:
- Decide whether you need the loaded location or original source location.
- If you need the original source URI, inspect
CodeBaseand convert it.
Mistake 3: Using CodeBase like a normal file path
Broken example:
path = (DaoTests).Assembly.CodeBase;
xmlPath = Path.Combine(path, );
Comparisons
| Approach | What it returns | Good for | Common problem |
|---|---|---|---|
Environment.CurrentDirectory | Process working directory | Command-line tools that control working dir | Often points to the host app folder |
Assembly.GetExecutingAssembly().Location | Loaded path of the currently executing assembly | Finding the actual DLL in memory | May be a shadow-copy temp path |
typeof(MyType).Assembly.Location | Loaded path of the assembly containing a specific type | Clear, explicit assembly lookup | Still affected by shadow copying |
AppDomain.CurrentDomain.BaseDirectory | Runtime base folder | Loading resource files at runtime | Not necessarily the original assembly source folder |
Cheat Sheet
// Loaded path of a specific assembly
string assemblyPath = typeof(MyType).Assembly.Location;
// Directory containing that assembly
string assemblyDir = Path.GetDirectoryName(assemblyPath);
// Runtime base directory
string baseDir = AppDomain.CurrentDomain.BaseDirectory;
// Original source path (URI -> local path)
string codeBase = typeof(MyType).Assembly.CodeBase;
string originalPath = new Uri(codeBase).LocalPath;
string originalDir = Path.GetDirectoryName(originalPath);
Rules of thumb
Environment.CurrentDirectoryis not the same as assembly directory.Locationgives the path of the loaded assembly.CodeBasemay preserve the original source location, but it is a URI.- Test runners may shadow copy assemblies to temp folders.
- For test data, prefer:
- copy files to output
- load them from
AppDomain.CurrentDomain.BaseDirectory
Best practical choice for tests
string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, , );
FAQ
How do I get the directory of the current assembly in C#?
Use:
string dir = Path.GetDirectoryName(typeof(MyType).Assembly.Location);
This gets the directory of the assembly containing MyType.
Why does Environment.CurrentDirectory return the wrong folder in tests?
Because it returns the process working directory, which may be the test runner's folder rather than your test DLL folder.
Why does Assembly.Location point to a temp folder?
Some test runners shadow copy assemblies before executing them. In that case, the loaded assembly really is in a temporary folder.
How can I get the original assembly path instead of the shadow-copy path?
Try Assembly.CodeBase and convert it from a URI to a local path:
string path = new Uri(typeof(MyType).Assembly.CodeBase).LocalPath;
What is the best way to load test files in unit tests?
Usually, copy the files to the output directory and load them with AppDomain.CurrentDomain.BaseDirectory.
Should I use GetExecutingAssembly() or ?
Mini Project
Description
Build a small test-data locator utility for a .NET test project. The utility should show the difference between the assembly location, the application base directory, and the original code base, then load an XML file from a TestData folder. This demonstrates which path APIs are stable and which can change under different runners.
Goal
Create a helper that reliably loads a test XML file from the runtime output directory and prints useful path diagnostics.
Requirements
- Create a helper method that returns the application base directory.
- Create a helper method that returns the loaded assembly directory for a known type.
- Create a helper method that converts
CodeBaseto a local file path. - Build a full path to
TestData/sample.xml. - Read the XML file if it exists and print its contents.
Keep learning
Related questions
AddTransient vs AddScoped vs AddSingleton in ASP.NET Core Dependency Injection
Learn the differences between AddTransient, AddScoped, and AddSingleton in ASP.NET Core DI with examples and practical usage.
Best Way to Repeat a Character in C#: Building Repeated Strings Efficiently
Learn the best way to repeat a character in C#, compare StringBuilder, string concatenation, and simpler built-in options.
C# Array Initialization Syntaxes Explained
Learn all common C# array initialization syntaxes with examples, rules, comparisons, and mistakes beginners often make.