如何将 Assembly.CodeBase 转换为 C# 中的文件系统路径?
我有一个项目,将模板存储在 DLL 和 EXE 旁边的 \Templates
文件夹中。
我想在运行时确定此文件路径,但使用一种既可以在单元测试中也可以在生产中使用的技术(并且我不想在 NUnit 中禁用卷影复制!)
Assembly.Location 不好,因为在 NUnit 下运行时它会返回卷影复制程序集的路径。
Environment.CommandLine
的用途也有限,因为在 NUnit 等中它返回 NUnit 的路径,而不是我的项目的路径。
Assembly.CodeBase
看起来很有希望,但它是一个 UNC 路径:
file:///D:/projects/MyApp/MyApp/bin/debug/MyApp.exe
现在我可以使用字符串操作将其转换为本地文件系统路径,但我怀疑有一种更简洁的方法可以做到这一点埋藏在 .NET 框架的某个地方。有人知道这样做的推荐方法吗?
(如果 UNC 路径不是 file:///
URL,则在这种情况下抛出异常是绝对没问题的)
I have a project that stores templates in a \Templates
folder next to the DLLs and EXE.
I want to determine this file path at runtime, but using a technique that will work inside a unit test as well as in production (and I don't want to disable shadow-copying in NUnit!)
Assembly.Location
is no good because it returns the shadow-copied assembly's path when running under NUnit.
Environment.CommandLine
is also of limited use because in NUnit et al it returns the path to NUnit, not to my project.
Assembly.CodeBase
looks promising, but it's a UNC path:
file:///D:/projects/MyApp/MyApp/bin/debug/MyApp.exe
Now I could turn this into a local filesystem path using string manipulation, but I suspect there's a cleaner way of doing it buried in the .NET framework somewhere. Anyone know a recommended way of doing this?
(Throwing an exception if the UNC path is not a file:///
URL is absolutely fine in this context)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您需要使用 System.Uri.LocalPath:
因此,如果您想要当前正在执行的程序集的原始位置:
LocalPath 包括程序集的文件名,例如,
如果您想要程序集的目录,则使用 System.IO.Path.GetDirectoryName( ):
这将为您提供:
You need to use System.Uri.LocalPath:
So if you want the original location of the currently executing assembly:
The LocalPath includes the assembly's file name, e.g.,
If you want the assembly's directory, then use System.IO.Path.GetDirectoryName():
which will give you:
请注意,它近似于 文件 uri,不是 UNC 路径 。
您可以通过手动进行字符串操作来解决这个问题。 说真的。
尝试使用以下目录(逐字记录)在 SO 上找到的所有其他方法:
这是一个有效的 Windows 路径,尽管有些不寻常。 (有些人会在路径中拥有这些字符之一,并且您希望您的方法适用于所有这些字符,对吧?)
可用的代码库(< a href="https://web.archive.org/web/20101010144616/http://blogs.msdn.com/b/suzcook/archive/2003/06/26/ assembly-codebase-vs- assembly-location。 aspx" rel="nofollow noreferrer">我们不需要
Location
,对吗?)属性是(在我的 Win7 和 .NET 4 上):您会注意到:
CodeBase
根本没有转义,它只是以file:///
为前缀的常规本地路径,并替换了反斜杠。因此,将其提供给System.Uri
不起作用。EscapedCodeBase
没有完全转义(我不知道这是否是一个错误,或者是否是URI 方案):) 如何转换为
%20
%20
序列也会转换为%20
! (百分比%
根本没有转义)对于本地文件(这就是我真正关心的
CodeBase
内容,因为如果文件不是本地的,您可能无论如何都想使用.Location
,以下内容对我有用(请注意,它也不是最漂亮的:我确信人们可以想出更好的解决方案,甚至可能想出一种解决方案,对
CodeBase 进行正确的 URL 编码/解码
属性,如果它是本地路径,但考虑到人们可以去掉file:///
并完成它,我想说这个解决方案足够好,如果当然真的很丑。Do note that it is something approximating a file uri, not an UNC path.
You solve this by doing string manipulation by hand. Seriously.
Try all other methods you can find on SO with the following directory (verbatim):
This is a valid, if somewhat unusual, Windows path. (Some people will have either one of these characters in there paths, and you would want you method to work for all of those, right?)
The available code base (we do not want
Location
, right?) properties are then (on my Win7 with .NET 4):You will note:
CodeBase
is not escaped at all, it's just the regular local path prefixed withfile:///
and the backslashes replaced. As such, it does not work to feed this toSystem.Uri
.EscapedCodeBase
is not escaped completely (I do not know if this is a bug or if this is a shortcoming of the URI scheme):) translates to
%20
%20
sequence also translates to%20
! (percent%
is not escaped at all)For local files (And that's really all I'd care about for the
CodeBase
stuff, because if the file ain't local, you probably want to use.Location
anyway, the following works for me (note that it isn't the prettiest either:I am sure one can come up with better solutions, probably one could even come up with a solution that does proper URL en-/decoding of the
CodeBase
property if it's a local path, but given that one can just strip off thefile:///
and be done with it, I'd say this solution stands as good enough, if certainly really ugly.这应该可行:
我使用它能够使用独立的 log4net.config 文件从 dll 库中进行日志记录。
This should work:
I am using this to be able to log from within the dll libraries using a standalone log4net.config file.
另一种解决方案,包括复杂路径:
和测试:
One more solution, including complex paths:
and tests:
由于您标记了此问题NUnit,因此您还可以使用
AssemblyHelper.GetDirectoryName
来获取执行程序集的原始目录:Since you tagged this question NUnit, you can also use
AssemblyHelper.GetDirectoryName
to get the original directory of the executing assembly: