views:

26024

answers:

13

Is there a way to get the path for the assembly in which the current code resides? I do not want the path of the calling assembly, just the one containing the code.

Basically my unit test needs to read some xml test files which are located relative to the dll. I want the path to always resolve correctly regardless of whether the testing dll is run from TestDriven.NET, the MbUnit GUI or something else.

Edit: People seem to be misunderstanding what I'm asking.

My test library is located in say c:\projects\myapplication\daotests\bin\Debug\daotests.dll and I would like to get the "*c:\projects\myapplication\daotests\bin\Debug*" path.

The three suggestions so far fail me when I run from the MbUnit Gui:

  • Console.Out.Write(Environment.CurrentDirectory) gives c:\Program Files\MbUnit

  • Console.Out.Write(System.Reflection.Assembly.GetAssembly(typeof(DaoTests)).Location) gives C:\Documents and Settings\george\Local Settings\Temp\ ....\DaoTests.dll

  • Console.Out.Write(System.Reflection.Assembly.GetExecutingAssembly().Location) gives the same as the previous

+8  A: 

This should work:

string path = System.Reflection.Assembly.GetExecutingAssembly().Location
jodonnell
A: 

The current directory where you exist.

Environment.CurrentDirectory;  // This is the current directory of your application

If you copy the .xml file out with build you should find it.

or

System.Reflection.Assembly assembly = System.Reflection.Assembly.GetAssembly(typeof(SomeObject));

// The location of the Assembly
assembly.Location;
David Basarab
+13  A: 

Does this help?

//get the full location of the assembly with DaoTests in it
string fullPath = System.Reflection.Assembly.GetAssembly(typeof(DaoTests)).Location;

//get the folder that's in
string theDirectory = Path.GetDirectoryName( fullPath );
Keith
see my edit, it does not, is this something strange about how MbUnit does things?
George Mauer
How come?fullPath would be "C:\projects\myapplication\daotests\bin\Debug\daotests.dll"theDirectory would be "C:\projects\myapplication\daotests\bin\Debug"Isn't that what you want?
Keith
Ahh, no I get you. MSTest does the same thing - everything is copied to a new temp directory every time.
Keith
Set the xml files to be content, copied with the dll, or resources, read from the dll.
Keith
A: 
assembly.GetFiles()[0].Name
Mark Cidade
+2  A: 

I suspect that the real issue here is that your test runner is copying your assembly to a different location. There's no way at runtime to tell where the assembly was copied from, but you can probably flip a switch to tell the test runner to run the assembly from where it is and not to copy it to a shadow directory.

Such a switch is likely to be different for each test runner, of course.

Have you considered embedding your XML data as resources inside your test assembly?

Curt Hagenlocher
+1  A: 

What about this:

System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
huseyint
A: 
string path = Path.GetDirectoryName(typeof(DaoTests).Module.FullyQualifiedName);
Jesse C. Slicer
+3  A: 

I've been using Assembly.CodeBase instead of Location:

Assembly a;
a = Assembly.GetAssembly(typeof(DaoTests));
string s = a.CodeBase.ToUpper(); // file:///c:/path/name.dll
Assert.AreEqual(true, s.StartsWith("FILE://"), "CodeBase is " + s);
s = s.Substring(7, s.LastIndexOf('/') - 7); // 7 = "file://"
while (s.StartsWith("/")) {
    s = s.Substring(1, s.Length - 1);
}
s = s.Replace("/", "\\");

It's been working, but I'm no longer sure it is 100% correct. The page at http://blogs.msdn.com/suzcook/archive/2003/06/26/assembly-codebase-vs-assembly-location.aspx says:

"The CodeBase is a URL to the place where the file was found, while the Location is the path where it was actually loaded. For example, if the assembly was downloaded from the internet, its CodeBase may start with "http://", but its Location may start with "C:\". If the file was shadow-copied, the Location would be the path to the copy of the file in the shadow copy dir. It’s also good to know that the CodeBase is not guaranteed to be set for assemblies in the GAC. Location will always be set for assemblies loaded from disk, however."

You may want to use CodeBase instead of Location.

dan gibson
+68  A: 

I've defined the following property as we use this often in unit testing.

static public string AssemblyDirectory
{
    get
    {
        string codeBase = Assembly.GetExecutingAssembly().CodeBase;
        UriBuilder uri = new UriBuilder(codeBase);
        string path = Uri.UnescapeDataString(uri.Path);
        return Path.GetDirectoryName(path);
    }
}

The Assembly.Location property sometimes gives you some funny results when using NUnit (where assemblies run from a temporary folder), so I prefer to use CodeBase which gives you the path in URI format, then UriBuild.UnescapeDataString removes the the File:// at the beginning, and GetDirectoryName changes it to the normal windows format.

John Sibly
Thank you for your code, saves me a lot of time
Funky81
This was it. The .Location property gave me some funky results as well. Thanks!
bdwakefield
+1 Nice one. Really helped out.
Luhmann
This has one issue I came across, if your directory name is:c:\My%20Directorythen the Uri.UnescapeDataString will return:c:\My DirectoryThis means that File.Exists("c:\My Directory\MyFile.txt") will return false as the correct path is actually "c:\My%20Directory\MyFile.txt"I came across this as our SVN paths have spaces in them and when we check them out it encodes the spaces.
row1
damn, that still doesnt work for me :0(Now instead of it giving me the MSBuild path, i get the path of TeamCity C:\TeamCity\buildAgent\temp\buildTmp\SYSTEM_SVR1 2010-08-24 17_34_23\Outbut yet another way to get a path :-)
schmoopy
@John Sibly: returns the path of the executing assembly - not the assembly (as in a .dll) that is being loaded by the calling executable. I need the .dll to be able to set a working directory. +1 though for a helpful answer and a good starting point.
dboarman
Saved my day :D
MoJo2600
+1  A: 

Here is a VB.Net port of John Sibly's code. VB is not case sensitive, so a couple of his variable names were colliding with Type names. Thanks for the code John!

Public Shared ReadOnly Property AssemblyDirectory() As String
    Get
        Dim codeBase As String = Assembly.GetExecutingAssembly().CodeBase
        Dim uriBuilder As New UriBuilder(codeBase)
        Dim assemblyPath As String = Uri.UnescapeDataString(uriBuilder.Path)
        Return Path.GetDirectoryName(assemblyPath)
    End Get
End Property
Mike Schall
+7  A: 

Same as John's answer, but a slightly less verbose extension method.

public static string GetCurrentExecutingDirectory(this Assembly assembly)
{
    string filePath = new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath;
    return Path.GetDirectoryName(filePath);            
}
Sneal
+2  A: 

As Simple as this

 var dir = AppDomain.CurrentDomain.BaseDirectory;
jalchr
+1  A: 

AppDomain.CurrentDomain.BaseDirectory works with MbUnit GUI.