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


355

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


EXE文件是可执行文件(Windows Forms,WPF应用程序)吗?程序可以是桌面应用程序(WinForms,WPF和WinRT-Windows Phone?),Web应用程序,Wcf服务应用程序,Visual Studio插件,Outlook-Word插件,VS中的单元测试(MSTest)或Silverlight应用程序。
Kiquenet 2014年

Answers:


405
System.AppDomain.CurrentDomain.FriendlyName

61
当心接受的答案。System.AppDomain.CurrentDomain.FriendlyName在Click-Once部署的应用程序下使用时遇到了问题。对于我们来说,这将返回“ DefaultDomain ”,而不是原始的exe名称。
Gaspode 2010年

40
我们最终使用了它:string file = object_of_type_in_application_assembly.GetType().Assembly.Location; string app = System.IO.Path.GetFileNameWithoutExtension( file );
Gaspode 2011年

4
可以将FriendlyName设置为任何值。如果您的exe文件带有多个dll,那么获取装配位置也可能不够。此外,如果使用多个AppDomain,则Assembly.GetCallingAssembly()返回null。
user276648

2
@Gaspode:仅仅说Path.GetFileNameWithoutExtension(GetType()。Assembly.Location)会更容易-您无需在当前程序集中指定类型的对象。您可以使用this的GetType,然后甚至不需要说“此”。
vbullinger 2012年

4
这可能是有用的,但应该不会是公认的答案:它是从什么要求很大的不同-它将同时在同样的事情一些情况,但是这完全是另一回事。如果您不是自己编写应用程序,则很可能会返回“我喜欢土豆!” 或您的幽默同事在构建应用程序时在此属性中写入的任何内容!
AnorZaken

236

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()获得与上述相同的结果。


3
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友好名称:UnitTestAdapter:运行测试ApplicationName:
Kiquenet 2014年

“程序”可以是桌面应用程序(WinForms,WPF和WinRT-Windows Phone?),Web应用程序,Wcf服务应用程序,Visual Studio插件,Outlook-Word插件,VS中的单元测试(MSTest)或Silverlight应用程序。例如,如何获取由IIS(而不是IISExpress或WebDevServer)托管的Wcf服务应用程序的服务主机程序集?
Kiquenet 2014年

6
+1我将回答这个问题,因为它以简洁明了的方式提供了您可能需要的所有三种变体。使用无路径或扩展名的裸程序名称对于程序内帮助文本(/?切换)非常有用,因为使用扩展名和路径只会使不必要的混乱。
Synetech

2
切记处置GetCurrentProcess()
Mahmoud Al-Qudsi

Process.GetCurrentProcess().ProcessName()为我返回MyApp.vshost
乔纳森·伍德

106

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

using System;
using System.Diagnostics;

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

36
更好地使用Process.GetCurrentProcess()。MainModule.FileName
KindDragon 2010年

Process.GetCurrentProcess()。MainModule.FileName在Excel插件(ExcelDNA)内完美运行
耳机

10
在Mono运行时上使用时,这种方法将失败。在Mono上运行的应用程序的进程名称将始终是.../bin/mono* nixes或.../mono.exeWindows 上的某些变体。
cdhowie 2012年

1
这应该是公认的答案。当前的AppDomain名称可能与可执行进程名称无关,尤其是当存在多个应用程序域时
Ivan Krivyakov

该方法可能比使用Assembly类慢得多。
欧文·梅耶

99

这样就足够了:

Environment.GetCommandLineArgs()[0];

3
嗯,这返回了(从vs.net运行并使用调试托管工具时),filename.vshost.exe的位置和名称……实际上是此时正在执行的文件)
Frederik Gheysels

13
这对我来说Environment.GetCommandLineArgs()是最好的答案,因为它是argvC / C ++ 的确切C#类似物。
弗雷德里克(Frederick The Fool)愚人节

同意!最佳答案。我需要获取Environment.GetCommandLineArgs()[1];
杰瑞·梁

1
为避免全路径:Path.GetFileNameWithoutExtension(Environment.GetCommandLineArgs()[0])
Nathan 2014年

1
尝试跟踪WCF服务时,此方法效果很好。在本例中,进程名称随iisexpress一起返回。但是此命令为我提供了实际的WCF服务程序集名称。
P.Brian.Mackey

19

这是为我工作的代码:

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

上面所有示例为我提供了带有vshost或正在运行的dll名称的processName。


4
对于那些不知道或错过其他答案的人,Assembly的名称空间是System.Reflection,Path的名称空间是System.IO。
amalgamate 2015年

4
如果应用程序入口点是本机代码而不是程序集,则GetEntryAssembly将返回null。
Emdot,2015年

18

尝试这个:

System.Reflection.Assembly.GetExecutingAssembly()

这将为您返回一个System.Reflection.Assembly实例,其中包含您可能想知道的有关当前应用程序的所有数据。我认为该Location物业可能会得到您所追求的目标。


6
这可能是更安全的使用CodeBase,而不是Location在案件.NET的卷影副本功能处于活动状态。见blogs.msdn.com/suzcook/archive/2003/06/26/...
德克福尔马尔

18
注意GetExecutingAssembly():如果从库程序集调用此函数,它将返回库程序集的名称,该名称与条目程序集的名称(即原始可执行文件)不同。如果使用GetEntryAssembly(),它将返回实际可执行文件的名称,但是如果该进程在WCF下运行,则将引发异常(这很罕见)。有关最可靠的代码,请使用Process.GetCurrentProcess()。ProcessName。
Contango 2010年

@Gravitas:当然不是,任何运行“解释的”可执行文件(例如,使用/ usr / bin / mono)将具有错误的进程名称。此外,ProcessName不适用于Windows服务。如果在库中使用它,请使用GetCallingAssembly。
Stefan Steiger

