Assembly.CodeBase 看起来很有希望,但它是一条 UNC 路径:
请注意,它近似于文件uri,而不是UNC 路径。
您可以通过手动进行字符串操作来解决这个问题。严重地。
尝试使用以下目录(逐字)在 SO 上找到的所有其他方法:
C:\Test\Space( )(h#)(p%20){[a&],t@,p%,+}.,\Release
这是一个有效的(如果有些不寻常的话)Windows 路径。(有些人会在其中的路径中有这些角色之一,您希望您的方法适用于所有这些角色,对吗?)
可用的代码库(我们不想要Location
,对吗?)属性是(在我的带有 .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 方案的一个缺点):
- 请注意空格字符 (
) 如何转换为%20
- 但
%20
序列也转换为%20
!(百分比%
根本没有逃脱)
- 没有人可以从这种扭曲的形式重建原件!
对于本地文件(这就是我真正关心的CodeBase
东西,因为如果文件不是本地文件,您可能无论如何都想使用.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:///
并完成它,我会说这个解决方案足够好,如果肯定真的很难看的话。