Geo*_*uer 746 .net c# reflection
有没有办法获取当前代码所在的程序集的路径?我不想要调用程序集的路径,只需要包含代码的路径.
基本上我的单元测试需要读取一些相对于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\george\Local Settings\Temp\....\DaoTests.dll
System.Reflection.Assembly.GetExecutingAssembly().Location
与前一个相同.
Joh*_*bly 996
我已经定义了以下属性,因为我们经常在单元测试中使用它.
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);
}
}
Run Code Online (Sandbox Code Playgroud)
Assembly.Location
在使用NUnit(其中程序集从临时文件夹运行)时,该属性有时会给你一些有趣的结果,所以我更喜欢使用CodeBase
它以URI格式提供路径,然后在开头UriBuild.UnescapeDataString
删除它File://
,并将其GetDirectoryName
更改为正常的Windows格式.
Kei*_*ith 312
这有帮助吗?
//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 );
Run Code Online (Sandbox Code Playgroud)
Jal*_*aer 306
这很简单:
var dir = AppDomain.CurrentDomain.BaseDirectory;
Run Code Online (Sandbox Code Playgroud)
Sne*_*eal 66
与John的答案相同,但是一种稍微冗长的扩展方法.
public static string GetDirectoryPath(this Assembly assembly)
{
string filePath = new Uri(assembly.CodeBase).LocalPath;
return Path.GetDirectoryName(filePath);
}
Run Code Online (Sandbox Code Playgroud)
现在你可以这样做:
var localDir = Assembly.GetExecutingAssembly().GetDirectoryPath();
Run Code Online (Sandbox Code Playgroud)
或者如果您愿意:
var localDir = typeof(DaoTests).Assembly.GetDirectoryPath();
Run Code Online (Sandbox Code Playgroud)
Ign*_*cia 46
使用CodeBase和UNC Network共享时,唯一有效的解决方案是:
System.IO.Path.GetDirectoryName(new System.Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath);
Run Code Online (Sandbox Code Playgroud)
它也适用于普通的URI.
jod*_*ell 32
除非程序集是阴影复制,否则这应该有效:
string path = System.Reflection.Assembly.GetExecutingAssembly().Location
Run Code Online (Sandbox Code Playgroud)
Ily*_*dik 19
我相信这适用于任何类型的应用程序:
AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory
Run Code Online (Sandbox Code Playgroud)
hus*_*int 14
那这个呢:
System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
Run Code Online (Sandbox Code Playgroud)
Cur*_*her 11
我怀疑这里真正的问题是你的测试运行器正在将你的程序集复制到另一个位置.在运行时无法确定程序集的复制位置,但您可以翻转一个开关,告诉测试运行程序从何处运行程序集,而不是将其复制到影子目录.
当然,对于每个测试跑步者来说,这种切换可能是不同的.
您是否考虑将XML数据作为资源嵌入测试程序集中?
var assembly = System.Reflection.Assembly.GetExecutingAssembly();
var assemblyPath = assembly.GetFiles()[0].Name;
var assemblyDir = System.IO.Path.GetDirectoryName(assemblyPath);
Run Code Online (Sandbox Code Playgroud)
这是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
Run Code Online (Sandbox Code Playgroud)
据我所知,大多数其他答案都有一些问题.
对基于磁盘(而不是基于Web)的非GACed程序集执行此操作的正确方法是使用当前正在执行的程序集的CodeBase
属性.
这将返回一个URL(file://
).而不是乱搞字符串操作,或者UnescapeDataString
通过利用LocalPath
属性来轻松转换Uri
.
var codeBaseUrl = Assembly.GetExecutingAssembly().CodeBase;
var filePathToCodeBase = new Uri(codeBaseUrl).LocalPath;
var directoryPath = Path.GetDirectoryName(filePathToCodeBase);
Run Code Online (Sandbox Code Playgroud)
这个怎么样 ...
string ThisdllDirectory = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
Run Code Online (Sandbox Code Playgroud)
然后只是砍掉你不需要的东西
从 .net framework 4.6 / .net core 1.0 开始,现在有一个AppContext.BaseDirectory,它应该给出与 相同的结果AppDomain.CurrentDomain.BaseDirectory
,除了 AppDomains 不是 .net core 1.x /.net 标准 1.x API 的一部分.
AppContext.BaseDirectory
Run Code Online (Sandbox Code Playgroud)
编辑:文档现在甚至声明:
在 .NET 5.0 及更高版本中,对于捆绑程序集,返回的值是主机可执行文件的包含目录。
事实上,Assembly.Location doc doc 说:
在 .NET 5.0 及更高版本中,对于捆绑程序集,返回的值为空字符串。
这些年来,没有人真正提到这一个.我从一个很棒的ApprovalTests项目中学到了一个技巧.诀窍是您使用程序集中的调试信息来查找原始目录.
这不能在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;
}
}
Run Code Online (Sandbox Code Playgroud)
程序集和 DLL 文件的概念不同。根据程序集的加载方式,路径信息会丢失或根本不可用。不过,在大多数情况下,提供的答案会起作用。
这个问题和之前的答案存在一个误解。在大多数情况下,提供的答案可以正常工作,但在某些情况下,无法获得当前代码所在的程序集的正确路径。
程序集(包含可执行代码)和 dll 文件(包含程序集)的概念不是紧密耦合的。程序集可能来自 DLL 文件,但并非必须如此。
使用Assembly.Load(Byte[])
( MSDN ) 方法可以直接从内存中的字节数组加载程序集。字节数组来自哪里并不重要。它可以从文件加载,从互联网下载,动态生成,...
这是一个从字节数组加载程序集的示例。文件加载后路径信息丢失。无法获得原始文件路径,并且之前描述的所有方法都不起作用。
此方法位于执行程序集中,该程序集位于“D:/Software/DynamicAssemblyLoad/DynamicAssemblyLoad/bin/Debug/Runner.exe”
static void Main(string[] args)
{
var fileContent = File.ReadAllBytes(@"C:\Library.dll");
var assembly = Assembly.Load(fileContent);
// Call the method of the library using reflection
assembly
?.GetType("Library.LibraryClass")
?.GetMethod("PrintPath", BindingFlags.Public | BindingFlags.Static)
?.Invoke(null, null);
Console.WriteLine("Hello from Application:");
Console.WriteLine($"GetViaAssemblyCodeBase: {GetViaAssemblyCodeBase(assembly)}");
Console.WriteLine($"GetViaAssemblyLocation: {assembly.Location}");
Console.WriteLine($"GetViaAppDomain : {AppDomain.CurrentDomain.BaseDirectory}");
Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)
这个类位于 Library.dll 中:
public class LibraryClass
{
public static void PrintPath()
{
var assembly = Assembly.GetAssembly(typeof(LibraryClass));
Console.WriteLine("Hello from Library:");
Console.WriteLine($"GetViaAssemblyCodeBase: {GetViaAssemblyCodeBase(assembly)}");
Console.WriteLine($"GetViaAssemblyLocation: {assembly.Location}");
Console.WriteLine($"GetViaAppDomain : {AppDomain.CurrentDomain.BaseDirectory}");
}
}
Run Code Online (Sandbox Code Playgroud)
为了完整起见,这里的实现GetViaAssemblyCodeBase()
对于两个程序集都是相同的:
private static string GetViaAssemblyCodeBase(Assembly assembly)
{
var codeBase = assembly.CodeBase;
var uri = new UriBuilder(codeBase);
return Uri.UnescapeDataString(uri.Path);
}
Run Code Online (Sandbox Code Playgroud)
Runner 打印以下输出:
Hello from Library:
GetViaAssemblyCodeBase: D:/Software/DynamicAssemblyLoad/DynamicAssemblyLoad/bin/Debug/Runner.exe
GetViaAssemblyLocation:
GetViaAppDomain : D:\Software\DynamicAssemblyLoad\DynamicAssemblyLoad\bin\Debug\
Hello from Application:
GetViaAssemblyCodeBase: D:/Software/DynamicAssemblyLoad/DynamicAssemblyLoad/bin/Debug/Runner.exe
GetViaAssemblyLocation:
GetViaAppDomain : D:\Software\DynamicAssemblyLoad\DynamicAssemblyLoad\bin\Debug\
Run Code Online (Sandbox Code Playgroud)
如您所见,代码库、位置或基本目录都不正确。
您存在的当前目录.
Environment.CurrentDirectory; // This is the current directory of your application
Run Code Online (Sandbox Code Playgroud)
如果您使用build复制.xml文件,您应该找到它.
要么
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetAssembly(typeof(SomeObject));
// The location of the Assembly
assembly.Location;
Run Code Online (Sandbox Code Playgroud)
我一直在使用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("/", "\\");
Run Code Online (Sandbox Code Playgroud)
它一直在工作,但我不再确定它是100%正确的.http://blogs.msdn.com/suzcook/archive/2003/06/26/assembly-codebase-vs-assembly-location.aspx上的页面说:
"CodeBase是找到文件的地方的URL,而Location是实际加载的路径.例如,如果程序集是从Internet下载的,它的CodeBase可能以"http://"开头. ,但它的位置可能以"C:\"开头.如果文件是阴影复制的,则位置将是阴影副本目录中文件副本的路径.知道CodeBase不能得到保证也很好要为GAC中的程序集设置.但是,总是会为从磁盘加载的程序集设置位置. "
您可能希望使用CodeBase而不是Location.
小智 5
在 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"
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
581858 次 |
最近记录: |