Как я могу получить путь к приложению в консольном приложении .NET?

Как найти путь к приложению в консольном приложении?

В Windows Forms я могу использовать Application.StartupPathтекущий путь, но, похоже, он недоступен в консольном приложении.

7.05.2009 23:05:09
Вы устанавливаете .NET Framework на целевой машине (клиент, разработчик)? если ваш ответ верен; Таким образом, вы можете добавить ссылку на System.Windows.Forms.dll и использовать Application.StartupPath! Это лучший способ, если вы хотите отказаться от дальнейших исключений в будущем!
Ehsan Mohammadi 13.03.2015 02:23:24
AppDomain.BaseDirectory является каталогом приложения. Имейте в виду, что приложение может вести себя по-разному в VS env и Win env. Но AppDomain должен быть не таким как application.path, но я надеюсь, что это не только для IIS.
Mertuarez 29.04.2016 13:11:05
26 ОТВЕТОВ
РЕШЕНИЕ

System.Reflection.Assembly.GetExecutingAssembly(), 1Location

Добавьте к этому, System.IO.Path.GetDirectoryNameесли все, что вам нужно, это каталог.

1 Согласно комментарию Mr.Mindor:
System.Reflection.Assembly.GetExecutingAssembly().Location возвращает место, где в данный момент находится исполняющая сборка, которое может быть, а может и не быть, где находится сборка, когда не выполняется. В случае теневых копий сборок вы получите путь во временный каталог. System.Reflection.Assembly.GetExecutingAssembly().CodeBaseвернет «постоянный» путь сборки.

1169
14.03.2019 08:48:54
System.Reflection.Assembly.GetExecutingAssembly (). Location возвращает местоположение, в котором в данный момент находится исполняющая сборка , что может быть или не быть в том месте, где находится сборка, когда она не выполняется. В случае теневых копий сборок вы получите путь во временный каталог. System.Reflection.Assembly.GetExecutingAssembly (). CodeBase вернет « вас устраивают » путь сборки.
Mr.Mindor 14.10.2011 18:13:51
@SamGoldberg: Это зависит от того, как он используется: stackoverflow.com/q/1068420/391656 . Или вы можете ... новый Uri (System.Reflection.Assembly.GetExecutingAssembly (). CodeBase) .LocalPath
Mr.Mindor 30.08.2012 21:31:34
GetExecutingAssemblyвозвращает сборку, которая содержит код, который выполняется в данный момент . Это не обязательно сборка консоли .exe . Это может быть сборка, которая была загружена из совершенно другого места. Вам придется использовать GetEntryAssembly! Также обратите внимание, что CodeBaseэто не может быть установлено, когда сборка находится в GAC. Лучшая альтернатива AppDomain.CurrentDomain.BaseDirectory.
bitbonk 6.08.2015 14:41:20
Пожалуйста, напишите код в 4 пробела, чтобы его было удобно копировать
fnc12 27.11.2016 16:06:56
если вы вызываете dll, System.Reflection.Assembly.GetExecutingAssembly (). CodeBase получит «file: /// C: /Windows/Microsoft.NET/Framework64/v4.0.30319/mscorlib.dll»
raidsan 26.12.2017 05:03:07

Возможно, вы хотите сделать это:

System.IO.Path.GetDirectoryName(
    System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)
29
20.11.2013 15:41:04

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

AppDomain.CurrentDomain.BaseDirectory
403
22.11.2013 12:39:53
Не используйте это. BaseDirectory может быть установлен во время выполнения. Это не гарантируется быть правильным (как принятый ответ).
usr 15.07.2012 20:29:29
+1 Это, вероятно, тот ответ, который вам нужен, поскольку он компенсирует теневое копирование.
George Mauer 8.05.2014 23:42:33
@usr Что заставляет вас думать, что это BaseDirectoryможет быть установлено во время выполнения? У него есть только добытчик.
bitbonk 6.08.2015 14:43:16
@bitbonk это может быть установлено во время создания домена приложения.
usr 6.08.2015 14:43:52
Разве BaseDirectory нельзя изменить в файле * .lnk, в поле «Начать с:»?
Alexander 15.06.2016 14:46:39

Возможно, немного поздно, но это стоит упомянуть:

Environment.GetCommandLineArgs()[0];

Или правильнее получить только путь к каталогу:

System.IO.Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]);

Редактировать:

