Как найти путь приложения в консольном приложении?
В Windows Forms я могу использовать Application.StartupPath для поиска текущего пути, но это, похоже, не доступно на консоли приложение.
Как найти путь приложения в консольном приложении?
В Windows Forms я могу использовать Application.StartupPath для поиска текущего пути, но это, похоже, не доступно на консоли приложение.
  System.Reflection.Assembly.GetExecutingAssembly().  Location 1
 Объедините это с  System.IO.Path.GetDirectoryName если вам нужен только каталог.
1 Согласно комментарию Mr.Mindor:
System.Reflection.Assembly.GetExecutingAssembly().LocationвозвращаетSystem.Reflection.Assembly.GetExecutingAssembly().Locationкотором в данный момент находится исполняющая сборка, что может быть или не быть в том месте, где находится сборка, когда она не выполняется. В случае сборок теневого копирования вы получите путь во временный каталог.System.Reflection.Assembly.GetExecutingAssembly().CodeBaseвернет "постоянный" путь сборки.
Вы можете использовать следующий код для получения текущего каталога приложений.
AppDomain.CurrentDomain.BaseDirectory
У вас есть два варианта поиска каталога приложения, которое вы выбрали, будет зависеть от вашей цели.
// 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);
Вероятно, немного поздно, но это стоит упомянуть:
Environment.GetCommandLineArgs()[0];
Или, вернее, получить только путь к каталогу:
System.IO.Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]);
Edit:
Довольно много людей отметили, что GetCommandLineArgs не гарантированно возвращает имя программы. См. Первое слово в командной строке - это имя программы только по соглашению. В статье говорится, что "хотя очень немногие программы для Windows используют эту причуду (я сам не знаю)". Таким образом, можно "обманывать" GetCommandLineArgs, но мы говорим о консольном приложении. Консольные приложения обычно бывают быстрыми и грязными. Так что это соответствует моей философии KISS.
Для всех, кто интересуется веб-приложениями 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", поэтому первое решение, безусловно, не подходит для веб-приложений.
Ответ выше был 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;
Возможно, вы захотите сделать это:
System.IO.Path.GetDirectoryName(
    System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)
вы можете использовать это вместо.
System.Environment.CurrentDirectory
Для консольных приложений вы можете попробовать следующее:
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\
Я использовал этот код и получил решение.
AppDomain.CurrentDomain.BaseDirectory
Если вы ищете .NET Core совместимый способ, используйте
System.AppContext.BaseDirectory
Это было представлено в .NET Framework 4.6 и .NET Core 1.0 (и .NET Standard 1.3). Смотрите: Свойство AppContext.BaseDirectory.
Согласно этой странице,
Это предпочтительная замена для AppDomain.CurrentDomain.BaseDirectory в .NET Core
Я использовал
System.AppDomain.CurrentDomain.BaseDirectory
когда я хочу найти путь относительно папки приложений. Это работает как для приложений ASP.Net, так и для winform. Он также не требует ссылки на сборки System.Web.
Вы можете просто добавить к своим проектам System.Windows.Forms, а затем использовать System.Windows.Forms.Application.StartupPath, как обычно.
Таким образом, не нужно использовать более сложные методы или использовать отражение.
Я использую это, если exe предполагается вызывать двойным щелчком мыши
var thisPath = System.IO.Directory.GetCurrentDirectory();
Я имею в виду, почему бы не использовать метод 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");
Следующая строка даст вам путь к приложению:
var applicationPath = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName)
Решение выше работает правильно в следующих ситуациях:
mkbundle пучками (другие методы не работают) 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);
AppDomain.CurrentDomain.BaseDirectory
Будет разрешена проблема для ссылки на файлы сторонних ссылок с установочными пакетами.
в VB.net
My.Application.Info.DirectoryPath
работает для меня (Тип приложения: Библиотека классов). Не уверен в С#... Возвращает путь без имени файла как строки
Ни один из этих методов не работает в особых случаях, таких как использование символической ссылки на 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) + @"\";
    }
}
Попробуйте эту простую строку кода:
 string exePath = Path.GetDirectoryName( Application.ExecutablePath);
Другое решение использует относительные пути, указывающие на текущий путь:
Path.GetFullPath(".")
Я не видел, чтобы кто-то конвертировал 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", где находится ваш код.
Существует много способов получить исполняемый путь, который мы должны использовать, зависит от наших потребностей, здесь есть ссылка, в которой обсуждаются разные методы.
Вот надежное решение, которое работает с приложениями 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 и т.д., А также ограниченный контроль, например. Убить и т.д. *
Вы можете создать имя папки как Ресурсы в проекте с помощью Обозревателя решений, затем вы можете вставить файл в Ресурсы.
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);
}