Assembly.CodeBase 看起来很有希望,但它是一条 UNC 路径:
请注意,它近似于 file uri,不是 UNC path。
您可以通过手动操作字符串来解决这个问题。 说真的。
尝试使用以下目录(逐字)在 SO 上找到的所有其他方法:
C:\Test\Space( )(h#)(p%20){[a&],t@,p%,+}.,\Release
这是一个有效的 Windows 路径,虽然有些不寻常。 (有些人会在其中的路径中有这些字符之一,你希望你的方法适用于所有,对吧?)
然后可用的代码库 (we do not want Location, right?) 属性是(在我的带有 .NET 4 的 Win7 上):
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! (百分比% 根本没有转义)
-
没有人可以用这种损坏的形式重建原件!
对于本地文件(这就是我真正关心 CodeBasestuff 的全部内容,因为如果文件不是本地文件,您可能还是想使用 .Location,以下对我有用(请注意它也不是最漂亮的:
public static string GetAssemblyFullPath(Assembly assembly)
{
string codeBasePseudoUrl = assembly.CodeBase; // "pseudo" because it is not properly escaped
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:/// 并完成它,我会说这个解决方案已经足够好了,如果当然真的很丑。