¿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?

In Formularios de Windows, Puedo usar Application.StartupPath para encontrar la ruta actual, pero no parece estar disponible en una aplicación de consola.

preguntado el 07 de mayo de 09 a las 20:05

¿Instala .NET Framework en la máquina de destino (cliente, desarrollo)? si tu respuesta es verdadera; Por lo tanto, puede agregar una referencia a System.Windows.Forms.dll y usar Application.StartupPath. ¡Esta es la mejor manera si desea descartar más excepciones futuras! -

AppDomain.BaseDirectory es el directorio de la aplicación. Tenga en cuenta que la aplicación puede comportarse de manera diferente en VS env y Win env. Pero AppDomain debería ser lo mismo que application.path pero espero que esto no sea solo para IIS. -

28 Respuestas

System.Reflection.Assembly.GetExecutingAssembly().Location1

Combina eso con System.IO.Path.GetDirectoryName si todo lo que quieres es el directorio.

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

respondido 14 mar '19, 08:03

System.Reflection.Assembly.GetExecutingAssembly (). La ubicación devuelve donde está el ensamblado en ejecución actualmente ubicado, que puede o no ser el lugar donde se ubica el ensamblaje cuando no se está ejecutando. En el caso de los ensamblados de copia instantánea, obtendrá una ruta en un directorio temporal. System.Reflection.Assembly.GetExecutingAssembly (). CodeBase devolverá el 'permanente'camino de la asamblea. - Señor menor

@SamGoldberg: Eso depende de cómo se use: stackoverflow.com/q/1068420/391656 . O puede ... nuevo Uri (System.Reflection.Assembly.GetExecutingAssembly (). CodeBase) .LocalPath - Señor menor

GetExecutingAssembly devuelve el montaje que contiene el código que se está ejecutando actualmente. Esta puede no ser necesariamente la consola .exe montaje. Puede ser un conjunto que se haya cargado desde una ubicación totalmente diferente. Tendrás que usar GetEntryAssembly! También tenga en cuenta que CodeBasees posible que no se establezca cuando el ensamblado está en la GAC. La mejor alternativa es AppDomain.CurrentDomain.BaseDirectory. - bitbonk

Escriba el código en 4 espacios para que sea cómodo de copiar - fnc12

@farosch: Application no existe para aplicaciones de consola. - sam hacha

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

AppDomain.CurrentDomain.BaseDirectory

respondido 22 nov., 13:12

No uses esto. BaseDirectory se puede configurar en tiempo de ejecución. No se garantiza que sea correcto (como lo es la respuesta aceptada). - usr

+1 Esta es probablemente la respuesta que desea, ya que compensa las instantáneas. - Jorge Mauer

@usr ¿Qué te hace pensar que BaseDirectory se puede configurar en tiempo de ejecución? Solo tiene un captador. - bitbonk

@bitbonk se puede configurar en el momento de la creación del dominio de la aplicación. - usr

¿No es que BaseDirectory se puede cambiar en un archivo * .lnk, en el campo "Iniciar en:"? - Alexander

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

Respondido 09 Feb 20, 19:02

Solo quería decir, obviamente, hay muchas más de 2 opciones por la cantidad de otras opciones que se publican ... - vapcguy

Si lo que sea que esté tratando de hacer con dicha ruta no es compatible con el formato URI, use var localDirectory = new Uri(directory).LocalPath; - scott solmer

Esto es simplemente incorrecto. ¿Qué es el ejecutable que no es un ensamblado .NET en absoluto? La respuesta correcta es comprobar el entorno e inspeccionar la línea de comandos. - marca

@ Ukuma.Scott Esto no funciona si la ruta contiene & o # - EsterasW

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

Edit:

Muchas personas han señalado que GetCommandLineArgs no se garantiza que devuelva el nombre del programa. Ver La primera palabra en la línea de comando es el nombre del programa solo por convención. El artículo afirma que "Aunque muy pocos programas de Windows utilizan este capricho (yo mismo no conozco ninguno)". Entonces es posible 'parodiar' 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.

Respondido 27 ago 15, 10:08

@usr la situación a la que alude es muy teórica. En el contexto de una aplicación de consola, no tiene sentido utilizar ningún otro método. ¡Mantenlo simple! - steve mc

