关于C#:如何获取代码所在程序集的路径?

How do I get the path of the assembly the code is in?

是否有方法获取当前代码所在的程序集的路径?我不需要调用程序集的路径,只需要包含代码的路径。

基本上,我的单元测试需要读取一些相对于DLL的XML测试文件。无论测试dll是从testsdriven.net、mbunit gui还是其他什么地方运行,我都希望路径始终正确解析。

编辑:人们似乎误解了我的要求。

我的测试库位于Say

C:\projects\myapplication\daotests\bin\Debug\daotests.dll

我想知道这条路:

C:\projects\myapplication\daotests\bin\Debug\

到目前为止,当我从MBUnit GUI运行时,这三个建议使我失败:

  • Environment.CurrentDirectory提供C:Program FilesmbUnit

  • System.Reflection.Assembly.GetAssembly(typeof(DaoTests)).Location提供C:文档和设置乔治本地设置 emp……daotests.dll

  • System.Reflection.Assembly.GetExecutingAssembly().Location与上一个相同。


我已经定义了以下属性,因为我们经常在单元测试中使用它。

1
2
3
4
5
6
7
8
9
10
public static string AssemblyDirectory
{
    get
    {
        string codeBase = Assembly.GetExecutingAssembly().CodeBase;
        UriBuilder uri = new UriBuilder(codeBase);
        string path = Uri.UnescapeDataString(uri.Path);
        return Path.GetDirectoryName(path);
    }
}

当使用nunit(程序集从临时文件夹运行)时,Assembly.Location属性有时会给您一些有趣的结果,因此我更喜欢使用CodeBase,它以uri格式为您提供路径,然后UriBuild.UnescapeDataString在开始时删除File://GetDirectoryName将其更改为正常的Windows格式。


这有帮助吗?

1
2
3
4
5
//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 );


就这么简单:

1
var dir = AppDomain.CurrentDomain.BaseDirectory;


和约翰的答案一样,只是稍微少了一点冗长的扩展方法。

1
2
3
4
5
public static string GetDirectoryPath(this Assembly assembly)
{
    string filePath = new Uri(assembly.CodeBase).LocalPath;
    return Path.GetDirectoryName(filePath);            
}

现在你可以做到:

1
var localDir = Assembly.GetExecutingAssembly().GetDirectoryPath();

或者如果你喜欢:

1
var localDir = typeof(DaoTests).Assembly.GetDirectoryPath();


在使用codebase和unc网络共享时,唯一对我有效的解决方案是:

1
System.IO.Path.GetDirectoryName(new System.Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath);

它也适用于正常的URI。


除非程序集被卷影复制,否则这应该可以工作:

1
string path = System.Reflection.Assembly.GetExecutingAssembly().Location

这个怎么样:

1
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);

我怀疑这里真正的问题是您的测试运行程序正在将您的程序集复制到其他位置。在运行时,无法确定程序集是从何处复制的,但您可能可以翻转开关,告诉测试运行程序从何处运行程序集,而不是将其复制到影子目录。

当然,对于每个测试运行者,这样的开关可能是不同的。

是否考虑将XML数据作为资源嵌入到测试程序集中?


1
AppDomain.CurrentDomain.BaseDirectory

使用MBUnit GUI。


这是John Sibly代码的vb.net端口。VisualBasic不区分大小写,因此他的几个变量名与类型名冲突。

1
2
3
4
5
6
7
8
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


1
2
3
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
var assemblyPath = assembly.GetFiles()[0].Name;
var assemblyDir = System.IO.Path.GetDirectoryName(assemblyPath);

这个怎么样…

1
string ThisdllDirectory = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);

那就砍下你不需要的东西吧


我一直在使用assembly.codebase而不是location:

