Как я могу получить имя текущего исполняемого файла в C #?

356

Я хочу получить имя запущенной в данный момент программы, то есть имя исполняемой программы. В C / C ++ вы получаете его args[0].

Йоаким
источник
Исполняемый файл является EXE-файлом (Windows Forms, приложения WPF)? Программа может быть настольным приложением (WinForms, WPF и WinRT-Windows Phone?), Веб-приложением, приложением службы Wcf, надстройкой Visual Studio, надстройкой Outlook-Word, модульным тестом в VS (MSTest) или приложением Silverlight.
Kiquenet

Ответы:

406
System.AppDomain.CurrentDomain.FriendlyName
Стивен А. Лоу
источник
61
Остерегайтесь принятого ответа. У нас были проблемы с использованием System.AppDomain.CurrentDomain.FriendlyNameприложений, развернутых в Click-Once. Для нас это возвращает DefaultDomain , а не оригинальное имя exe.
Gaspode
40
Мы использовали это в конце концов:string file = object_of_type_in_application_assembly.GetType().Assembly.Location; string app = System.IO.Path.GetFileNameWithoutExtension( file );
Гаспод
4
FriendlyName может быть установлен на что угодно. Также получение места сборки может быть недостаточно, если у вас есть exe с несколькими dll. Кроме того, если вы используете несколько доменов приложений, Assembly.GetCallingAssembly () возвращает значение null.
user276648
2
@Gaspode: было бы проще просто сказать Path.GetFileNameWithoutExtension (GetType (). Assembly.Location) - вам не нужно указывать объект типа в текущей сборке. Вы можете использовать GetType этого, и тогда вам даже не нужно говорить «это».
vbullinger
4
Это может быть полезно, но это не должен быть принятый ответ: он сильно отличается от того, о чем просили - в некоторых ситуациях это будет совпадать , но это совсем другое. Если бы вы сами не написали заявление, оно вполне могло бы вернуть: «Мне нравится картошка!» или что еще ваш юмористический коллега написал в это свойство, когда создавал приложение!
AnorZaken
237

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, веб-приложением, модульным тестовым приложением, 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.exe \en.x.engine MainModule.ModuleName: vstest.executionengine.x86.exe FriendlyName: UnitTestAdapter: Выполнение теста ApplicationName:
Kiquenet
«Программа» может быть настольным приложением (WinForms, WPF и WinRT-Windows Phone?), Веб-приложением, приложением службы Wcf, надстройкой Visual Studio, надстройкой Outlook-Word, модульным тестом в VS (MSTest) или приложением Silverlight , Например, как получить сборку узла службы для приложения службы Wcf, размещенного в IIS, а не в IISExpress или WebDevServer?
Kiquenet
6
+1 Я собираюсь пойти с этим ответом, потому что он предоставляет все три варианта, которые могут вам понадобиться, простым и понятным способом. Использование простого имени программы без пути или расширения очень полезно для текста справки в программе ( /?переключатель), потому что использование расширения и пути просто загромождает его без необходимости.
Synetech
2
Не забудьте распоряжаться результатомGetCurrentProcess()
Махмуд Аль-Кудси
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
Process.GetCurrentProcess (). MainModule.FileName прекрасно работает из надстройки Excel (ExcelDNA)
наушники
10
Этот подход потерпит неудачу при использовании в среде исполнения Mono; имя процесса для приложений, работающих в Mono, всегда будет некоторым вариантом .../bin/mono* nixes или .../mono.exeWindows.
cdhowie
1
Это должен быть принятый ответ. Текущее имя домена приложения может не иметь ничего общего с именем исполняемого процесса, особенно при наличии нескольких доменов приложений
Иван Кривяков
Этот метод может быть значительно медленнее, чем игра с классом Assembly.
Эрвин Майер
99

Этого должно быть достаточно:

Environment.GetCommandLineArgs()[0];
Джеймс Б
источник
3
Хм, это возвращает (при запуске из vs.net и использовании хоста отладки) местоположение и имя файла filename.vshost.exe ... это действительно файл, который выполняется в это время)
Фредерик Гэйселс
13
Это лучший ответ для меня, потому что Environment.GetCommandLineArgs()это точный аналог C # argvиз C / C ++.
Фредерик Дурак
Согласовано! лучший ответ. У меня есть необходимость получить Environment.GetCommandLineArgs () [1];
Джерри Лян
1
Чтобы избежать полного пути:Path.GetFileNameWithoutExtension(Environment.GetCommandLineArgs()[0])
Натан
1
Это хорошо работает при попытке отследить службы WCF. Имя процесса возвращается с iisexpress в моем случае. Но эта команда дает мне фактическое имя сборки службы WCF.
P.Brian.Mackey
19

Это код, который работал для меня:

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

Все приведенные выше примеры дали мне имя процесса с vshost или имя запущенной DLL.

Таль Сегал
источник
4
Для тех, кто не знает или пропустил его в других ответах, пространством имен для Assembly является System.Reflection, а пространством имен для Path является System.IO.
объединение
4
GetEntryAssembly будет возвращать ноль, если точка входа приложения находится в собственном коде, а не в сборке.
Эмдот
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.
Контанго
@Gravitas: Конечно, нет, любой исполняемый файл с «интерпретацией», например, с / usr / bin / mono, будет иметь неправильное имя процесса. Также ProcessName не будет работать со службами Windows. Если вы используете его в библиотеке, используйте GetCallingAssembly.
Стефан Штайгер
1
Работал на меня. Имя свойства возвращенного вызова GetName () экземпляра Assembly - это то, что вам нужно, и оно не содержит часть «.exe». Также тестируется на Mono / Linux с ожидаемым результатом. Assembly.GetName (). Имя
Hatoru Hansou
1
Хм, обратите внимание, что возвращаемая строка не изменится, даже если вы переименуете исполняемый файл вручную с помощью проводника. В то время как Environment.GetCommandLineArgs () [0] изменяется вместе с фактическим исполняемым именем файла (конечно). По совпадению, второй метод оказался лучше для моей конкретной ситуации, так как я хочу, чтобы папка данных была названа в качестве фактического исполняемого имени файла.
Hatoru Hansou
11
System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.Name;

даст вам FileName вашего приложения, как; "MyApplication.exe"

Теоман Шипахи
источник
11

Почему никто не предложил это, это просто.

Path.GetFileName(Application.ExecutablePath)
Xmen
источник
3
Какое пространство имен делает Application.
Джитендра
6
Это полезно, когда внутри приложения Windows Forms, но не иначе
NineBerry
@NineBerry Вы могли бы быть заинтересованы в Application.ExecutablePath«S исходный код .
Жуткий
@NineBerry Смотрите мой пост. Это работает в консольных приложениях, если вы добавляете ссылку на System.Windows.Forms.
Джон
9

Если вам нужно имя программы для настройки правила брандмауэра, используйте:

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

Это обеспечит правильность имени как при отладке в VisualStudio, так и при запуске приложения непосредственно в Windows.

Марк Уэбел
источник
2
Для моих целей (создание имени файла журнала) это лучший ответ. При запуске размещенного процесса (скажем, службы или веб-приложения) System.AppDomain.CurrentDomain.FriendlyName может вернуть некрасивое имя GUID-y со встроенными слешами.
Курт
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");
    }
}

Я не могу утверждать, что проверил каждую опцию, но она не делает ничего глупого, как возврат vhost во время сеансов отладки.

Orwellophile
источник
2
+1 для развлечения. :-) Я бы вряд ли использовал этот код, если только я не пишу действительно универсальную библиотеку, которая не имеет представления о своей среде (и тогда, вероятно, не будет хорошей идеей поддерживать какое-либо глобальное состояние, которое вы собираетесь использовать имя для).
Андрей Таранцов
@ Orwellophile «Программа» может быть настольным приложением (WinForms, WPF и WinRT-Windows Phone?), Веб-приложением, приложением службы Wcf, надстройкой Visual Studio, надстройкой Outlook-Word, модульным тестом в VS (MSTest) или Приложение Silverlight. Например, как получить сборку узла службы для приложения службы Wcf, размещенного в IIS, а не в IISExpress или WebDevServer? Любой полный код, действительный для WinForms, WPF, веб-приложения, приложения-службы Wcf, надстройки Visual Studio, надстройки Outlook-Word, модульного тестирования в приложениях VS (MSTest)?
Kiquenet
8
  • System.Reflection.Assembly.GetEntryAssembly().Location возвращает расположение имени exe, если сборка не загружена из памяти.
  • System.Reflection.Assembly.GetEntryAssembly().CodeBase возвращает местоположение как URL.