@usr mmm: mirar la columna de cmdline de taskmgr respalda lo que estoy diciendo. Algunos servicios del sistema con solo el nombre del exe. No importa. Lo que intento decir es que al desarrollar una aplicación de consola no hay necesidad de complicar las cosas más de lo necesario. Especialmente cuando ya tenemos la información disponible. Ahora, si está ejecutando una aplicación de consola de tal manera que engañe a GetCommandLineArgs, entonces ya está saltando los obstáculos y probablemente deba preguntarse si una aplicación de consola es el camino correcto a seguir. - steve mc

Su solución "simple" implica dos llamadas a métodos. La solución "complicada" implica dos llamadas a métodos. No hay diferencia práctica, excepto que la solución "simple" puede darle una respuesta incorrecta bajo ciertas circunstancias que no están bajo su control cuando está escribiendo el programa. ¿Por qué correr el riesgo? Utilice las otras dos llamadas a métodos y su programa no será más complicado pero será más confiable. - Chris

Funcionó para mi escenario, las otras soluciones no, así que gracias por proporcionar otra alternativa :-) Estaba usando el ejecutor de pruebas ReSharper para ejecutar una prueba de MS Unit y el código que estaba probando necesitaba un .dll específico para estar en el directorio de ejecución. .. y Assembly.GetExecutingDirectory () devuelve un resultado diferente de forma extraña. - Wallismark

@Chris - en defensa de esta respuesta. Funciona para pruebas unitarias, la solución GetEntryAssembly no, porque GetEntryAssembly devuelve nulo. Las respuestas que proponen GetExecutingAssembly son falsas, porque solo devuelven el ejecutable si el ensamblado en ejecución es el ejecutable. Esta no es la solución simple, sino la correcta. - marca

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.

Respondido 06 Oct 11, 20:10

La respuesta anterior fue el 90% de lo que necesitaba, pero me devolvió un Uri en lugar de una ruta normal.

Como se explica en la publicación de foros de MSDN, ¿Cómo convertir la ruta 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;

Respondido 13 Abr '12, 21:04

esto también funciona bien si el exe en cuestión es un servicio de Windows y el directorio actual devuelve C: \ Windows \ system32. El código anterior devuelve la ubicación real del exe - daimto

Excepto si luego intentas hacer algo como File.CreateDirectory(path), le dará la excepción de que no permite rutas URI ... - vapcguy

