Как я могу получить путь к приложению в консольном приложении .NET?
-
10-07-2019 - |
Вопрос
Как найти путь к приложению в консольном приложении?
В Формы Windows, Я могу использовать Application.StartupPath
чтобы найти текущий путь, но, похоже, он недоступен в консольном приложении.
Решение
System.Reflection.Assembly.GetExecutingAssembly ()
. Местоположение код>
1
Объедините это с System.IO. Path.GetDirectoryName
, если вам нужен только каталог.
1 Согласно комментарию мистера Миндора:
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]);
Редактировать:
Довольно много людей отметили это GetCommandLineArgs
не гарантируется возврат имени программы.Видеть Первое слово в командной строке является именем программы только по соглашению..В статье действительно говорится: «Хотя очень немногие программы для Windows используют эту причуду (я сам ни о чем не знаю)».Так что "подделать" можно GetCommandLineArgs
, но мы говорим о консольном приложении.Консольные приложения обычно быстрые и грязные.Так что это соответствует моей философии KISS.
Для всех, кто интересуется веб-приложениями asp.net.Вот мои результаты трех разных методов
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;
Возможно, вы хотите сделать это:
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 а>. р>
Я использовал
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)
Вышеупомянутое решение работает правильно в следующих ситуациях:
- простое приложение
- в другом домене, где Assembly.GetEntryAssembly() вернет ноль
- DLL загружается из встроенных ресурсов в виде массива байтов и загружается в AppDomain как Assembly.Load(byteArrayOfEmbeddedDll).
Assembly.GetEntryAssembly (). Местоположение
или Assembly.GetExecutingAssembly (). Местоположение
Используйте в сочетании с 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);
AppDomain.CurrentDomain.BaseDirectory
Решит проблему, ссылаясь на сторонние справочные файлы с установочными пакетами.
в VB.net
My.Application.Info.DirectoryPath
работает для меня (Тип приложения: Библиотека классов). Не уверен насчет C # ... Возвращает путь без имени файла в виде строки
Ни один из этих методов не работает в особых случаях, таких как использование символической ссылки на 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 " отформатированный путь к вашему коду. Р>
Есть много способов получить путь к исполняемому файлу, который мы должны использовать в зависимости от наших потребностей. Здесь есть ссылка, в которой обсуждаются различные методы.
Различные способы получения пути к исполняемому файлу приложения а> р>
Вот надежное решение, которое работает с приложениями 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()
... предоставит вам текущий процесс вместе с их информацией, например, Идентификатор и т. Д., А также ограниченный контроль, например, Убить и т. Д. *
Вы можете создать имя папки в качестве ресурсов в проекте с помощью обозревателя решений, а затем вставить файл в ресурсы.
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);
}