2009-06-11 2 views
83

Можно создать дубликат:
How do I get the name of the current executable in C#?Как найти текущее имя исполняемого файла?

Исполняемый файл загружает внешнюю библиотеку.
Есть ли способ для библиотеки узнать исполняемый файл вызова?

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

ответ

112
System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName 
+7

Этот, как правило, добавляет «.vhost». в имени файла проблема не возникает при использовании System.Reflection.Assembly.GetEntryAssembly(). Location (см. альтернативный ответ). – Contango

+4

@Contango, вызванный использованием «процесса хостинга Visual Studio» в VS. – LuddyPants

+0

Для модульных испытаний в VS 2012. Имя процесса: 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

7

Я думаю, что это должно быть то, что вы хотите:

System.Reflection.Assembly.GetEntryAssembly().Location 

Это возвращает сборку, которая была впервые загружена при запуске процесса, который, похоже, будет тем, что вы хотите.

GetCallingAssembly не обязательно будет возвращать нужную вам сборку в общем случае, так как она возвращает сборку, содержащую метод, который был выше в стеке вызовов (то есть он может находиться в одной и той же DLL).

+0

я в не уверен в GetCallingAssembly() - не возвращает ли сборку, содержащую вызывающий метод (один в стеке вызовов)? Скорее всего, это скорее библиотека, чем исполняемый файл. –

+0

@ Мартин: Да, ты прав. GetCallingAssembly может работать/быть одобренным в некоторых случаях, но, похоже, он хочет GetEntryAssembly здесь. – Noldorin

70

Если вы хотите исполняемым:

System.Reflection.Assembly.GetEntryAssembly().Location 

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

System.Reflection.Assembly.GetCallingAssembly().Location 

Если вы захотите е только файл имя и не путь, использование:

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

GetEntryAssembly может возвращать null, если вызвано из неуправляемого кода. –

+0

Я не верю, что это не сработает, если исполняемый файл не является .NET-приложением. Например, IIS запускает рабочие процессы (w3wp.exe), которые являются неуправляемыми исполняемыми файлами, которые внутренне разворачивают экземпляр CLR, который выполняет управляемый код. Если вы используете это из управляемого кода, я не верю, что вы получите путь к w3wp.exe. –

40

В дополнение к указанным выше ответов.

я написал следующее 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

Подключаемый модуль ReSharper к Visual Studio подчеркивает

System.Diagnostics.Process.GetCurrentProcess().MainModule 

как возможно Система.NullReferenceException. Если вы посмотрите на документацию MainModule, вы обнаружите, что это свойство может также вызывать NotSupportedException, PlatformNotSupportedException и InvalidOperationException.

Метод GetEntryAssembly также не на 100% безопасен. MSDN:

Метод GetEntryAssembly может возвращать нуль, когда управляемая сборка была загружена из неуправляемого приложения. Например, если неуправляемое приложение создает экземпляр COM-компонента, написанного в C# , вызов метода GetEntryAssembly из компонента C# возвращает 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"); 
+1

Метод GetEntryAssembly также возвращает значение null, если вы используете приложение-службу WCF в режиме отладки в IIS. Это, по общему признанию, редкая ситуация, с которой столкнулся только разработчик. – Contango

+0

Assembly.GetEntryAssembly() для меня null, когда я использую Addin VS 2008. System.Diagnostics.Process.GetCurrentProcess().MainModule - файл devenv.exe, но не моя DLL с Addin. и я не знаю, получить сборку (из Addin) из другой сборки, использующей addin. – Kiquenet

+0

1) Если A.exe использует B.dll, а B.dll использует C.dll, что происходит, если этот код находится в C.dll ?. 2) AppDomain может быть EXE-приложением, веб-приложением, модульным тестовым приложением, Addin Visual Studio и «Silverlight App» (?). Может быть, интересное полное решение для всех случаев. – Kiquenet

2

Это один не был включен:

System.Windows.Forms.Application.ExecutablePath; 

~ Джо

+1

Мне всегда казалось немым, что пространство имен Forms имеет класс Application ... это абсолютно не связано с Forms. – Nyerguds

+0

LOL - да, я тоже не использую. Нечетное место, чтобы найти его. – jp2code

+4

Собственно, класс Application связан исключительно с формами, поскольку метод Application.Run - это то, что инициирует цикл сообщений главного окна, который обрабатывает все события окна (a.k.a. «form»). Он также содержит DoEvents(), который позволяет окну обрабатывать ожидающие события события внутри обработчика. Все это должно быть знакомо всем, кто запрограммировал API Win32 до изобретения .NET. – Triynko

Смежные вопросы