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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1642827/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 13:30:33  来源:igfitidea点击:

Finding my main executable's path using Assembly vs AppDomain

.netpathdirectoryexe

提问by tsemer

I'm a .NET user, and my goal is as simple as finding the absolute path of the directory of my main executing assembly (the EXE file).

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

I have several candidates:

我有几个候选人:

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

If to judge by the .NET documentation - I'm leaning towards CodeBase. Can anyone shed light over all three in a bit more specific terms than the .NET documentation? An example to demonstrate the difference perhaps?

如果根据 .NET 文档来判断 - 我倾向于CodeBase. 谁能用比 .NET 文档更具体的术语来阐明这三个方面?一个例子来证明差异?

回答by Sorin Comanescu

I would use GetEntryAssembly()instead of GetExecutingAssembly().

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

To see why, do this:

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

  • Create a new Console Project
  • Add a class library project (ClassLibrary1) to the solution and reference it from the Console Project.
  • 创建一个新的控制台项目
  • 将类库项目 ( ClassLibrary1)添加到解决方案并从控制台项目中引用它。

Put this in 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));
        }
    }
}

Put this in console's Program.cs:

把它放在控制台的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();
        }
    }
}

Build the solution, copy ClassLibrary1.dllto c:\tempand run.

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

As you will see, GetExecutingAssembly()may trick you in certain conditions.

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

One last note, if your app is a Windows Forms one, you can just use Application.ExecutablePath.

最后要注意的是,如果您的应用程序是 Windows Forms 应用程序,您只需使用Application.ExecutablePath.

回答by René

I'm not sure about AppDomain.CurrentDomain.BaseDirectory, but the difference between Assembly.GetExecutingAssembly().CodeBaseand Assembly.GetExecutingAssembly().Locationwas explained in this blog post.

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

The CodeBase is a URL to the place where the file was found, while the Location is the path from where it was actually loaded. For example, if the assembly was downloaded from the internet, its CodeBase may start with "http://", but its Location may start with "C:\". If the file was shadow copied, the Location would be the path to the copy of the file in the shadow-copy dir.

It's also good to know that the CodeBase is not guaranteed to be set for assemblies in the GAC. Location will always be set for assemblies loaded from disk, however.

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

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

So it seems your best bet is Locationif you need the real directory the file was executed from.

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

回答by Alexander Zwitbaum

Unfortunately, all the methods above can fail if you use a virtualization like XenoCode postbuild. I have tested many methods and found another solution here. I've found that only the

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

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

returns the correct filename of the executable. So combining the filename with the path from Assembly.GetEntryAssembly().Locationyou will get the correct path of the executable.

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

回答by o.k.w

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

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

Assembly.CodeBase

汇编代码库

To get the absolute path to the loaded manifest-containing file, use the Assembly.Locationproperty instead.

If the assembly was loaded as a byte array, using an overload of the Load method that takes an array of bytes, this property returns the location of the caller of the method, not the location of the loaded assembly.

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

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

For AppDomain.CurrentDomain.BaseDirectory, I honestly have no idea about the differences from a practical point of view.

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

回答by balaji dileep kumar

Use System.Linq

使用 System.Linq

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