如何在 C# 中获取当前可执行文件的名称?

Posted

技术标签:

【中文标题】如何在 C# 中获取当前可执行文件的名称?【英文标题】:How do I get the name of the current executable in C#? 【发布时间】:2009-03-05 21:00:07 【问题描述】:

我想获取当前正在运行的程序的名称,即程序的可执行名称。在 C/C++ 中,您可以从 args[0] 获得它。

【问题讨论】:

可执行文件是 EXE 文件(Windows 窗体、WPF 应用程序)?程序可以是桌面应用程序(WinForms、WPF 和 WinRT-Windows Phone?)、Web 应用程序、Wcf 服务应用程序、Visual Studio 插件、Outlook-Word 插件、VS 中的单元测试 (MSTest) 或 Silverlight 应用程序。 【参考方案1】:
System.AppDomain.CurrentDomain.FriendlyName

【讨论】:

提防接受的答案。我们在 Click-Once 部署的应用程序下使用 System.AppDomain.CurrentDomain.FriendlyName 时遇到了问题。对我们来说,这是返回“DefaultDomain”,而不是原始的 exe 名称。 我们最后用了这个:string file = object_of_type_in_application_assembly.GetType().Assembly.Location; string app = System.IO.Path.GetFileNameWithoutExtension( file ); FriendlyName 可以设置为任何值。如果您有一个带有多个 dll 的 exe,那么获取程序集位置可能还不够。此外,如果您使用多个 AppDomain,Assembly.GetCallingAssembly() 将返回 null。 @Gaspode :只说 Path.GetFileNameWithoutExtension(GetType().Assembly.Location) 会更容易 - 您不需要在当前程序集中指定类型的对象。你可以使用这个的GetType,然后你甚至不需要说“这个”。 这可能很有用,但它应该是公认的答案:它与所要求的有很大不同 - 巧合的是,它在 中是相同的一些 的情况,但这完全是另外一回事。如果您不是自己编写应用程序,它很可能会返回“我喜欢土豆!”或者您的幽默同事在构建应用程序时在此属性中写入的任何其他内容!【参考方案2】:

System.AppDomain.CurrentDomain.FriendlyName - 返回带有扩展名的文件名(例如 MyApp.exe)。

System.Diagnostics.Process.GetCurrentProcess().ProcessName - 返回文件名 没有 扩展名(例如 MyApp)。

System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName - 返回完整路径和文件名(例如 C:\Examples\Processes\MyApp.exe)。然后,您可以将其传递给 System.IO.Path.GetFileName()System.IO.Path.GetFileNameWithoutExtension() 以获得与上述相同的结果。

【讨论】:

AppDomain 可以是 EXE 应用程序、Web 应用程序、单元测试应用程序、Addin Visual Studio 和“Silverlight 应用程序”(?)。也许对所有情况都有趣的完整解决方案。例如,对于单元测试 VS2012 - ProcessName: vstest.executionengine.x86 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:运行测试ApplicationName: “程序”可以是桌面应用程序(WinForms、WPF 和 WinRT-Windows Phone?)、Web 应用程序、Wcf 服务应用程序、Visual Studio 插件、Outlook-Word 插件、VS 中的单元测试(MSTest) 或 Silverlight 应用程序。例如,如何获取托管在 IIS 中的 Wcf 服务应用程序的服务主机程序集,而不是 IISExpress 或 WebDevServer ? +1 我会选择这个答案,因为它以简洁明了的方式提供了您可能需要的所有三种变体。使用不带路径或扩展名的纯程序名称对于程序内帮助文本(/? 开关)非常有用,因为使用扩展名和路径只会不必要地弄乱它。 记得处置GetCurrentProcess()的结果 Process.GetCurrentProcess().ProcessName() 为我返回 MyApp.vshost【参考方案3】:

这就足够了:

Environment.GetCommandLineArgs()[0];

【讨论】:

嗯,这会返回(当从 vs.net 运行并使用调试托管的东西时),filename.vshost.exe 的位置和名称......这确实是正在执行的文件这次) 这对我来说是最好的答案,因为 Environment.GetCommandLineArgs() 是 C/C++ 中 argv 的确切 C# 类似物。 同意!最佳答案。我需要获取 Environment.GetCommandLineArgs()[1]; 避免完整路径:Path.GetFileNameWithoutExtension(Environment.GetCommandLineArgs()[0]) 这在尝试跟踪 WCF 服务时效果很好。在我的情况下,进程名称与 iisexpress 一起返回。但是这个命令给了我实际的 WCF 服务程序集名称。【参考方案4】:

System.Diagnostics.Process.GetCurrentProcess() 获取当前正在运行的进程。您可以使用ProcessName 属性来确定名称。下面是一个示例控制台应用程序。

using System;
using System.Diagnostics;

class Program

    static void Main(string[] args)
    
        Console.WriteLine(Process.GetCurrentProcess().ProcessName);
        Console.ReadLine();
    

【讨论】:

更好地使用 Process.GetCurrentProcess().MainModule.FileName Process.GetCurrentProcess().MainModule.FileName 在 Excel 插件 (ExcelDNA) 中完美运行 这种方法在 Mono 运行时使用时会失败;在 Mono 上运行的应用程序的进程名称将始终是 *nixes 上的 .../bin/mono 或 Windows 上的 .../mono.exe 的某种变体。 这应该是公认的答案。当前的 AppDomain 名称可能与可执行进程名称无关,尤其是存在多个应用程序域时 @Frank 也许使用了特定于操作系统的技巧,例如阅读/proc/self/cmdline。 (var args = File.ReadAllText("/proc/self/cmdline").Split('\0'); args = args.Take(args.Length - 1).ToArray(); 会给你一个这样的参数数组。)【参考方案5】:

这是对我有用的代码:

string fullName = Assembly.GetEntryAssembly().Location;
string myName = Path.GetFileNameWithoutExtension(fullName);

以上所有示例都给了我带有 vshost 的 processName 或正在运行的 dll 名称。

【讨论】:

对于那些不知道或在其他答案中遗漏的人,Assembly 的命名空间是 System.Reflection,Path 的命名空间是 System.IO。 GetEntryAssembly 将返回 null 如果应用程序入口点在本机代码中而不是在程序集中。 当心这与 .net 5 和单文件程序集一起崩溃【参考方案6】:

试试这个:

System.Reflection.Assembly.GetExecutingAssembly()

这将为您返回一个System.Reflection.Assembly 实例,其中包含您可能想知道的有关当前应用程序的所有数据。我认为Location 属性可能会得到你想要的东西。

【讨论】:

如果 .NET 的卷影复制功能处于活动状态,使用 CodeBase 而不是 Location 可能更安全。见blogs.msdn.com/suzcook/archive/2003/06/26/… 注意GetExecutingAssembly():如果从库程序集中调用它,它会返回库程序集的名称,该名称与入口程序集(即原始可执行文件)的名称不同。如果使用 GetEntryAssembly(),它会返回实际可执行文件的名称,但如果进程在 WCF 下运行,则会引发异常(诚然,这种情况很少见)。对于最健壮的代码,请使用 Process.GetCurrentProcess().ProcessName。 @Gravitas:当然不是,任何运行“解释”的可执行文件,例如与 /usr/bin/mono 将有错误的进程名称。 ProcessName 也不适用于 Windows 服务。如果您在库中使用它,请使用 GetCallingAssembly。 为我工作。返回的 Assembly 实例 GetName() 调用的属性 Name 是您需要的,并且不包括“.exe”部分。还在 Mono/Linux 上进行了测试,得到了预期的结果。 Assembly.GetName().Name 嗯,请注意,即使您使用文件资源管理器手动重命名可执行文件,返回的字符串也不会改变。而 Environment.GetCommandLineArgs()[0] 会随着实际的可执行文件名而变化(当然)。巧合的是,第二种方法更适合我的具体情况,因为我希望将数据文件夹命名为实际的可执行文件名。【参考方案7】:

为什么没有人建议这个,很简单。

Path.GetFileName(Application.ExecutablePath)

【讨论】:

Application 驻留在哪个命名空间。 这在 Windows 窗体应用程序中很有用,但在其他情况下则不然 @NineBerry 你可能对Application.ExecutablePath的source code感兴趣。 @NineBerry 查看我的帖子。如果您添加对 System.Windows.Forms 的引用,这适用于控制台应用程序。【参考方案8】:

更多选项:

System.Reflection.Assembly.GetExecutingAssembly().GetName().Name Path.GetFileName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase

【讨论】:

见***.com/questions/616584/…【参考方案9】:
System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name;

将为您提供应用程序的文件名,例如; “我的应用程序.exe”

【讨论】:

【参考方案10】:

如果您需要程序名称来设置防火墙规则,请使用:

System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName

这将确保在 VisualStudio 中调试和直接在 Windows 中运行应用程序时名称正确。

【讨论】:

出于我的目的(创建日志文件名),这是最好的答案。如果运行托管进程(例如,服务或 Web 应用程序),System.AppDomain.CurrentDomain.FriendlyName 可以返回带有嵌入斜杠的丑陋 GUID-y 名称。 这对 .NET Core 2+ 没有 工作,它将报告“dotnet.exe” - 或者可能是应用程序主机(如果这样设置)。【参考方案11】:

当不确定或有疑问时,绕着圈跑,尖叫和喊叫。

class Ourself

    public static string OurFileName() 
        System.Reflection.Assembly _objParentAssembly;

        if (System.Reflection.Assembly.GetEntryAssembly() == null)
            _objParentAssembly = System.Reflection.Assembly.GetCallingAssembly();
        else
            _objParentAssembly = System.Reflection.Assembly.GetEntryAssembly();

        if (_objParentAssembly.CodeBase.StartsWith("http://"))
            throw new System.IO.IOException("Deployed from URL");

        if (System.IO.File.Exists(_objParentAssembly.Location))
            return _objParentAssembly.Location;
        if (System.IO.File.Exists(System.AppDomain.CurrentDomain.BaseDirectory + System.AppDomain.CurrentDomain.FriendlyName))
            return System.AppDomain.CurrentDomain.BaseDirectory + System.AppDomain.CurrentDomain.FriendlyName;
        if (System.IO.File.Exists(System.Reflection.Assembly.GetExecutingAssembly().Location))
            return System.Reflection.Assembly.GetExecutingAssembly().Location;

        throw new System.IO.IOException("Assembly not found");
    

我不能声称已经测试了每个选项,但它不会做任何愚蠢的事情,比如在调试会话期间返回虚拟主机。

【讨论】:

+1 娱乐。 :-) 不过,我几乎不会使用此代码,除非我正在编写一个不了解其环境的真正通用库(然后维护您将要使用的任何全局状态可能不是一个好主意)的名称)。 @Orwellophile “程序”可以是桌面应用程序(WinForms、WPF;和 WinRT-Windows Phone?)、Web 应用程序、Wcf 服务应用程序、Visual Studio 插件、Outlook-Word 插件、单元测试在 VS (MSTest) 或 Silverlight 应用程序中。例如,如何获取托管在 IIS 中的 Wcf 服务应用程序的服务主机程序集,而不是 IISExpress 或 WebDevServer ?任何适用于 WinForms、WPF、Web 应用程序、Wcf 服务应用程序、Visual Studio 插件、Outlook-Word 插件、VS (MSTest) 应用程序中的单元测试的完整代码?【参考方案12】: System.Reflection.Assembly.GetEntryAssembly().Location 如果程序集未从内存加载,则返回 exe 名称的位置。 System.Reflection.Assembly.GetEntryAssembly().CodeBase 以 URL 形式返回位置。

【讨论】:

经过测试,即使它是从 C# 库中调用的,它也能 100% 工作。 GetEntryAssembly() 如果您不在主 AppDomain 中,则返回 null。【参考方案13】:

您可以使用Environment.GetCommandLineArgs() 获取参数,使用Environment.CommandLine 获取输入的实际命令行。

另外,您可以使用Assembly.GetEntryAssembly()Process.GetCurrentProcess()

但是,在调试时,您应该小心,因为最后一个示例可能会给出调试器的可执行文件名称(取决于您附加调试器的方式),而不是您的可执行文件,就像其他示例一样。

【讨论】:

注意GetExecutingAssembly():如果从库程序集中调用它,它会返回库程序集的名称,该名称与入口程序集(即原始可执行文件)的名称不同。如果使用 GetEntryAssembly(),它会返回实际可执行文件的名称,但如果进程在 WCF 下运行,则会引发异常(诚然,这种情况很少见)。对于最健壮的代码,请使用 Process.GetCurrentProcess().ProcessName。 @Gravitas:好点 - 哇,我写这篇文章已经有一段时间了! :D 我会相应地编辑 Environment.CommandLine 给出绝对路径,而不是输入的命令行,至少在 Mono/Linux 上是这样。 @Mechanicalsnail:听起来 Mono 并不完全遵循文档。很有趣。【参考方案14】:

如果您正在寻找可执行文件的完整路径信息,可靠的方法是使用以下方法:

   var executable = System.Diagnostics.Process.GetCurrentProcess().MainModule
                       .FileName.Replace(".vshost", "");

这消除了中间 dll、vshost 等的任何问题。

【讨论】:

我在 Ubuntu Linux 15.10 C++ 中使用 realpath 和 STL C++ 字符串替换尝试了可靠的方法,但它导致 Point and Click 失败。正如我们今天的软件总监所推测的那样,这可能是由单声道中的错误引起的吗?谢谢。 我不会在 Mono 上编程,尽管尝试一下可能会很有趣 Gasponde 在上面写道:“我们在 Click-Once 部署的应用程序下使用 System.AppDomain.CurrentDomain.FriendlyName 时遇到了问题。”您能否猜测一下 Click-Once 在 .NET 中部署的应用程序可能存在哪些问题?谢谢。 为我在 VS2017 中的示例程序返回 C:\Program Files\dotnet\dotnet.exe。【参考方案15】:

如果您只需要应用程序名称而不需要扩展名,则此方法有效:

Path.GetFileNameWithoutExtension(AppDomain.CurrentDomain.FriendlyName);

【讨论】:

【参考方案16】:

这是你想要的吗:

Assembly.GetExecutingAssembly ().Location

【讨论】:

注意GetExecutingAssembly():如果从库程序集中调用它,它会返回库程序集的名称,该名称与入口程序集(即原始可执行文件)的名称不同。如果使用 GetEntryAssembly(),它会返回实际可执行文件的名称,但如果进程在 WCF 下运行,则会引发异常(诚然,这种情况很少见)。对于最健壮的代码,请使用 Process.GetCurrentProcess().ProcessName。 答案不应该是问题。这是 OP 想要的吗?【参考方案17】:

在 .Net Core(或 Mono)上,当定义进程的二进制文件是 Mono 或 .Net Core (dotnet) 的运行时二进制文件而不是您感兴趣的实际应用程序时,大多数答案将不适用。在这种情况下,使用这个:

var myName = Path.GetFileNameWithoutExtension(System.Reflection.Assembly.GetEntryAssembly().Location);

【讨论】:

GetEntryAssembly() 可以返回 null。【参考方案18】:

对于 Windows 应用程序(表单和控制台),我使用这个:

然后在 VS 中添加对 System.Windows.Forms 的引用:

using System.Windows.Forms;
namespace whatever

    class Program
    
        static string ApplicationName = Application.ProductName.ToString();
        static void Main(string[] args)
        
            ........
        
    

无论我是在 VS 中运行实际的可执行文件还是调试,这对我来说都是正确的。

请注意,它返回的应用程序名称不带扩展名。

约翰

【讨论】:

【参考方案19】:

超级简单,在这里:

Environment.CurrentDirectory + "\\" + Process.GetCurrentProcess().ProcessName

【讨论】:

对于 .NET Core Process.GetCurrentProcess().ProcessName 返回“dotnet”。 当前目录是暂时的,不能作为程序集/可执行文件的位置。【参考方案20】:

如果您在 .NET 6.0 或更高版本中发布单文件应用程序,则可以使用Environment.ProcessPath

【讨论】:

【参考方案21】:

获取路径和名称

System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName

【讨论】:

这重复了this answer 和this answer。

以上是关于如何在 C# 中获取当前可执行文件的名称?的主要内容,如果未能解决你的问题,请参考以下文章

如何将文件扩展名关联到 C# 中的当前可执行文件

C# WinForm获取 当前执行程序路径的几种方法

在 Windows cmd 中,如何在当前目录中运行可执行文件(而不是在 %PATH% 中具有相同名称的可执行文件)而不参考完整路径? [关闭]

c#怎么获取程序当前运行路径

移动当前可执行文件 c#

Linux下如何获取当前可执行文件的文件名