Довольно много людей отметили, что GetCommandLineArgsне гарантируется возвращение имени программы. См . Первое слово в командной строке - это имя программы только по соглашению . В статье утверждается, что «Хотя очень немногие программы для Windows используют эту причуду (я сам о себе не знаю)». Так что можно «подделать» GetCommandLineArgs, но речь идет о консольном приложении. Консольные приложения обычно бывают быстрыми и грязными. Так что это вписывается в мою философию KISS.

82
27.08.2015 09:17:55
@usr Ситуация, на которую вы ссылаетесь, носит исключительно теоретический характер. В контексте консольного приложения не имеет смысла использовать какой-либо другой метод. Будь проще!
Steve Mc 21.07.2012 10:32:04
@usr mmm - просмотр столбца cmdline taskmgr подтверждает то, что я говорю. Несколько системных служб только с именем exe. Ничего. Я пытаюсь сказать, что при разработке консольного приложения нет необходимости делать вещи более сложными, чем они должны быть. Особенно, когда у нас уже есть информация. Теперь, если вы запускаете консольное приложение таким образом, чтобы обмануть GetCommandLineArgs, то вы уже перепрыгиваете через обручи, и вам, возможно, придется спросить себя, является ли консольное приложение правильным способом.
Steve Mc 22.07.2012 08:54:15
Ваше «простое» решение включает два вызова метода. «Сложное» решение включает в себя два вызова метода. Нет практической разницы - за исключением того, что «простое» решение может дать вам неправильный ответ при определенных обстоятельствах, которые не находятся под вашим контролем при написании программы. Зачем рисковать? Используйте два других вызова метода, и ваша программа не будет более сложной, но будет более надежной.
Chris 22.02.2013 14:53:03
Сработал для моего сценария, другие решения не сработали, так что спасибо за предоставление другой альтернативы :-) Я использовал ReSharper Runner для запуска MS Unit test, и код, который я тестировал, нуждался в конкретной .dll, чтобы быть в каталоге выполнения. ..and Assembly.GetExecutingDirectory () странно возвращает другой результат.
wallismark 4.03.2015 06:27:16
@ Крис - в защиту этого ответа. Это работает для модульных тестов, решение GetEntryAssembly - нет, потому что GetEntryAssembly возвращает ноль. Ответы, которые предлагают GetExecutingAssembly, являются поддельными, потому что они возвращают исполняемый файл, только если исполняемая сборка является исполняемым файлом. Это не простое, но правильное решение.
mark 13.04.2018 13:16:23

Для всех, кто интересуется веб-приложениями asp.net. Вот мои результаты 3 разных методов

protected void Application_Start(object sender, EventArgs e)
{
  string p1 = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
  string p2 = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath;
  string p3 = this.Server.MapPath("");
  Console.WriteLine("p1 = " + p1);
  Console.WriteLine("p2 = " + p2);
  Console.WriteLine("p3 = " + p3);
}

результат

p1 = C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\a897dd66\ec73ff95\assembly\dl3\ff65202d\29daade3_5e84cc01
p2 = C:\inetpub\SBSPortal_staging\
p3 = C:\inetpub\SBSPortal_staging

приложение физически запускается из «C: \ inetpub \ SBSPortal_staging», поэтому первое решение определенно не подходит для веб-приложений.

44
6.10.2011 19:42:16

У вас есть два варианта поиска каталога приложения, который вы выберете, будет зависеть от вашей цели.

// to get the location the assembly is executing from
//(not necessarily where the it normally resides on disk)
// in the case of the using shadow copies, for instance in NUnit tests, 
// this will be in a temp directory.
string path = System.Reflection.Assembly.GetExecutingAssembly().Location;

//To get the location the assembly normally resides on disk or the install directory
string path = System.Reflection.Assembly.GetExecutingAssembly().CodeBase;

//once you have the path you get the directory with:
var directory = System.IO.Path.GetDirectoryName(path);
166
9.02.2020 19:20:04
Просто хотел сказать, очевидно, что существует гораздо больше, чем 2 варианта по тому, сколько других вариантов опубликовано ...
vapcguy 27.06.2016 17:23:27
Если все, что вы пытаетесь сделать с указанным путем, не поддерживает формат URI, используйтеvar localDirectory = new Uri(directory).LocalPath;
Okuma.Scott 27.09.2016 13:25:19
Это просто неправильно. Какой исполняемый файл не является сборкой .NET вообще? Правильный ответ - проверить среду и проверить командную строку.
mark 13.04.2018 13:17:27
@ Ukuma.Scott Это не работает, если путь содержит & или #
MatsW 7.02.2019 09:12:11