langpavel
источник
Протестировано, это работает на 100%, даже если оно вызывается из библиотеки C #.
Контанго
1
GetEntryAssembly () возвращает ноль, если вы не находитесь в основном домене приложения.
user276648
4

Если вы ищете полную информацию о пути вашего исполняемого файла, надежный способ сделать это - использовать следующее:

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

Это устраняет любые проблемы с dll, vshost и т. Д.

theMayer
источник
Я попробовал ваш надежный способ в Ubuntu Linux 15.10 C ++ с использованием realpath, за которым следовала замена строки STL C ++, и это привело к сбою Point and Click. Может ли это быть вызвано ошибкой в ​​моно, как сегодня предположил наш директор по программному обеспечению? Спасибо.
Фрэнк
Я не программирую на Mono, хотя это может быть интересно
TheMayer
Гаспонд писал выше, что «у нас были проблемы с использованием System.AppDomain.CurrentDomain.FriendlyName в приложениях, развернутых нажатием одной кнопки». Не могли бы вы догадаться, какие могут быть проблемы с приложениями, развернутыми по технологии Click-Once в .NET? Спасибо.
Фрэнк
Возвращает C: \ Program Files \ dotnet \ dotnet.exe для моей программы-примера в VS2017.
19
3

Вы можете использовать Environment.GetCommandLineArgs()для получения аргументов и Environment.CommandLineдля получения фактической командной строки, как введено.

Также вы можете использовать Assembly.GetEntryAssembly()или Process.GetCurrentProcess().

Однако при отладке следует соблюдать осторожность, поскольку в этом последнем примере может быть указано имя исполняемого файла вашего отладчика (в зависимости от того, как вы присоединяете отладчик), а не свой исполняемый файл, как и другие примеры.

Джефф Йейтс
источник
4
Остерегайтесь GetExecutingAssembly (): если вы вызываете это из сборки библиотеки, она возвращает имя сборки библиотеки, которая отличается от имени сборки записи (то есть исходного исполняемого файла). Если вы используете GetEntryAssembly (), он возвращает имя фактического исполняемого файла, но выдает исключение, если процесс выполняется под WCF (по общему признанию, редкая ситуация). Для наиболее надежного кода используйте Process.GetCurrentProcess (). ProcessName.
Контанго
@Gravitas: хороший момент - вау, это было давно, так как я написал это! : D Я буду редактировать соответственно
Джефф Йейтс
Environment.CommandLineдает абсолютный путь, а не введенную командную строку, по крайней мере, в Mono / Linux.
Механическая улитка
@Mechanicalsnail: похоже, что Mono не совсем соответствует документации. Интересно.
Джефф Йейтс
1

Это то, что вы хотите:

Assembly.GetExecutingAssembly ().Location
Фредерик Гейсель
источник
4
Остерегайтесь GetExecutingAssembly (): если вы вызываете это из сборки библиотеки, она возвращает имя сборки библиотеки, которая отличается от имени сборки записи (то есть исходного исполняемого файла). Если вы используете GetEntryAssembly (), он возвращает имя фактического исполняемого файла, но выдает исключение, если процесс выполняется под WCF (по общему признанию, редкая ситуация). Для наиболее надежного кода используйте Process.GetCurrentProcess (). ProcessName.
Контанго
Ответ не должен быть вопросом. Этого хотел ОП?
19
1

В .Net Core (или Mono) большинство ответов не будут применяться, если двоичным файлом, определяющим процесс, является исполняемый двоичный файл Mono или .Net Core (dotnet), а не ваше собственное приложение, которое вас интересует. В этом случае , использовать этот:

var myName = Path.GetFileNameWithoutExtension(System.Reflection.Assembly.GetEntryAssembly().Location);
Тобиас
источник
1
GetEntryAssembly()может вернуть ноль.
user2864740
1

Для приложений Windows (формы и консоли) я использую это:

Добавьте ссылку на System.Windows.Forms в VS затем:

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);
RJN
источник