Pregunta

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

En Windows Forms , puedo usar Application.StartupPath para encuentra la ruta actual, pero parece que no está disponible en una aplicación de consola.

¿Fue útil?

Solución

System.Reflection.Assembly.GetExecutingAssembly () . Ubicación 1

Combina 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 dónde se encuentra actualmente el ensamblaje en ejecución, que puede o no estar donde se encuentra 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' del ensamblado.

Otros consejos

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

AppDomain.CurrentDomain.BaseDirectory

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

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

Edición :

Muchas personas han señalado que GetCommandLineArgs no 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. 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 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;

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 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 \

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

AppDomain.CurrentDomain.BaseDirectory

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). Consulte: AppContext.BaseDirectory Property .

De acuerdo a esta página ,

  

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

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.

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

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

Utilizo esto si se supone que se llama al exe haciendo doble clic en él

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

Quiero decir, ¿por qué no un método 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());
                }
            }
    }

Lo usaría igual que Application.StartupPath:

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

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 matriz de bytes y se carga en AppDomain como Assembly.Load (byteArrayOfEmbeddedDll)

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

Usar 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.

Con GetEntryAssembly () debe tener en cuenta que esto puede devolver nulo 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.

en VB.net

My.Application.Info.DirectoryPath

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

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á el " C: \ xxx \ xxx " ruta formateada 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 32 bits y 64 bits .

Agregue 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<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 aquellos interesados:

Process.GetProcesses() 

... le dará una matriz de todos los procesos que se ejecutan actualmente, y ...

Process.GetCurrentProcess()

... le dará el proceso actual, junto con su información, p. Id, etc. y también control limitado, p. Matar, 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);
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top