¿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.
¿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.
Respuestas:
System.Reflection.Assembly.GetExecutingAssembly()
. 1Location
Combina eso con System.IO.Path.GetDirectoryName
si todo lo que quieres es el directorio.
1 Según el comentario del Sr.Mindor:
System.Reflection.Assembly.GetExecutingAssembly().Location
regresa donde se encuentra actualmente el ensamblaje ejecutor, que puede o no ser donde se ubica el ensamblaje cuando no se está ejecutando. En el caso de los ensamblados de instantáneas, obtendrá una ruta en un directorio temporal.System.Reflection.Assembly.GetExecutingAssembly().CodeBase
devolverá la ruta 'permanente' de la asamblea.
GetExecutingAssembly
devuelve el ensamblado que contiene el código que se está ejecutando actualmente . Esto puede no ser necesariamente el ensamblado .exe de la consola . Puede ser un ensamblaje que se ha cargado desde una ubicación totalmente diferente. Tendrás que usar GetEntryAssembly
! También tenga en cuenta que es CodeBase
posible que no se configure cuando el ensamblaje está en el GAC. La mejor alternativa es AppDomain.CurrentDomain.BaseDirectory
.
Puede usar el siguiente código para obtener el directorio de la aplicación actual.
AppDomain.CurrentDomain.BaseDirectory
BaseDirectory
se puede configurar en tiempo de ejecución? Solo tiene un captador.
Tiene dos opciones para encontrar el directorio de la aplicación, que elija dependerá de su 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);
var localDirectory = new Uri(directory).LocalPath;
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:
Muchas personas han señalado que GetCommandLineArgs
no se garantiza que devuelva el nombre del programa. Consulte La primera palabra en la línea de comando es el nombre del programa solo por convención . El artículo establece que "Aunque muy pocos programas de Windows usan este capricho (no conozco ninguno)". Por lo tanto, es posible "falsificar" GetCommandLineArgs
, pero estamos hablando de una aplicación de consola. Las aplicaciones de consola suelen ser rápidas y sucias. Entonces 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 fue el 90% de lo que necesitaba, pero me devolvió un Uri en lugar de un camino normal.
Como se explica en la publicación de foros de MSDN, ¿Cómo convertir la ruta URI a la ruta de archivo normal? , Usé 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;
File.CreateDirectory(path)
, se le dará la excepción de que no permite URI caminos ...
#
carácter). El identificador y todo lo que sigue se trunca de la ruta resultante.
new Uri
y System.IO.Path.GetDirectoryName
? Eso te da una cadena de ruta normal en lugar de a Uri
.
puedes usar este en su lugar.
System.Environment.CurrentDirectory
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: AppContext.BaseDirectory Property .
De acuerdo con esta página ,
Este es el reemplazo preferido para AppDomain.CurrentDomain.BaseDirectory en .NET Core
Process.GetCurrentProcess().MainModule.FileName
Para aplicaciones de consola, puede probar 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 intentarlo (hay una barra invertida adicional al final):
AppDomain.CurrentDomain.BaseDirectory
Salida:
c: \ users \ xxxxxxx \ documents \ visual studio 2012 \ Projects \ ImageHandler \ GetDir \ bin \ Debug \
BaseDirectory
puede configurar en tiempo de ejecución. NO se garantiza que sea correcto"
He usado este código y obtengo la solución.
AppDomain.CurrentDomain.BaseDirectory
Simplemente puede agregar a sus referencias de proyecto System.Windows.Forms
y luego usar las de System.Windows.Forms.Application.StartupPath
siempre.
Por lo tanto, no es necesario utilizar métodos más complicados o usar la reflexión.
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:
mkbundle
paquetes de Mono (ningún otro método funciona)Lo uso si se supone que se llama al exe 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 ASP.Net como para aplicaciones winform. Tampoco requiere ninguna referencia a los ensamblados System.Web.
Quiero decir, ¿por qué no un método 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());
}
}
}
Lo usarías al 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 desde GetEntryAssembly()
y GetExecutingAssembly()
pueden ser diferentes, aunque en la mayoría de los casos el directorio será el mismo.
Tenga GetEntryAssembly()
en cuenta que esto puede volver null
si el módulo de entrada no está administrado (es decir, C ++ o VB6 ejecutable). 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.
Ninguno de estos métodos funciona en casos especiales como el uso de un enlace simbólico al exe, devolverán la ubicación del enlace, no el exe real.
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) + @"\";
}
}
Pruebe esta simple línea de código:
string exePath = Path.GetDirectoryName( Application.ExecutablePath);
Otra solución es usar rutas relativas que apuntan a la ruta actual:
Path.GetFullPath(".")
No vi a nadie convertir el LocalPath proporcionado por la reflexión de .Net Core en una ruta utilizable de 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 "C: \ xxx \ xxx" completa a donde está su 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 .
Agregue estas referencias:
utilizando 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<ManagementObject>() 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 los interesados:
Process.GetProcesses()
... le dará una serie de todos los procesos que se ejecutan actualmente, y ...
Process.GetCurrentProcess()
... le dará el proceso actual, junto con su información, por ejemplo, Id, etc. y también un control limitado, por ejemplo, Kill, etc. *
Puede crear un nombre de carpeta como Recursos dentro del proyecto usando el Explorador de soluciones, 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);
}