【问题标题】:How do I find the current executable filename? [duplicate]如何找到当前的可执行文件名? [复制]
【发布时间】:2010-11-02 02:03:58
【问题描述】:

可能重复:
How do I get the name of the current executable in C#?

可执行文件加载外部库。
库有没有办法知道调用的可执行文件?

(我发誓我在其他地方看到了这个问题的答案,但我似乎再也找不到了)

【问题讨论】:

    标签: c# .net


    【解决方案1】:

    除了上面的答案。

    我编写了以下 test.exe 作为控制台应用程序

    static void Main(string[] args) {
      Console.WriteLine(
        System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName);
      Console.WriteLine(
        System.Reflection.Assembly.GetEntryAssembly().Location);
      Console.WriteLine(
        System.Reflection.Assembly.GetExecutingAssembly().Location);
      Console.WriteLine(
        System.Reflection.Assembly.GetCallingAssembly().Location);
    }
    

    然后我编译了项目并将其输出重命名为 test2.exe 文件。输出行正确且相同。

    但是,如果我在 Visual Studio 中启动它,结果是:

    d:\test2.vhost.exe

    d:\test2.exe

    d:\test2.exe

    C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll

    Visual Studio 的 ReSharper 插件在

    System.Diagnostics.Process.GetCurrentProcess().MainModule
    

    尽可能 System.NullReferenceException。如果你查看 MainModule 的文档,你会发现这个属性也可以抛出 NotSupportedException、PlatformNotSupportedException 和 InvalidOperationException。

    GetEntryAssembly 方法也不是 100%“安全”的。 MSDN:

    GetEntryAssembly 方法在托管程序集时可以返回 null 已从非托管应用程序加载。例如,如果一个 非托管应用程序创建一个编写的 COM 组件的实例 在 C# 中,从 C# 组件调用 GetEntryAssembly 方法 返回 null,因为进程的入口点是非托管的 代码而不是托管程序集。

    对于我的解决方案,我更喜欢Assembly.GetEntryAssembly().Location。

    如果需要解决虚拟化的问题,则更感兴趣。例如,我们有一个项目,我们使用 Xenocode Postbuild 将 .net 代码链接到一个可执行文件中。必须重命名此可执行文件。所以上面所有的方法都不起作用,因为它们只获取原始程序集或内部进程的信息。

    我找到的唯一解决方案是

    var location = System.Reflection.Assembly.GetEntryAssembly().Location;
    var directory = System.IO.Path.GetDirectoryName(location);
    var file = System.IO.Path.Combine(directory, 
      System.Diagnostics.Process.GetCurrentProcess().ProcessName + ".exe");
    

    【讨论】:

    • 如果您在 IIS 下以调试模式运行 WCF 服务应用程序,GetEntryAssembly 方法也会返回 null。诚然,这是只有开发人员才会遇到的罕见情况。
    • Assembly.GetEntryAssembly() 对我来说是空的,当我使用 Addin VS 2008 时。System.Diagnostics.Process.GetCurrentProcess().MainModule 是 devenv.exe,但不是我的 DLL 与 Addin。而且我不知道从另一个使用插件的程序集中获取(插件的)程序集。
    • 1) 如果 A.exe 使用 B.dll,而 B.dll 使用 C.dll,如果该代码在 C.dll 中会发生什么? 2) AppDomain 可以是 EXE 应用程序、Web 应用程序、单元测试应用程序、Addin Visual Studio 和“Silverlight App”(?)。可能是所有情况下有趣的完整解决方案。
    【解决方案2】:

    Environment.GetCommandLineArgs()[0]

    【讨论】:

    • 在static void Main(string[] args) 内应该是使用的那个。这很奇怪,因为根据我对 C++ 的记忆,第一个参数始终是可执行文件。
    【解决方案3】:

    这个不包括在内:

    System.Windows.Forms.Application.ExecutablePath;
    

    ~乔

    【讨论】:

    • 在我看来,Forms 命名空间有那个 Application 类总是很愚蠢……它与 Forms 完全无关。
    • LOL - 是的,我也不使用它。奇怪的地方找到它。
    • 实际上,Application 类只与 Forms 相关,因为 Application.Run 方法是启动处理所有窗口(也称为“form”)事件的主窗口消息循环的方法。它还包含 DoEvents(),它允许窗口在处理程序中处理未决事件。在 .NET 发明之前编写 Win32 API 的任何人都应该熟悉这些内容。
    【解决方案4】:
    System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName
    

    【讨论】:

    • 这个倾向于添加“.vhost”。在文件名中,如果使用 System.Reflection.Assembly.GetEntryAssembly().Location 则不会出现问题(请参阅替代答案)。
    • @Contango,这是在VS中使用“Visual Studio Hosting Process”引起的。
    • 用于 VS 2012 中的单元测试。 ProcessName: vstest.executionengine.x86 ConfigurationFile: C:\TFS\Tests\MyData.Tests.v4.0\bin\Debug\MyData.Tests.v4.0 .dll.config MainModule.FileName: C:\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO 11.0\COMMON7\IDE\COMMONEXTENSIONS\MICROSOFT\TESTWINDOW\vstest.executionengine.x86.exe MainModule.ModuleName: vstest.executionengine.x86.exe FriendlyName:UnitTestAdapter:运行测试
    • @Kiquenet,是的,在单元测试中,当前可执行文件是测试运行器;你的意思是什么?
    • 这给出了可执行文件的完整路径,如果您只需要可执行文件名,请使用 System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName。
    【解决方案5】:

    我认为这应该是你想要的:

    System.Reflection.Assembly.GetEntryAssembly().Location
    

    这将返回进程启动时首次加载的程序集,这似乎是您想要的。

    GetCallingAssembly 在一般情况下不一定会返回您想要的程序集,因为它返回的程序集包含调用堆栈中紧靠更高位置的方法(即它可能在同一个 DLL 中)。

    【讨论】:

    • 我不确定 GetCallingAssembly() - 这不是返回包含调用方法的程序集(调用堆栈上的一个)吗?这很可能是库而不是可执行文件。
    • @Martin:是的,你是对的。 GetCallingAssembly 在某些情况下可能有效/适用,但他似乎希望在这里使用 GetEntryAssembly。
    【解决方案6】:

    如果你想要可执行文件:

    System.Reflection.Assembly.GetEntryAssembly().Location
    

    如果您想要使用您的库的程序集(如果您的代码直接从可执行文件中的类调用,则可以是与上述相同的程序集):

    System.Reflection.Assembly.GetCallingAssembly().Location
    

    如果您只想要文件名称而不想要路径,请使用:

    Path.GetFileName(System.Reflection.Assembly.GetEntryAssembly().Location)
    

    【讨论】:

    • GetEntryAssembly 如果从非托管代码调用,可能会返回 null。
    • 如果可执行文件不是 .NET 应用程序,我认为这不起作用。例如,IIS 启动工作进程 (w3wp.exe),它们是非托管可执行文件,在内部启动执行托管代码的 CLR 实例。如果你在托管代码中使用它,我不相信你会得到 w3wp.exe 的路径。
    • @MicahZoltu:GetEntryAssembly 在 Web 应用程序中返回 null,请参阅 GetEntryAssembly for web applications
    • Assembly.GetEntryAssembly().Location 和 Assembly.GetCallingAssembly().Location 返回应用程序 .dll ,期望 .exe。
    【解决方案7】:

    Assembly.GetEntryAssembly()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-14
      • 1970-01-01
      • 2012-08-28
      • 2017-04-20
      • 2010-09-09
      相关资源
      最近更新 更多