Assembly.CodeBase看起来很有前途,但它是一个UNC路径:
请注意,它是类似于
文件URI,而不是
UNC路径。
你可以通过手动进行字符串操作来解决这个问题。真的。
尝试在以下目录中找到所有其他你能在SO上找到的方法(逐字逐句):
C:\Test\Space( )(h#)(p%20){[a&],t@,p%,+}.,\Release
这是一个有效的,虽然有些不寻常的Windows路径。(有些人的路径中可能会有这些字符之一,而且你肯定希望你的方法对所有这些情况都能正常工作,对吧?)
可用的代码库(
我们不需要Location
,对吧?)属性然后是(在我的Win7上使用.NET 4):
assembly.CodeBase -> file:///C:/Test/Space( )(h#)(p%20){[a&],t@,p%,+}.,/Release
assembly.EscapedCodeBase -> file:///C:/Test/Space(%20)(h%23)(p%20)%7B%5Ba%26%5D,t@,p%,+%7D.,/Release
你会注意到:
CodeBase
根本没有被转义,它只是常规的本地路径前缀加上file:///
,并且反斜杠被替换掉。因此,将其传递给System.Uri
是不起作用的。
EscapedCodeBase
并没有完全转义(我不知道这是否是一个错误,或者这是否是URI scheme的不足之处):
- 注意空格字符(
)被转换为%20
- 但是
%20
序列也被转换为%20
!(百分号%
根本没有被转义)
- 没有人能够从这个混乱的形式中重建原始形式!
对于本地文件(这对于
CodeBase
的东西来说真的是我关心的全部),因为如果文件不是本地的,你可能想要使用
.Location
,以下对我来说是有效的(请注意,它也不是最漂亮的):
public static string GetAssemblyFullPath(Assembly assembly)
{
string codeBasePseudoUrl = assembly.CodeBase;
if (codeBasePseudoUrl != null) {
const string filePrefix3 = @"file:///";
if (codeBasePseudoUrl.StartsWith(filePrefix3)) {
string sPath = codeBasePseudoUrl.Substring(filePrefix3.Length);
string bsPath = sPath.Replace('/', '\\');
Console.WriteLine("bsPath: " + bsPath);
string fp = Path.GetFullPath(bsPath);
Console.WriteLine("fp: " + fp);
return fp;
}
}
System.Diagnostics.Debug.Assert(false, "CodeBase evaluation failed! - Using Location as fallback.");
return Path.GetFullPath(assembly.Location);
}
我相信人们可以提出更好的解决方案,可能甚至可以提出一个解决方案,如果
CodeBase
属性是一个本地路径,那么可以进行正确的URL编码/解码。但是,考虑到我们只需要去掉
file:///
就可以解决问题,我认为这个解决方案已经足够好了,尽管确实很丑陋。