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

770

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

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

  • 5
    Вы устанавливаете .NET Framework на целевой машине (клиент, разработчик)? если ваш ответ верен; Таким образом, вы можете добавить ссылку на System.Windows.Forms.dll и использовать Application.StartupPath! Это лучший способ, если вы хотите отказаться от дальнейших исключений в будущем!
  • 0
    AppDomain.BaseDirectory является каталогом приложения. Имейте в виду, что приложение может вести себя по-разному в VS env и Win env. Но AppDomain должен быть не таким, как application.path, но я надеюсь, что это не только для IIS.
Теги:
console-application
console

25 ответов

1035
Лучший ответ

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

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

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

  • 0
    К вашему сведению, когда я запускаю это из веб-приложения IIS, я получаю такой результат ... C: \ Windows \ Microsoft.NET \ Framework64 \ v4.0.30319 \ Временные файлы ASP.NET \ root \ a897dd66 \ ec73ff95 \ assembly \ dl3 \ ff65202d \ e9a4e8db_5d84cc01
  • 233
    System.Reflection.Assembly.GetExecutingAssembly (). Location возвращает местоположение, в котором в данный момент находится исполняющая сборка, что может быть или не быть в том месте, где находится сборка, когда она не выполняется. В случае сборок теневого копирования вы получите путь во временный каталог. System.Reflection.Assembly.GetExecutingAssembly (). CodeBase вернет «» пути вас устраивают сборки.
Показать ещё 16 комментариев
362

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

AppDomain.CurrentDomain.BaseDirectory
  • 0
    Отличный совет, особенно при использовании встроенных ресурсов
  • 34
    Не используйте это. BaseDirectory может быть установлен во время выполнения. Это не гарантируется быть правильным (как принятый ответ).
Показать ещё 4 комментария
122

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

// 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);
  • 1
    Просто хотел сказать, очевидно, что есть много больше, чем 2 варианта, сколько других вариантов опубликовано ...
  • 12
    Если все, что вы пытаетесь сделать с указанным путем, не поддерживает формат URI, используйте var localDirectory = new Uri(directory).LocalPath;
Показать ещё 2 комментария
72

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

Environment.GetCommandLineArgs()[0];

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

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

Edit:

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

  • 0
    А может быть так: path = Environment.GetCommandLineArgs () [0] .Substring (0, iniFilePath.LastIndexOf ("\\") + 1);
  • 0
    @fabspro - я отредактировал пост, чтобы показать дополнительный шаг удаления имени приложения и просто оставив путь к каталогу
Показать ещё 8 комментариев
38

Для всех, кто интересуется веб-приложениями 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", поэтому первое решение, безусловно, не подходит для веб-приложений.

34

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

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

// Get normal filepath of this assembly permanent directory
var path = new Uri(
    System.IO.Path.GetDirectoryName(
        System.Reflection.Assembly.GetExecutingAssembly().CodeBase)
    ).LocalPath;
  • 0
    это также хорошо работает, если рассматриваемый exe-файл - это служба Windows, а текущий каталог возвращает C: \ Windows \ system32. Приведенный выше код возвращает фактическое местоположение exe
  • 0
    За исключением случаев, когда вы пытаетесь сделать что-то вроде File.CreateDirectory(path) , это даст вам исключение, что он не разрешает пути URI ...
Показать ещё 3 комментария
25

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

System.IO.Path.GetDirectoryName(
    System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)
18

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

System.Environment.CurrentDirectory
  • 0
    Это позволит получить папку исполняемого файла, хотя
  • 21
    Если что-то не вызвало Directory.SetCurrentDirectory () ...
Показать ещё 1 комментарий
17

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

System.IO.Directory.GetCurrentDirectory();

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

c:\users\xxxxxxx\documents\visual studio 2012\Projects\ImageHandler\GetDir\bin\Debug

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

AppDomain.CurrentDomain.BaseDirectory

Вывод:

c:\users\xxxxxxx\documents\visual studio 2012\Projects\ImageHandler\GetDir\bin\Debug\

12

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

AppDomain.CurrentDomain.BaseDirectory
7

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

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

  • 0
    Я использовал это, и это работает хорошо. Но однажды я использовал этот метод в своем проекте модульного тестирования. И, конечно, это не удалось, потому что он искал мой файл в C: \ PROGRAM FILES (X86) \ MICROSOFT VISUAL STUDIO 14.0 \ COMMON7 \ IDE \ COMMONEXTENSIONS \ MICROSOFT \ TESTWINDOW
7

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

System.AppDomain.CurrentDomain.BaseDirectory

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

7

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

var thisPath = System.IO.Directory.GetCurrentDirectory();
  • 4
    Это не правильно, потому что вы можете получить случайные каталоги в результате.
  • 0
    эта команда возвращает Environment.CurrentDirectory, который может быть изменен во время выполнения на любой путь, поэтому он не является надежным решением.
5

Я имею в виду, почему бы не использовать метод p/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");
  • 1
    Зачем p / invoke, когда для этого так много .NET?
  • 3
    Потому что почему нет?
Показать ещё 1 комментарий
4

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

System.AppContext.BaseDirectory

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

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

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

4
AppDomain.CurrentDomain.BaseDirectory

Будет разрешена проблема для ссылки на файлы сторонних ссылок с установочными пакетами.

  • 11
    Этот ответ уже предлагался 5 лет назад, даже не раз.
4

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

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

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

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

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetModuleFileName(HandleRef hModule, StringBuilder buffer, int length);
2

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

 string exePath = Path.GetDirectoryName( Application.ExecutablePath);
2

Ни один из этих методов не работает в особых случаях, таких как использование символической ссылки на 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

в VB.net

My.Application.Info.DirectoryPath

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

0

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

Различные способы получения исполняемого файла приложения

0

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

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

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

  • простое приложение
  • в другом домене, где Assembly.GetEntryAssembly() возвращает null
  • DLL загружается из встроенных ресурсов в виде массива байтов и загружается в AppDomain как Assembly.Load(byteArrayOfEmbeddedDll)
0

Я не видел, чтобы кто-то конвертировал 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

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

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

с использованием 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 и т.д., А также ограниченный контроль, например. Убить и т.д. *

-5

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

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);
}
  • 6
    Использование Environment.CurrentDirectory очень неправильно, не используйте это! этот путь может измениться во время выполнения. Даже при запуске это недетерминировано.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню