提问



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


基本上我的单元测试需要读取一些相对于dll的xml测试文件。无论测试dll是从TestDriven.NET,MbUnit GUI还是其他东西运行,我都希望路径始终正确解析。


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


我的测试库位于说



  C:\\项目\\ MyApplication的\\ daotests \\ BIN \\调试\\ daotests.dll



我想得到这条道路:



  C:\\项目\\ MyApplication的\\ daotests \\ BIN \\调试\\



当我从MbUnit Gui运行时,到目前为止,这三个建议都让我失望:



  • Environment.CurrentDirectory
    给出 c:\\ Program Files \\ MbUnit

  • System.Reflection.Assembly.GetAssembly(typeof(DaoTests)).Location
    给出 C:\\ Documents and
    设置\\乔治\\本地
    Settings \\ Temp \\ .... \\ DaoTests.dll

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


最佳参考


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


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);
    }
}


Assembly.Location属性有时会在使用NUnit(其中程序集从临时文件夹运行)时给你一些有趣的结果,所以我更喜欢使用CodeBase来提供URI格式的路径,然后UriBuild.UnescapeDataString]]删除开头的File://GetDirectoryName将其更改为正常的Windows格式。

其它参考1


这有帮助吗?


//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 );

其它参考2


这很简单:


var dir = AppDomain.CurrentDomain.BaseDirectory;

其它参考3


与John的答案相同,但是一种稍微冗长的扩展方法。


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


现在你可以这样做:


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


或者如果您愿意:


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

其它参考4


使用CodeBase和UNC Network共享时唯一有效的解决方案是:


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


它也适用于普通的URI。

其它参考5


这应该有效,除非程序集是阴影复制:


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

其它参考6


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


当然,对于每个测试跑步者来说,这种切换可能是不同的。


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

其它参考7


那这个呢:


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

其它参考8


AppDomain.CurrentDomain.BaseDirectory


适用于MbUnit GUI。

其它参考9


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

其它参考10


这是John Sibly代码的VB.NET端口.Visual Basic不区分大小写,因此他的几个变量名称与类型名称冲突。


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

其它参考11


我一直在使用Assembly.CodeBase而不是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("/", "\\");


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


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


您可能想要使用CodeBase而不是Location。

其它参考12


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


这不能在RELEASE模式下工作,也不能在启用优化的情况下工作,也不能在与编译它的机器不同的机器上工作。


但是,这将为您提供相对于您从调用它的源代码文件的位置的路径


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;
    }
}

其它参考13


您存在的当前目录。


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


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


要么


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

// The location of the Assembly
assembly.Location;

其它参考14


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


对基于磁盘(而不是基于Web)的非GACed程序集执行此操作的正确方法是使用当前正在执行的程序集CodeBase属性。[50]


这将返回一个URL(file://)。不要乱用字符串操作或UnescapeDataString,而是可以通过利用UriLocalPath属性来最小化地转换。


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

其它参考15


这个怎么样 ...


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


然后只是砍掉你不需要的东西

其它参考16


您可以通过获取bin路径
    AppDomain.CurrentDomain.RelativeSearchPath

其它参考17


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


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


我已经写了一篇关于如何在II中使用dll的完整描述 - http://nodogmablog.bryanhogan.net/2016/09/locating-and-checking-an-executing-dll-on-a-running-web -server/[53]

其它参考18


在Windows窗体应用程序中,您可以简单地使用Application.StartupPath


但对于DLL和控制台应用程序,代码更难记住......


string slash = Path.DirectorySeparatorChar.ToString();
string root = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);

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

其它参考19


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

其它参考20


这就是我提出的。 在Web项目之间,单元测试(nunit和resharper测试运行器);我发现这对我有用。


我一直在寻找代码来检测构建的配置,Debug/Release/CustomName。唉,#if DEBUG。 所以,如果有人可以改进!


随意编辑和改进。


获取应用文件夹。对于web根,unittests有用,可以获取测试文件的文件夹。


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文件夹:用于使用反射执行程序集。如果由于构建属性而在那里复制文件。


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;
    }
}

其它参考21


这应该工作:


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)。

其它参考22


我发现我的解决方案足以检索位置。


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

其它参考23


我在过去的NUnit中也有同样的行为。默认情况下NUnit将程序集复制到临时目录中。您可以在NUnit设置中更改此行为:


[54]


也许TestDriven.NETMbUnit GUI具有相同的设置。

其它参考24


我使用它来获取Bin目录的路径:


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


你得到这个结果:



  c:\\ users \\ ricooley \\ documents \\ visual studio
  2010 \\项目\\ Windows_Test_Project \\ Windows_Test_Project \\ BIN


其它参考25


Web应用程序?


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