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

发布于 2024-08-09 11:27:59 字数 370 浏览 5 评论 0原文

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

我有几个候选:

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

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

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).

I have several candidates:

  • 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

白云不回头 2024-08-16 11:27:59

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

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

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

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

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

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.

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

腻橙味 2024-08-16 11:27:59

我会使用 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

I would use GetEntryAssembly() instead of 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.

Put this in 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:

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.dll to c:\temp and run.

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

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

听风吹 2024-08-16 11:27:59

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

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

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

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

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

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

别在捏我脸啦 2024-08-16 11:27:59

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

Assembly.CodeBase

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

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

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

From: 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.Location property 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.

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

小情绪 2024-08-16 11:27:59

使用系统.Linq

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

Use System.Linq

string MainExecutablePath= (System.Diagnostics.Process.GetProcesses().First(P =>P.MainWindowTitle == "MainExecutable'sWindowName")).MainModule.FileName.ToString();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文