27

我是一个 .NET 用户,我的目标就像找到我的主要执行程序集(EXE 文件)的目录的绝对路径一样简单。

我有几个候选人:

  • Assembly.GetExecutingAssembly().CodeBase
  • Assembly.GetExecutingAssembly().Location
  • AppDomain.CurrentDomain.BaseDirectory

如果根据 .NET 文档来判断 - 我倾向于CodeBase. 任何人都可以用比 .NET 文档更具体的术语来阐明这三个方面吗?也许可以举一个例子来证明差异?

4

5 回答 5

17

我会使用GetEntryAssembly()而不是GetExecutingAssembly().

要了解原因,请执行以下操作:

  • 创建一个新的控制台项目
  • 将类库项目 ( ClassLibrary1) 添加到解决方案并从控制台项目中引用它。

把这个放在ClassLibrary1

namespace ClassLibrary1
{
    using System;
    using System.IO;
    using System.Reflection;

    public class Class1
    {
        public void GetInfo(int n)
        {
            Assembly asm = Assembly.GetEntryAssembly();
            Console.WriteLine("[GetEntryAssembly {0}] Location:{1}", n, Path.GetDirectoryName(asm.Location));
            asm = Assembly.GetExecutingAssembly();
            Console.WriteLine("[GetExecutingAssembly() {0}] Location:{1}", n, Path.GetDirectoryName(asm.Location));
        }
    }
}

把它放在控制台的Program.cs

namespace ConsoleApplication4
{
    using System;
    using System.IO;
    using System.Reflection;
    using ClassLibrary1;

    class Program
    {
        static void Main(string[] args)
        {
            Assembly asm = Assembly.GetEntryAssembly();
            Console.WriteLine("[GetEntryAssembly() 1] Location:{0}", Path.GetDirectoryName(asm.Location));
            asm = Assembly.GetExecutingAssembly();
            Console.WriteLine("[GetExecutingAssembly() 1] Location:{0}", Path.GetDirectoryName(asm.Location));

            Class1 obj1 = new Class1();
            obj1.GetInfo(2);

            asm = Assembly.LoadFile(@"C:\temp\ClassLibrary1.dll");
            Type t = asm.GetType("ClassLibrary1.Class1");
            object obj2 = asm.CreateInstance("ClassLibrary1.Class1");
            t.GetMethod("GetInfo").Invoke(obj2, new object[] { 3 });

            Console.ReadKey();
        }
    }
}

构建解决方案,复制ClassLibrary1.dllc:\temp并运行。

如您所见,GetExecutingAssembly()在某些情况下可能会欺骗您。

最后一点,如果您的应用程序是 Windows 窗体应用程序,您可以只使用Application.ExecutablePath.

于 2009-10-29T11:53:44.863 回答
16

我不确定,但在这篇博文中解释了和AppDomain.CurrentDomain.BaseDirectory之间的区别。Assembly.GetExecutingAssembly().CodeBaseAssembly.GetExecutingAssembly().Location

CodeBase 是指向文件所在位置的 URL,而 Location 是实际加载文件的路径。例如,如果程序集是从 Internet 下载的,则其 CodeBase 可能以“http://”开头,但其 Location 可能以“C:\”开头。如果文件是影子复制的,则 Location 将是影子复制目录中文件副本的路径。

还很高兴知道,不能保证为 GAC 中的程序集设置 CodeBase。但是,将始终为从磁盘加载的程序集设置位置。

所以看起来你最好的选择是Location如果你需要执行文件的真实目录。

于 2011-11-10T15:18:31.483 回答
8

不幸的是,如果您使用 XenoCode postbuild 之类的虚拟化,上述所有方法都可能失败。我测试了很多方法,在这里找到了另一种解决方案。我发现只有

System.Diagnostics.Process.GetCurrentProcess().ProcessName + ".exe"

返回可执行文件的正确文件名。因此,将文件名与Assembly.GetEntryAssembly().Location您的路径相结合将获得可执行文件的正确路径。

于 2010-05-17T15:29:34.370 回答
0

来自:http: //msdn.microsoft.com/en-us/library/system.reflection.assembly.codebase.aspx

汇编代码库

要获取加载的包含清单的文件的绝对路径,请改用该 Assembly.Location属性。

如果程序集是作为字节数组加载的,则使用采用字节数组的 Load 方法的重载,此属性返回方法调用者的位置,而不是加载的程序集的位置。

因为AppDomain.CurrentDomain.BaseDirectory,老实说,从实际的角度来看,我不知道这些差异。

于 2009-10-29T10:43:20.253 回答
-3

使用 System.Linq

string MainExecutablePath= (System.Diagnostics.Process.GetProcesses().First(P =>P.MainWindowTitle == "MainExecutable'sWindowName")).MainModule.FileName.ToString();
于 2014-02-19T09:45:49.743 回答