1
2
3
4
5
6
7
8
9
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("/","\");

它一直在工作,但我不再确定它是100%正确的。http://blogs.msdn.com/suzbook/archive/2003/06/26/assembly-codebase-vs-assembly-location.aspx上的页面显示:

"代码库是找到文件的位置的URL,而位置是实际加载文件的路径。例如,如果程序集是从Internet下载的,则其代码基可能以"http://"开头,但其位置可能以"c:"开头。如果文件是卷影复制的,则位置将是卷影复制目录中文件副本的路径。也很好地知道,不能保证为GAC中的程序集设置代码基。但是,将始终为从磁盘加载的程序集设置位置。"

您可能希望使用代码库而不是位置。


据我所知,大多数其他答案都有一些问题。

对于基于磁盘(而不是基于Web)的非gaced程序集,正确的方法是使用当前执行的程序集的CodeBase属性。

这将返回一个URL(File://)。这可以通过利用UriLocalPath属性,在不干扰字符串操作或UnescapeDataString的情况下进行转换。

1
2
3
var codeBaseUrl = Assembly.GetExecutingAssembly().CodeBase;
var filePathToCodeBase = new Uri(codeBaseUrl).LocalPath;
var directoryPath = Path.GetDirectoryName(filePathToCodeBase);


这些年来,没有人真的提到过这个。我从很棒的ApprovalTests项目中学到了一个技巧。技巧是使用程序集中的调试信息查找原始目录。

这不会在发布模式下工作,也不会在启用优化的情况下工作,也不会在与编译时不同的计算机上工作。

但这将为您提供与调用源代码文件的位置相关的路径。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public static class PathUtilities
{
    public static string GetAdjacentFile(string relativePath)
    {
        return GetDirectoryForCaller(1) + relativePath;
    }
    public static string GetDirectoryForCaller()
    {
        return GetDirectoryForCaller(1);
    }


    public static string GetDirectoryForCaller(int callerStackDepth)
    {
        var stackFrame = new StackTrace(true).GetFrame(callerStackDepth + 1);
        return GetDirectoryForStackFrame(stackFrame);
    }

    public static string GetDirectoryForStackFrame(StackFrame stackFrame)
    {
        return new FileInfo(stackFrame.GetFileName()).Directory.FullName + Path.DirectorySeparatorChar;
    }
}

当前存在的目录。

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

如果用build复制.xml文件,应该找到它。

1
2
3
4
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetAssembly(typeof(SomeObject));

// The location of the Assembly
assembly.Location;


当开发人员可以更改代码以包含所需的代码段时,所有建议的答案都有效,但是如果您想在不更改任何代码的情况下执行此操作,则可以使用Process Explorer。

它将列出系统上所有正在执行的DLL,您可能需要确定正在运行的应用程序的进程ID,但这通常并不太困难。

我已经写了一个完整的描述如何在II中为一个dll做这个-http://nodogmablog.bryanhogan.net/2016/09/locating-and-checking-an-executing-dll-on-a-running-web-server/


在Windows窗体应用程序中,您只需使用Application.StartupPath

但是对于DLL和控制台应用程序来说,代码更难记住…

1
2
3
4
5
string slash = Path.DirectorySeparatorChar.ToString();
string root = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);

root += slash;
string settingsIni = root +"settings.ini"

你可以通过AppDomain.CurrentDomain.RelativesearchPath


如果路径包含""符号,则会得到不正确的目录。所以我使用了对john sibly答案的修改,它是uribuilder.path和uribuilder.fragment的组合:

1
2
3
4
5
6
7
8
9
10
11
12
public static string AssemblyDirectory
{
    get
    {
        string codeBase = Assembly.GetExecutingAssembly().CodeBase;
        UriBuilder uri = new UriBuilder(codeBase);
        //modification of the John Sibly answer    
        string path = Uri.UnescapeDataString(uri.Path.Replace("/","\") +
          uri.Fragment.Replace("
/","\"));
        return Path.GetDirectoryName(path);
     }
}

1
string path = Path.GetDirectoryName(typeof(DaoTests).Module.FullyQualifiedName);

我以前在江户有过同样的行为。默认情况下,NUnit会将程序集复制到temp目录中。您可以在NUnit设置中更改此行为:

enter image description here

可能TestDriven.NETMbUnitGUI具有相同的设置。


我发现我的解决方案足以找到那个地点。

1
var executingAssembly = new FileInfo((Assembly.GetExecutingAssembly().Location)).Directory.FullName;


这应该有效:

1
2
3
4
5
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
Assembly asm = Assembly.GetCallingAssembly();
String path = Path.GetDirectoryName(new Uri(asm.EscapedCodeBase).LocalPath);

string strLog4NetConfigPath = System.IO.Path.Combine(path,"log4net.config");

我正使用它来部署DLL文件库以及一些配置文件(这是从DLL文件中使用log4net)。


这就是我想到的。在Web项目之间,单元测试(nunit和resharper测试运行程序);我发现这对我很有用。

我一直在寻找代码来检测构建的配置,Debug/Release/CustomName。唉,江户记1〔6〕。所以如果有人能改进的话!

随时编辑和改进。

正在获取应用文件夹。对于Web根目录有用,UnitTests用于获取测试文件的文件夹。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public static string AppPath
{
    get
    {
        DirectoryInfo appPath = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory);

        while (appPath.FullName.Contains(@"\bin", StringComparison.CurrentCultureIgnoreCase)
                || appPath.FullName.EndsWith(@"\bin", StringComparison.CurrentCultureIgnoreCase))
        {
            appPath = appPath.Parent;
        }
        return appPath.FullName;
    }
}

获取bin文件夹:用于使用反射执行程序集。如果由于生成属性而将文件复制到那里。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public static string BinPath
{
    get
    {
        string binPath = AppDomain.CurrentDomain.BaseDirectory;

        if (!binPath.Contains(@"\bin", StringComparison.CurrentCultureIgnoreCase)
            && !binPath.EndsWith(@"\bin", StringComparison.CurrentCultureIgnoreCase))
        {
            binPath = Path.Combine(binPath,"bin");
            //-- Please improve this if there is a better way
            //-- Also note that apps like webapps do not have a debug or release folder. So we would just return bin.
#if DEBUG
            if (Directory.Exists(Path.Combine(binPath,"Debug")))
                        binPath = Path.Combine(binPath,"Debug");
#else
            if (Directory.Exists(Path.Combine(binPath,"Release")))
                        binPath = Path.Combine(binPath,"Release");
#endif
        }
            return binPath;
    }
}

我使用这个来获取bin目录的路径:

1
2
var i = Environment.CurrentDirectory.LastIndexOf(@"");
var path = Environment.CurrentDirectory.Substring(0,i);

你得到这个结果:

"c:\users
icooley\documents\visual studio
2010\Projects\Windows_Test_Project\Windows_Test_Project\bin"


Web应用程序?

1
Server.MapPath("~/MyDir/MyFile.ext")