¿Cómo puedo obtener la ruta de la aplicación en una aplicación de consola .NET?

¿Cómo encuentro la ruta de la aplicación en una aplicación de consola?

En Windows Forms , puedo usar Application.StartupPath para encontrar la ruta actual, pero esto no parece estar disponible en una aplicación de consola.

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

Combine eso con System.IO.Path.GetDirectoryName si todo lo que desea es el directorio.

1 Según el comentario del Sr. Mindor:
System.Reflection.Assembly.GetExecutingAssembly().Location devuelve donde se encuentra actualmente el ensamblaje en ejecución, que puede o no ser el lugar donde se encuentra el ensamblado cuando no se está ejecutando. En el caso de ensambles de copia de sombra, obtendrá una ruta en un directorio temporal. System.Reflection.Assembly.GetExecutingAssembly().CodeBase devolverá la ruta ‘permanente’ del ensamblado.

Puede usar el siguiente código para obtener el directorio de la aplicación actual.

 AppDomain.CurrentDomain.BaseDirectory 

Tienes dos opciones para encontrar el directorio de la aplicación, que elijas dependerá de tu propósito.

 // 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); 

Probablemente un poco tarde, pero vale la pena mencionarlo:

 Environment.GetCommandLineArgs()[0]; 

O más correctamente para obtener solo la ruta del directorio:

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

Editar:

Muy pocas personas han señalado que GetCommandLineArgs no garantiza devolver el nombre del progtwig. Ver La primera palabra en la línea de comando es el nombre del progtwig solo por convención . El artículo establece que “aunque muy pocos progtwigs de Windows usan esta peculiaridad (no estoy al tanto de ninguno)”. Por lo tanto, es posible ‘falsificar’ GetCommandLineArgs , pero estamos hablando de una aplicación de consola. Las aplicaciones de la consola generalmente son rápidas y sucias. Así que esto encaja con mi filosofía KISS.

Para cualquier persona interesada en las aplicaciones web asp.net. Aquí están mis resultados de 3 métodos diferentes

 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); } 

resultado

 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 

la aplicación se ejecuta físicamente desde “C: \ inetpub \ SBSPortal_staging”, por lo que la primera solución definitivamente no es apropiada para aplicaciones web.

La respuesta anterior era el 90% de lo que necesitaba, pero devolví un Uri en lugar de una ruta normal para mí.

Como se explica en la publicación de foros de MSDN, ¿Cómo convertir la ruta de URI a la ruta de archivo normal? , Utilicé lo siguiente:

 // Get normal filepath of this assembly's permanent directory var path = new Uri( System.IO.Path.GetDirectoryName( System.Reflection.Assembly.GetExecutingAssembly().CodeBase) ).LocalPath; 

Puede estar buscando hacer esto:

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

puedes usar este en su lugar.

 System.Environment.CurrentDirectory 

Para las aplicaciones de consola, puede intentar esto:

 System.IO.Directory.GetCurrentDirectory(); 

Salida (en mi máquina local):

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

O puede intentar (hay una barra invertida adicional al final):

 AppDomain.CurrentDomain.BaseDirectory 

Salida:

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

He usado este código y tengo la solución.

 AppDomain.CurrentDomain.BaseDirectory 

Utilizo esto si se supone que se debe llamar al ejecutando haciendo doble clic en él

 var thisPath = System.IO.Directory.GetCurrentDirectory(); 

He usado

 System.AppDomain.CurrentDomain.BaseDirectory 

cuando quiero encontrar una ruta relativa a una carpeta de aplicaciones. Esto funciona tanto para aplicaciones ASP.Net como winform. Tampoco requiere ninguna referencia a los ensamblados System.Web.

Simplemente puede agregar a su proyecto referencias System.Windows.Forms y luego usar System.Windows.Forms.Application.StartupPath como de costumbre.

Entonces, no necesita métodos más complicados o usar el reflection.

Si está buscando una forma compatible con .NET Core, use

 System.AppContext.BaseDirectory 

Esto se introdujo en .NET Framework 4.6 y .NET Core 1.0 (y .NET Standard 1.3). Ver: Propiedad AppContext.BaseDirectory .

De acuerdo con esta página ,

Este es el reemplazo preferido para AppDomain.CurrentDomain.BaseDirectory en .NET Core

Quiero decir, ¿por qué no un método de invocación?

  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()); } } } 

Lo usaría igual que Application.StartupPath:

  Console.WriteLine("The path to this executable is: " + AppInfo.StartupPath + "\\" + System.Diagnostics.Process.GetCurrentProcess().ProcessName + ".exe"); 

Assembly.GetEntryAssembly().Location o Assembly.GetExecutingAssembly().Location

Use en combinación con System.IO.Path.GetDirectoryName() para obtener solo el directorio.

Las rutas de GetEntryAssembly() y GetExecutingAssembly() pueden ser diferentes, aunque en la mayoría de los casos el directorio será el mismo.

Con GetEntryAssembly() tener en cuenta que esto puede devolver null si el módulo de entrada no está administrado (es decir, el ejecutable C ++ o VB6). En esos casos, es posible usar GetModuleFileName desde la API de Win32:

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

Resolverá el problema para referir los archivos de referencia de terceros con paquetes de instalación.

en VB.net

 My.Application.Info.DirectoryPath 

funciona para mí (Tipo de aplicación: Biblioteca de clases). No estoy seguro de C # … Devuelve la ruta sin nombre de archivo como cadena

Ninguno de estos métodos funciona en casos especiales, como usar un enlace simbólico al exe, devolverán la ubicación del enlace, no el actual.

Entonces puede usar QueryFullProcessImageName para evitar eso:

 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) + @"\"; } } 

Prueba esta simple línea de código:

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

La siguiente línea le dará una ruta de aplicación:

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

La solución anterior funciona correctamente en las siguientes situaciones:

  • aplicación simple
  • en otro dominio donde Assembly.GetEntryAssembly () devolvería null
  • La DLL se carga desde los recursos incrustados como una matriz de bytes y se carga en AppDomain como Assembly.Load (byteArrayOfEmbeddedDll)

No vi a nadie convertir el LocalPath proporcionado por .Net Core reflection en una ruta utilizable System.IO así que aquí está mi versión.

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

Esto devolverá la ruta formateada completa “C: \ xxx \ xxx” a donde está tu código.

Hay muchas formas de obtener una ruta ejecutable, la que deberíamos usar depende de nuestras necesidades. Aquí hay un enlace que analiza diferentes métodos.

Diferentes formas de obtener la ruta ejecutable de la aplicación

Aquí hay una solución confiable que funciona con aplicaciones de 32 bits y 64 bits .

Agrega estas referencias:

usando System.Diagnostics;

usando System.Management;

Agregue este método a su proyecto:

 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() select mo["ExecutablePath"]).First().ToString(); MethodResult = ExecutablePath; } } } catch //(Exception ex) { //ex.HandleException(); } return MethodResult; } 

Ahora úsalo así:

 int RootProcessId = Process.GetCurrentProcess().Id; GetProcessPath(RootProcessId); 

Tenga en cuenta que si conoce la identificación del proceso, este método devolverá el ExecutePath correspondiente.

Extra, para aquellos interesados:

 Process.GetProcesses() 

… le dará una selección de todos los procesos actualmente en ejecución, y …

 Process.GetCurrentProcess() 

… le dará el proceso actual, junto con su información, por ejemplo, Id, etc. y también control limitado, por ejemplo, matar, etc. *

Puede crear un nombre de carpeta como Recursos dentro del proyecto usando Solution Explorer, luego puede pegar un archivo dentro de los Recursos.

 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); }