Desafortunadamente, esto no funciona para rutas que contienen un identificador de fragmento (el # personaje). El identificador y todo lo que le sigue se trunca de la ruta resultante. - bgfvdu3w

¿Por qué no cambias? new Uri y System.IO.Path.GetDirectoryName? Eso le da una cadena de ruta normal en lugar de una Uri. - Timo

Encuentro este el mejor. Este mismo enfoque me ha funcionado de manera confiable en cualquier entorno. En producción, depuración local, pruebas unitarias ... ¿Desea abrir un archivo de contenido que incluyó ("contenido - copiar si es más reciente") en una prueba unitaria? Está allá. - Timo

Es posible que esté buscando hacer esto:

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

respondido 20 nov., 13:15

Tenga en cuenta que esto devolvió un URI, que no es compatible en todos los casos. - Denise Skidmore

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.

Según esta página,

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

Respondido 02 Feb 18, 02:02

véase también github.com/dotnet/runtime/issues/13051 para aplicaciones de consola dotnet autónomas. La recomendación aquí es usar Process.GetCurrentProcess().MainModule.FileName - Gavin

puedes usar este en su lugar.

System.Environment.CurrentDirectory

Respondido el 16 de Septiembre de 15 a las 14:09

Sin embargo, esto obtendrá la carpeta del ejecutable: Iain

Esto se puede cambiar de varias formas (configuración de atajos, etc.) ... es mejor NO usarlo. - Yousha Aleayoub

Para las aplicaciones de consola, puede probar esto:

System.IO.Directory.GetCurrentDirectory();

Salida (en mi máquina local):

c: \ usuarios \ xxxxxxx \ documentos \ visual studio 2012 \ Proyectos \ ImageHandler \ GetDir \ bin \ Debug

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

AppDomain.CurrentDomain.BaseDirectory

Salida:

c: \ usuarios \ xxxxxxx \ documentos \ visual studio 2012 \ Projects \ ImageHandler \ GetDir \ bin \ Debug \

Respondido el 18 de junio de 14 a las 23:06

"El BaseDirectory se puede configurar en tiempo de ejecución. NO se garantiza que sea correcto "- Yousha Aleayoub

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

AppDomain.CurrentDomain.BaseDirectory

Respondido el 31 de enero de 17 a las 08:01

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 nulo
  • DLL se carga desde los recursos integrados como una matriz de bytes y se carga en AppDomain como Assembly.Load (byteArrayOfEmbeddedDll)
  • con mono mkbundle paquetes (ningún otro método funciona)

Respondido 06 Oct 19, 11:10

En el depurador en Linux, esto devuelve: / usr / share / dotnet - Vladimir

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

Por lo tanto, no es necesario utilizar métodos más complicados ni utilizar la reflexión.

contestado el 09 de mayo de 16 a las 13:05

Usé ese y funciona bien. Pero una vez usé el método que lo tenía en mi proyecto de prueba unitaria. Y, por supuesto, falló porque estaba buscando mi archivo en C: \ PROGRAM FILES (X86) \ MICROSOFT VISUAL STUDIO 14.0 \ COMMON7 \ IDE \ COMMONEXTENSIONS \ MICROSOFT \ TESTWINDOW - ainasiart

@ainasiart, entonces, ¿cómo hago para que esto funcione durante la prueba unitaria? - Nicolás Siegmundt

Lo uso si se supone que se debe llamar al exe haciendo doble clic en él

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

Respondido el 10 de Septiembre de 13 a las 23:09

Esto no es correcto porque puede obtener directorios aleatorios como resultado. - amiliar

este comando devuelve Environment.CurrentDirectory, que se puede cambiar en tiempo de ejecución a cualquier ruta, por lo que no es una solución confiable. - Yuri Kozlov

He utilizado

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.

Respondido 07 Abr '14, 17:04

Quiero decir, ¿por qué no el 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ía como Application.StartupPath:

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

Respondido 24 Jul 14, 21:07

¿Por qué p / invoke cuando hay tanto .NET para esto? - ProfK

@ user3596865 porque requiere una dependencia estricta de Windows y no es compatible con DNX o Mono. Y tal vez haya un cambio radical en las futuras versiones de Windows. Así que de nuevo: ¿por qué deberíamos usar pinvoke aquí? - Benjamín Abt

Assembly.GetEntryAssembly().Location or Assembly.GetExecutingAssembly().Location

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

Los caminos de GetEntryAssembly() y GetExecutingAssembly() puede ser diferente, aunque en la mayoría de los casos el directorio será el mismo.

Contamos con GetEntryAssembly() tienes que ser consciente de que esto puede volver null si el módulo de entrada no está administrado (es decir, ejecutable C ++ o VB6). En esos casos es posible utilizar GetModuleFileName desde la API de Win32:

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

Respondido el 11 de junio de 12 a las 16:06

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

contestado el 16 de mayo de 18 a las 03:05

AppDomain.CurrentDomain.BaseDirectory

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

Respondido 14 Jul 14, 07:07

Esta respuesta ya se sugirió hace 5 años, incluso más de una vez. - PL

Prueba esta sencilla línea de código:

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

respondido 20 nov., 17:09

No vi a nadie convertir el LocalPath proporcionado por la reflexión de .Net Core en una ruta System.IO utilizable, 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á el C:\\xxx\\xxx ruta formateada a donde está su código.

respondido 10 nov., 20:14

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

Respondido 05 Feb 17, 08:02

Otra solución es usar rutas relativas que apuntan a la ruta actual:

Path.GetFullPath(".")

Respondido el 22 de junio de 19 a las 22:06

Esto obtiene el directorio actual, no la ubicación del EXE inicial. - diez cuatro

Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName) Es el único que me ha funcionado en todos los casos que lo he intentado.

respondido 10 nov., 20:14

Con .NET Core 3 y superior obtendrá el .dll y no el archivo .exe. Para obtener la ruta del archivo .exe, puede usar.

var appExePath = Process.GetCurrentProcess().MainModule.FileName;

respondido 05 mar '21, 15:03

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

Agregue estas referencias:

utilizando System.Diagnostics;

utilizando 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 están ejecutando 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. *

Respondido el 20 de junio de 20 a las 10:06

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

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

Respondido 03 Abr '18, 08:04

Para su información: el enlace muestra una advertencia de amenaza cuando se hace clic en él. - Gregorio William Bryant

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

contestado el 28 de mayo de 12 a las 12:05

Usar Environment.CurrentDirectory es muy incorrecto, ¡no use esto! esta ruta puede cambiar en tiempo de ejecución. Incluso al inicio, no es determinista. - usr

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.