如何在C#中将Assembly.CodeBase转换为文件系统路径?

11 浏览
0 Comments

如何在C#中将Assembly.CodeBase转换为文件系统路径?

我有一个项目,将模板存储在与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,则在此上下文中引发异常是完全可以的)

admin 更改状态以发布 2023年5月20日
0
0 Comments

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方案的缺陷):
    • 请注意空格字符()如何转换为%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:///并完成它,我认为这个解决方案已经足够好了,尽管确实非常丑陋。

0
0 Comments

你需要使用System.Uri.LocalPath:

string localPath = new Uri("file:///D:/projects/MyApp/MyApp/bin/debug/MyApp.exe").LocalPath;

所以如果你想获得当前执行程序集的原始位置:

string localPath = new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath;

LocalPath包括程序集的文件名,例如:

D:\projects\MyApp\MyApp\bin\debug\MyApp.exe

如果你想获得程序集的目录,那么使用System.IO.Path.GetDirectoryName():

string localDirectory = Path.GetDirectoryName(new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath);

这将给你:

D:\projects\MyApp\MyApp\bin\debug

0