1
为我工作。返回的Assembly实例GetName()调用的属性Name是您所需要的,并且不包括“ .exe”部分。还在Mono / Linux上进行了测试,具有预期的结果。Assembly.GetName()。Name
Hatoru Hansou 2014年

1
嗯,请注意,即使您使用文件资源管理器手动重命名了可执行文件,返回的字符串也不会改变。虽然Environment.GetCommandLineArgs()[0]随实际的可执行文件名一起更改(当然)。巧合的是,第二种方法对我的特定情况效果更好,因为我希望将数据文件夹命名为实际的可执行文件名。
Hatoru Hansou 2014年

11
System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name;

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


11

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

Path.GetFileName(Application.ExecutablePath)

3
Application驻留在哪个命名空间中。
Jeetendra

6
在Windows Forms应用程序中使用时很有用,但在其他情况下
则不可用

@NineBerry你可能会在感兴趣Application.ExecutablePath源代码
诡异的

@NineBerry看到我的帖子。如果您添加对System.Windows.Forms的引用,则在控制台应用程序中有效。
约翰·


9

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

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

这将确保在Visual Studio中进行调试时以及在Windows中直接运行应用程序时,名称均正确。


2
就我的目的(创建日志文件名),这是最佳答案。如果运行托管进程(例如,服务或Web应用程序),System.AppDomain.CurrentDomain.FriendlyName可以返回带有嵌入式斜杠的难看的GUID-y名称。
Curt

8

不确定或有疑问时,请转圈,尖叫和喊叫。

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");
    }
}

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


2
+1娱乐。:-)但是,除非我要编写一个不了解其环境的通用类库,否则我几乎不会使用此代码(然后,维护要使用的全局状态可能不是一个好主意)的名称)。
Andrey Tarantsov 2013年

@Orwellophile“程序”可以是桌面应用程序(WinForms,WPF和WinRT-Windows Phone?),Web应用程序,Wcf服务应用程序,Visual Studio插件,Outlook-Word插件,VS中的单元测试(MSTest)或Silverlight应用程序。例如,如何获取由IIS(而不是IISExpress或WebDevServer)托管的Wcf服务应用程序的服务主机程序集?任何适用于WinForms,WPF,Web应用程序,Wcf服务应用程序,Visual Studio插件,Outlook-Word插件,VS(MSTest)应用程序中的单元测试的完整代码吗?
Kiquenet 2014年

8
  • System.Reflection.Assembly.GetEntryAssembly().Location 如果未从内存中加载程序集,则返回exe名称的位置。
  • System.Reflection.Assembly.GetEntryAssembly().CodeBase 返回位置作为URL。

经过测试,即使它是在C#库中调用的,它也可以100%工作。
Contango 2010年

1
如果您不在主AppDomain中,则GetEntryAssembly()返回null。
user276648

4

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

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

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


我在Ubuntu Linux 15.10 C ++中尝试了使用realpath的可靠方法,然后替换了STL C ++字符串,这导致Point and Click失败。今天推测我们的软件总监可能是单声道错误引起的吗?谢谢。
弗兰克,

我没有在Mono上编程,尽管尝试可能会很有趣
theMayer

Gasponde在上面写道:“在Click-Once部署的应用程序下使用System.AppDomain.CurrentDomain.FriendlyName时遇到了问题。” 您是否可以猜测.NET中Click-Once部署的应用程序可能会出现什么问题?谢谢。
弗兰克,

在VS2017中为我的示例程序返回C:\ Program Files \ dotnet \ dotnet.exe。
jwdonahue

3

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

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

但是,在调试时,请务必小心,因为最后的示例可能会给调试器的可执行文件名称(取决于附加调试器的方式),而不是其他示例所提供的可执行文件。


4
注意GetExecutingAssembly():如果从库程序集调用此函数,它将返回库程序集的名称,该名称与条目程序集的名称(即原始可执行文件)不同。如果使用GetEntryAssembly(),它将返回实际可执行文件的名称,但是如果该进程在WCF下运行,则将引发异常(这很罕见)。有关最可靠的代码,请使用Process.GetCurrentProcess()。ProcessName。
Contango 2010年

@Gravitas:好点-哇,距离我写这篇文章已有一段时间了!:D我将进行相应的编辑
杰夫·耶茨

Environment.CommandLine至少在Mono / Linux上给出绝对路径,而不是输入的命令行。
机械蜗牛

@Mechanicalsnail:听起来像Mono不太遵循文档。有趣。
杰夫·耶茨

1

这是你想要的吗:

Assembly.GetExecutingAssembly ().Location

4
注意GetExecutingAssembly():如果从库程序集调用此函数,它将返回库程序集的名称,该名称与条目程序集的名称(即原始可执行文件)不同。如果使用GetEntryAssembly(),它将返回实际可执行文件的名称,但是如果该进程在WCF下运行,则将引发异常(这很罕见)。有关最可靠的代码,请使用Process.GetCurrentProcess()。ProcessName。
Contango 2010年

答案不应该是一个问题。那是OP想要的吗?
jwdonahue

1

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

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

1
GetEntryAssembly()可以返回null。
user2864740

1

对于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中运行实际的可执行文件还是调试程序,这对我来说都是正确的。

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

约翰


1

超级简单,在这里:

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

1
对于.NET Core,Process.GetCurrentProcess()。ProcessName返回“ dotnet”。
埃夫让尼·纳博科夫

1
当前目录在时间上是暂时的,不能依赖于程序集/可执行文件的位置。
jwdonahue

1

如果您只需要应用程序名称而不带扩展名,则可以使用此功能:

Path.GetFileNameWithoutExtension(AppDomain.CurrentDomain.FriendlyName);

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.