题
有没有办法获取当前代码所在的程序集的路径?我不需要调用程序集的路径,只需要包含代码的路径。
基本上我的单元测试需要读取一些相对于 dll 定位的 xml 测试文件。我希望路径始终能够正确解析,无论测试 dll 是从 TestDriven.NET、MbUnit GUI 还是其他东西运行。
编辑: :人们似乎误解了我的要求。
我的测试库位于比如说
C:\projects\myapplication\daotests\bin\Debug\daotests.dll
我想得到这条路径:
C:\projects\myapplication\daotests\bin\Debug\
当我从 MbUnit Gui 运行时,到目前为止,这三个建议让我失败了:
Environment.CurrentDirectory
给出 c:\Program Files\MbUnitSystem.Reflection.Assembly.GetAssembly(typeof(DaoTests)).Location
给出 C:文档和设置 George local设置 temp .... daotests.dllSystem.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 格式。
其他提示
这有帮助吗?
//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 );
就这么简单:
var dir = AppDomain.CurrentDomain.BaseDirectory;
与约翰的答案相同,但扩展方法稍微简洁一些。
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();
使用 CodeBase 和 UNC 网络共享时唯一对我有用的解决方案是:
System.IO.Path.GetDirectoryName(new System.Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath);
它也适用于普通的 URI。
这应该可以工作,除非程序集是 影子复制:
string path = System.Reflection.Assembly.GetExecutingAssembly().Location
那这个呢:
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
我怀疑这里真正的问题是您的测试运行程序正在将程序集复制到不同的位置。在运行时无法判断程序集是从哪里复制的,但您可以翻转一个开关来告诉测试运行程序从其所在位置运行程序集,而不是将其复制到影子目录。
当然,每个测试运行者的这种切换可能会有所不同。
您是否考虑过将 XML 数据作为资源嵌入到测试程序集中?
AppDomain.CurrentDomain.BaseDirectory
与 MbUnit GUI 一起使用。
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
var assemblyPath = assembly.GetFiles()[0].Name;
var assemblyDir = System.IO.Path.GetDirectoryName(assemblyPath);
这是 John Sible 代码的 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
这个怎么样 ...
string ThisdllDirectory = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
然后砍掉你不需要的东西
您所在的当前目录。
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;
我一直在使用 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 说:
“CodeBase 是找到文件的位置的 URL,而 Location 是实际加载文件的路径。例如,如果程序集是从 Internet 下载的,则其 CodeBase 可能以“http://”开头,但其位置可能以“C:\”开头。如果文件是卷影复制的,则位置将是卷影复制目录中文件副本的路径。还需要知道的是,不能保证为 GAC 中的程序集设置 CodeBase。但是,始终会为从磁盘加载的程序集设置位置。"
你 可能 想要使用 CodeBase 而不是 Location。
据我所知,大多数其他答案都存在一些问题。
执行此操作的正确方法是 基于磁盘(与基于 Web 相对)、非 GAC 组装 是使用当前正在执行的程序集 CodeBase
财产。
这将返回一个 URL (file://
)。而不是乱搞 字符串操作 或者 UnescapeDataString
, ,这可以通过利用 LocalPath
的财产 Uri
.
var codeBaseUrl = Assembly.GetExecutingAssembly().CodeBase;
var filePathToCodeBase = new Uri(codeBaseUrl).LocalPath;
var directoryPath = Path.GetDirectoryName(filePathToCodeBase);
这么多年来,还没有人真正提起过这个。我从很棒的人那里学到的一个技巧 批准测试项目. 。诀窍是您使用程序集中的调试信息来查找原始目录。
这在 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;
}
}
您可以通过appdomain.currentdomain.relationsearchpath获取bin路径
当开发人员可以更改代码以包含所需的代码片段时,所有建议的答案都有效,但如果您想在不更改任何代码的情况下执行此操作,则可以使用 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 和控制台应用程序来说,代码更难记住......
string slash = Path.DirectorySeparatorChar.ToString();
string root = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
root += slash;
string settingsIni = root + "settings.ini"
string path = Path.GetDirectoryName(typeof(DaoTests).Module.FullyQualifiedName);
如果路径包含“#”符号,您将得到不正确的目录。因此,我使用 John Sible 答案的修改版,即 UriBuilder.Path 和 UriBuilder.Fragment 的组合:
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);
}
}
这就是我想出来的。 在 Web 项目之间,进行单元测试(nunit 和 resharper 测试运行程序);我发现这对我有用。
我一直在寻找代码来检测构建的配置, Debug/Release/CustomName
. 。唉, #if DEBUG
. 所以如果有人可以改进这一点!
请随意编辑和改进。
获取应用程序文件夹. 。对于网络根目录、单元测试以获取测试文件的文件夹很有用。
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;
}
}
这应该有效:
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)。
我发现我的解决方案足以检索位置。
var executingAssembly = new FileInfo((Assembly.GetExecutingAssembly().Location)).Directory.FullName;
我用它来获取 Bin 目录的路径:
var i = Environment.CurrentDirectory.LastIndexOf(@"\");
var path = Environment.CurrentDirectory.Substring(0,i);
你得到这个结果:
“ C: Users Ricooley Documents Visual Studio 2010 Projects Windows_test_project Windows_test_project bin”
Web应用程序?
Server.MapPath("~/MyDir/MyFile.ext")