Как найти путь к приложению в консольном приложении?
В Windows Forms я могу использовать, Application.StartupPathчтобы найти текущий путь, но он не доступен в консольном приложении.
Как найти путь к приложению в консольном приложении?
В Windows Forms я могу использовать, Application.StartupPathчтобы найти текущий путь, но он не доступен в консольном приложении.
Ответы:
System.Reflection.Assembly.GetExecutingAssembly(), 1Location
Добавьте к этому, System.IO.Path.GetDirectoryNameесли все, что вам нужно, это каталог.
1 Согласно комментарию Mr.Mindor:
System.Reflection.Assembly.GetExecutingAssembly().Locationвозвращает место, где в данный момент находится исполняющая сборка, которое может быть, а может и не быть, где находится сборка, когда не выполняется. В случае сборок теневого копирования вы получите путь во временный каталог.System.Reflection.Assembly.GetExecutingAssembly().CodeBaseвернет «постоянный» путь сборки.
GetExecutingAssemblyвозвращает сборку, содержащую код, который в данный момент выполняется . Это не обязательно сборка консоли .exe . Это может быть сборка, которая была загружена из совершенно другого места. Вам придется использовать GetEntryAssembly! Также обратите внимание, что CodeBaseэто не может быть установлено, когда сборка находится в GAC. Лучшая альтернатива AppDomain.CurrentDomain.BaseDirectory.
Вы можете использовать следующий код, чтобы получить текущий каталог приложения.
AppDomain.CurrentDomain.BaseDirectory
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);
var localDirectory = new Uri(directory).LocalPath;
Возможно, немного поздно, но это стоит упомянуть:
Environment.GetCommandLineArgs()[0];
Или правильнее получить только путь к каталогу:
System.IO.Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]);
Редактировать:
Довольно много людей отметили, что 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's permanent directory
var path = new Uri(
System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().CodeBase)
).LocalPath;
File.CreateDirectory(path), это даст вам исключение, что он не разрешает пути URI ...
#символ). Идентификатор и все, что следует за ним, усекается из полученного пути.
new Uriи System.IO.Path.GetDirectoryName? Это дает вам нормальную строку пути вместо Uri.
Вы можете использовать это вместо этого.
System.Environment.CurrentDirectory
Если вы ищете .NET Core совместимый способ, используйте
System.AppContext.BaseDirectory
Это было представлено в .NET Framework 4.6 и .NET Core 1.0 (и .NET Standard 1.3). Смотрите: Свойство AppContext.BaseDirectory .
Согласно этой странице ,
Это предпочтительная замена для AppDomain.CurrentDomain.BaseDirectory в .NET Core
Process.GetCurrentProcess().MainModule.FileName
Для консольных приложений вы можете попробовать это:
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 \
BaseDirectoryМожет быть установлено во время выполнения. Оно НЕ гарантированно будет правильным»
Я использовал этот код и получил решение.
AppDomain.CurrentDomain.BaseDirectory
Вы можете просто добавить в свой проект ссылки, System.Windows.Formsа затем использовать System.Windows.Forms.Application.StartupPath как обычно.
Таким образом, не нужно более сложных методов или использования отражения.
Следующая строка даст вам путь к приложению:
var applicationPath = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName)
Вышеупомянутое решение работает должным образом в следующих ситуациях:
mkbundleсвязками Моно (другие методы не работают)Я использую это, если предполагается, что exe-файл вызывается двойным щелчком
var thisPath = System.IO.Directory.GetCurrentDirectory();
я использовал
System.AppDomain.CurrentDomain.BaseDirectory
когда я хочу найти путь относительно папки приложений. Это работает как для ASP.Net, так и для приложений winform. Также не требуется никаких ссылок на сборки System.Web.
Я имею в виду, почему не метод 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");
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);
в VB.net
My.Application.Info.DirectoryPath
у меня работает (Тип приложения: Библиотека классов). Не уверен насчет C # ... Возвращает путь без имени файла в виде строки
AppDomain.CurrentDomain.BaseDirectory
Решит проблему, ссылаясь на сторонние справочные файлы с установочными пакетами.
Ни один из этих методов не работает в особых случаях, таких как использование символической ссылки на исполняемый файл, они будут возвращать местоположение ссылки, а не фактический исполняемый файл.
Поэтому можно использовать 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» туда, где находится ваш код.
Есть много способов получить путь к исполняемому файлу, который мы должны использовать, это зависит от наших потребностей. Вот ссылка, которая обсуждает различные методы.
Вот надежное решение, которое работает с 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 и т. д. *
Вы можете создать имя папки как Ресурсы в проекте, используя 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);
}