Assembly.GetEntryAssembly().Location или Assembly.GetExecutingAssembly().Location

Используйте в сочетании с, System.IO.Path.GetDirectoryName()чтобы получить только каталог.

Пути от GetEntryAssembly()и GetExecutingAssembly()могут отличаться, хотя в большинстве случаев каталог будет одинаковым.

При этом GetEntryAssembly()вы должны знать, что это может вернуться, nullесли модуль ввода неуправляем (т.е. исполняемый файл C ++ или VB6). В этих случаях можно использовать GetModuleFileNameиз Win32 API:

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetModuleFileName(HandleRef hModule, StringBuilder buffer, int length);
5
11.06.2012 15:40:02

Ответ выше был на 90% от того, что мне было нужно, но вместо обычного пути я вернул Uri.

Как объясняется в сообщении на форумах MSDN, Как преобразовать путь URI в обычный путь к файлу? Я использовал следующее:

// Get normal filepath of this assembly's permanent directory
var path = new Uri(
    System.IO.Path.GetDirectoryName(
        System.Reflection.Assembly.GetExecutingAssembly().CodeBase)
    ).LocalPath;
42
13.04.2012 20:20:44
это также хорошо работает, если рассматриваемый exe-файл является службой Windows и текущий каталог возвращает C: \ Windows \ system32. Приведенный выше код возвращает фактическое местоположение exe
DaImTo 20.02.2015 11:32:49
За исключением случаев, когда вы попытаетесь сделать что-то подобное File.CreateDirectory(path), это даст вам исключение, что он не разрешает пути URI ...
vapcguy 27.06.2016 17:26:20
К сожалению, это не работает для путей, которые содержат идентификатор фрагмента ( #символ). Идентификатор и все, что следует за ним, усекается из полученного пути.
bgfvdu3w 2.02.2018 08:07:31
Почему бы вам не поменяться new Uriи System.IO.Path.GetDirectoryName? Это дает вам нормальную строку пути вместо Uri.
Timo 5.11.2018 16:50:33
Я считаю это лучшим. Этот же подход надежно работал для меня в любой среде. На производстве, локальная отладка, модульное тестирование ... Хотите открыть файл контента, который вы включили («контент - скопируйте, если новее») в модульный тест? Это здесь.
Timo 5.11.2018 16:54:33

Вы можете создать имя папки как Ресурсы в рамках проекта, используя Solution Explorer, затем вы можете вставить файл в Ресурсы.

private void Form1_Load(object sender, EventArgs e) {
    string appName = Environment.CurrentDirectory;
    int l = appName.Length;
    int h = appName.LastIndexOf("bin");
    string ll = appName.Remove(h);                
    string g = ll + "Resources\\sample.txt";
    System.Diagnostics.Process.Start(g);
}
-5
28.05.2012 11:59:13
Использование Environment.CurrentDirectory очень неправильно, не используйте это! этот путь может измениться во время выполнения. Даже при запуске это недетерминировано.
usr 15.07.2012 20:28:07

Вы можете использовать это вместо этого.

System.Environment.CurrentDirectory
23
16.09.2015 13:34:02
Это получит папку исполняемого файла, хотя
Iain 15.11.2012 20:27:08
Это можно изменить несколькими способами (настройки ярлыков и т. Д.) ... лучше НЕ использовать это.
Yousha Aleayoub 19.11.2019 20:09:03

Я использую это, если exe-файл должен вызываться двойным щелчком по нему

var thisPath = System.IO.Directory.GetCurrentDirectory();
7
10.09.2013 22:07:58
Это не правильно, потому что вы можете получить случайные каталоги в результате.
amuliar 3.07.2013 10:58:33
эта команда возвращает Environment.CurrentDirectory, который может быть изменен во время выполнения на любой путь, поэтому он не является надежным решением.
Yury Kozlov 11.01.2019 03:41:55

я использовал

System.AppDomain.CurrentDomain.BaseDirectory

когда я хочу найти путь относительно папки приложений. Это работает как для ASP.Net, так и для приложений winform. Также не требуется никаких ссылок на сборки System.Web.

7
7.04.2014 16:57:01

Для консольных приложений вы можете попробовать это:

System.IO.Directory.GetCurrentDirectory();

Вывод (на моей локальной машине):

c: \ users \ xxxxxxx \ Documents \ visual studio 2012 \ Проекты \ ImageHandler \ GetDir \ bin \ Debug

Или вы можете попробовать (в конце есть дополнительная обратная косая черта):

AppDomain.CurrentDomain.BaseDirectory

Вывод:

c: \ users \ xxxxxxx \ Documents \ visual studio 2012 \ Проекты \ ImageHandler \ GetDir \ bin \ Debug \

19
18.06.2014 22:03:32
«Значение BaseDirectoryможет быть установлено во время выполнения. Оно НЕ гарантированно будет правильным»,
Yousha Aleayoub 19.11.2019 20:09:58
AppDomain.CurrentDomain.BaseDirectory

Решит проблему, ссылаясь на сторонние справочные файлы с установочными пакетами.

4
14.07.2014 06:43:49
Этот ответ уже предлагался 5 лет назад, даже не раз.
P-L 14.08.2014 19:05:31

Я имею в виду, почему не метод ap / invoke?

    using System;
    using System.IO;
    using System.Runtime.InteropServices;
    using System.Text;
    public class AppInfo
    {
            [DllImport("kernel32.dll", CharSet = CharSet.Auto, ExactSpelling = false)]
            private static extern int GetModuleFileName(HandleRef hModule, StringBuilder buffer, int length);
            private static HandleRef NullHandleRef = new HandleRef(null, IntPtr.Zero);
            public static string StartupPath
            {
                get
                {
                    StringBuilder stringBuilder = new StringBuilder(260);
                    GetModuleFileName(NullHandleRef, stringBuilder, stringBuilder.Capacity);
                    return Path.GetDirectoryName(stringBuilder.ToString());
                }
            }
    }

Вы бы использовали его так же, как Application.StartupPath:

    Console.WriteLine("The path to this executable is: " + AppInfo.StartupPath + "\\" + System.Diagnostics.Process.GetCurrentProcess().ProcessName + ".exe");
6
24.07.2014 20:56:42
Зачем p / invoke, когда для этого так много .NET?
ProfK 3.03.2015 18:57:32
@ user3596865, поскольку требует жесткой зависимости от Windows и несовместим с DNX или Mono. И, возможно, в будущих версиях Windows произойдет серьезное изменение. Итак, еще раз: почему мы должны использовать pinvoke здесь?
Ben 20.01.2016 10:05:31

в VB.net

My.Application.Info.DirectoryPath

у меня работает (Тип приложения: Библиотека классов). Не уверен насчет C # ... Возвращает путь без имени файла в виде строки

5
16.05.2018 02:45:23

Вот надежное решение, которое работает с 32-битными и 64-битными приложениями.

Добавьте эти ссылки:

использование System.Diagnostics;

использование System.Management;

Добавьте этот метод в ваш проект:

public static string GetProcessPath(int processId)
{
    string MethodResult = "";
    try
    {
        string Query = "SELECT ExecutablePath FROM Win32_Process WHERE ProcessId = " + processId;

        using (ManagementObjectSearcher mos = new ManagementObjectSearcher(Query))
        {
            using (ManagementObjectCollection moc = mos.Get())
            {
                string ExecutablePath = (from mo in moc.Cast<ManagementObject>() select mo["ExecutablePath"]).First().ToString();

                MethodResult = ExecutablePath;

            }

        }

    }
    catch //(Exception ex)
    {
        //ex.HandleException();
    }
    return MethodResult;
}

Теперь используйте это так:

int RootProcessId = Process.GetCurrentProcess().Id;

GetProcessPath(RootProcessId);

Обратите внимание, что если вы знаете идентификатор процесса, то этот метод вернет соответствующий ExecutePath.

Дополнительно для заинтересованных:

Process.GetProcesses() 

... даст вам массив всех запущенных в данный момент процессов и ...

Process.GetCurrentProcess()

... даст вам текущий процесс, вместе с их информацией, например, Id и т. д., а также ограниченным контролем, например, Kill и т. д. *

-1
9.03.2016 10:56:48

Вы можете просто добавить в свой проект ссылки, System.Windows.Formsа затем использовать System.Windows.Forms.Application.StartupPath как обычно.

Таким образом, не нужно более сложных методов или использования отражения.

9
9.05.2016 12:27:58
Я использовал это, и это работает хорошо. Но однажды я использовал этот метод в своем проекте модульного тестирования. И, конечно, это не удалось, потому что он искал мой файл в C: \ PROGRAM FILES (X86) \ MICROSOFT VISUAL STUDIO 14.0 \ COMMON7 \ IDE \ COMMONEXTENSIONS \ MICROSOFT \ TESTWINDOW
ainasiart 31.08.2017 19:09:37
@ainasiart, так как мне заставить это работать во время модульного тестирования?
Nicholas Siegmundt 9.12.2019 18:42:53

Я использовал этот код и получил решение.

AppDomain.CurrentDomain.BaseDirectory
14
31.01.2017 08:17:40

Ни один из этих методов не работает в особых случаях, таких как использование символической ссылки на exe, они возвращают местоположение ссылки, а не фактический exe.

Поэтому можно использовать QueryFullProcessImageName, чтобы обойти это:

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Diagnostics;

internal static class NativeMethods
{
    [DllImport("kernel32.dll", SetLastError = true)]
    internal static extern bool QueryFullProcessImageName([In]IntPtr hProcess, [In]int dwFlags, [Out]StringBuilder lpExeName, ref int lpdwSize);

    [DllImport("kernel32.dll", SetLastError = true)]
    internal static extern IntPtr OpenProcess(
        UInt32 dwDesiredAccess,
        [MarshalAs(UnmanagedType.Bool)]
        Boolean bInheritHandle,
        Int32 dwProcessId
    );
}

public static class utils
{

    private const UInt32 PROCESS_QUERY_INFORMATION = 0x400;
    private const UInt32 PROCESS_VM_READ = 0x010;

    public static string getfolder()
    {
        Int32 pid = Process.GetCurrentProcess().Id;
        int capacity = 2000;
        StringBuilder sb = new StringBuilder(capacity);
        IntPtr proc;

        if ((proc = NativeMethods.OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, pid)) == IntPtr.Zero)
            return "";

        NativeMethods.QueryFullProcessImageName(proc, 0, sb, ref capacity);

        string fullPath = sb.ToString(0, capacity);

        return Path.GetDirectoryName(fullPath) + @"\";
    }
}
2
5.02.2017 08:54:41

Попробуйте эту простую строку кода:

 string exePath = Path.GetDirectoryName( Application.ExecutablePath);
2
20.11.2017 09:42:03

Если вы ищете .NET Core совместимый способ, используйте

System.AppContext.BaseDirectory

Это было представлено в .NET Framework 4.6 и .NET Core 1.0 (и .NET Standard 1.3). Смотрите: Свойство AppContext.BaseDirectory .

Согласно этой странице ,

Это предпочтительная замена для AppDomain.CurrentDomain.BaseDirectory в .NET Core

20
2.02.2018 02:14:02
см. также github.com/dotnet/runtime/issues/13051 для автономных консольных приложений dotnet. Рекомендация здесь - использоватьProcess.GetCurrentProcess().MainModule.FileName
Gavin 2.03.2020 08:46:54

Я не видел, чтобы кто-нибудь преобразовал LocalPath, предоставленный отражением .Net Core, в пригодный для использования путь System.IO, так что вот моя версия.

public static string GetApplicationRoot()
{
   var exePath = new Uri(System.Reflection.
   Assembly.GetExecutingAssembly().CodeBase).LocalPath;

   return new FileInfo(exePath).DirectoryName;

}

Это вернет полный путь в формате «C: \ xxx \ xxx» туда, где находится ваш код.

0
7.02.2018 19:03:49

Следующая строка даст вам путь к приложению:

var applicationPath = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName)

Вышеупомянутое решение работает должным образом в следующих ситуациях:

  • простое приложение
  • в другом домене, где Assembly.GetEntryAssembly () будет возвращать ноль
  • DLL загружается из встроенных ресурсов как байтовый массив и загружается в домен приложений как Assembly.Load (byteArrayOfEmbeddedDll)
  • со mkbundleсвязками Моно (другие методы не работают)
7
6.10.2019 10:57:38
Под отладчиком на Linux это возвращает: / usr / share / dotnet
Vladimir 12.03.2020 07:50:39

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

Различные способы получить путь к исполняемому приложению

0
3.04.2018 07:26:38

Другое решение использует относительные пути, указывающие на текущий путь:

Path.GetFullPath(".")
1
22.06.2019 21:34:03
Это получает текущий каталог, а не местоположение запуска EXE.
tenfour 10.03.2020 08:20:55