代码之家  ›  专栏  ›  技术社区  ›  Dylan Beattie

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

  •  57
  • Dylan Beattie  · 技术社区  · 14 年前

    我有一个项目将模板存储在 \Templates dll和EXE旁边的文件夹。

    Assembly.Location 不好,因为它在NUnit下运行时返回卷影复制的程序集路径。

    Environment.CommandLine 也有有限的用途,因为在NUnit等人中,它返回到NUnit的路径,而不是我的项目。

    Assembly.CodeBase 看起来很有希望,但这是一条北卡罗来纳州的道路:

    file:///D:/projects/MyApp/MyApp/bin/debug/MyApp.exe
    

    现在我 能够

    (如果UNC路径不是 file:/// URL在这个上下文中是绝对正确的)

    5 回复  |  直到 10 年前
        1
  •  110
  •   Martin Ba    10 年前

    您需要使用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;
    
        2
  •  25
  •   Stephen Kennedy annamataws    7 年前

    Assembly.CodeBase看起来很有前途,但它是一个UNC路径:

    请注意,这是一个近似的东西。 file uri , 一个 UNC path


    你可以通过手工操作字符串来解决这个问题。 说真的。

    使用以下目录(逐字)尝试您可以在SO上找到的所有其他方法:

    C:\Test\Space( )(h#)(p%20){[a&],t@,p%,+}.,\Release
    

    全部的 是吗?)

    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 知道这是一个bug还是 URI scheme
      • 注意空格字符( )翻译成 %20
      • %20个 序列 翻译成 %20个 ! (百分比 %
      • 没有人

    对于本地文件(这就是我真正关心的 代码库 东西,因为如果文件不是本地的,你可能想使用 .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);
        }
    

    我相信人们可以想出更好的解决方案,甚至有可能想出一个解决方案,对 代码库 属性,如果它是本地路径,但考虑到可以将 文件:/// 算了吧,如果 当然 真丑。

        3
  •  5
  •   mmmmmm    12 年前

    这应该有效:

    ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
    Assembly asm = Assembly.GetCallingAssembly();
    String path = Path.GetDirectoryName(new Uri(asm.EscapedCodeBase).LocalPath);
    
    string strLog4NetConfigPath = System.IO.Path.Combine(path, "log4net.config");
    

    我使用这个可以从dll库中使用一个独立的log4net.config文件进行日志记录。

        4
  •  4
  •   ili    8 年前

        public static string GetPath(this Assembly assembly)
        {
            return Path.GetDirectoryName(assembly.GetFileName());
        }
    
        public static string GetFileName(this Assembly assembly)
        {
            return assembly.CodeBase.GetPathFromUri();
        }
    
        public static string GetPathFromUri(this string uriString)
        {
            var uri = new Uri(Uri.EscapeUriString(uriString));
            return String.Format("{0}{1}", Uri.UnescapeDataString(uri.PathAndQuery), Uri.UnescapeDataString(uri.Fragment));
        }
    

    以及测试:

        [Test]
        public void GetPathFromUriTest()
        {
            Assert.AreEqual(@"C:/Test/Space( )(h#)(p%20){[a&],t@,p%,+}.,/Release", @"file:///C:/Test/Space( )(h#)(p%20){[a&],t@,p%,+}.,/Release".GetPathFromUri());
            Assert.AreEqual(@"C:/Test/Space( )(h#)(p%20){[a&],t@,p%,+}.,/Release",  @"file://C:/Test/Space( )(h#)(p%20){[a&],t@,p%,+}.,/Release".GetPathFromUri());
        }
    
        [Test]
        public void AssemblyPathTest()
        {
            var asm = Assembly.GetExecutingAssembly();
    
            var path = asm.GetPath();
            var file = asm.GetFileName();
    
            Assert.IsNotEmpty(path);
            Assert.IsNotEmpty(file);
    
            Assert.That(File     .Exists(file));
            Assert.That(Directory.Exists(path));
        }
    
        5
  •  2
  •   wezzix maxk    9 年前

    既然你标记了这个问题 单元测试 AssemblyHelper.GetDirectoryName 要获取执行程序集的原始目录,请执行以下操作:

    using System.Reflection;
    using NUnit.Framework.Internal;
    ...
    string path = AssemblyHelper.GetDirectoryName(Assembly.GetExecutingAssembly())