使用Assembly vs AppDomain查找我的主要可执行文件的路径

时间:2009-10-29 10:39:20

标签: .net path directory exe

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

我有几位候选人:

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

如果要通过.NET文档判断 - 我倾向于CodeBase。 任何人都可以用比.NET文档更具体的术语来解释这三个问题吗?举例来证明这种差异?

5 个答案:

答案 0 :(得分:16)

我会使用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.dll复制到c:\temp并运行。

正如您将看到的,GetExecutingAssembly()可能会在某些条件下欺骗您。

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

答案 1 :(得分:12)

我不确定AppDomain.CurrentDomain.BaseDirectory,但解释Assembly.GetExecutingAssembly().CodeBaseAssembly.GetExecutingAssembly().Location之间的差异in this blog post

  

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

     

知道不保证为GAC中的程序集设置CodeBase也是很好的。但是,总是会为从磁盘加载的程序集设置位置。

如果您需要执行文件的真实目录,那么最好的选择是Location

答案 2 :(得分:8)

不幸的是,如果您使用像XenoCode postbuild这样的虚拟化,上面的所有方法都会失败。 我测试了很多方法并找到了另一个解决方案here。 我发现只有

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

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

答案 3 :(得分:0)

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

<强> Assembly.CodeBase

  

获取加载的绝对路径   包含清单的文件,使用   而是Assembly.Location财产。

     

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

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

答案 4 :(得分:-3)

使用System.Linq

string MainExecutablePath= (System.Diagnostics.Process.GetProcesses().First(P =>P.MainWindowTitle == "MainExecutable'sWindowName")).MainModule.FileName.ToString();