[c#] Come posso ottenere il percorso dell'applicazione in un'applicazione console .NET?



Answers

È possibile utilizzare il seguente codice per ottenere la directory dell'applicazione corrente.

AppDomain.CurrentDomain.BaseDirectory
Question

Come trovo il percorso dell'applicazione in un'applicazione console?

In Windows Form , posso usare Application.StartupPath per trovare il percorso corrente, ma questo non sembra essere disponibile in un'applicazione console.




La seguente linea ti darà un percorso applicativo:

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

La soluzione di cui sopra funziona correttamente nelle seguenti situazioni:

  • semplice app
  • in un altro dominio dove Assembly.GetEntryAssembly () restituisce null
  • La DLL viene caricata dalle risorse incorporate come array di byte e caricata in AppDomain come Assembly.Load (byteArrayOfEmbeddedDll)



Voglio dire, perché non metodo 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 useresti proprio come Application.StartupPath:

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



Ecco una soluzione affidabile che funziona con applicazioni a 32 bit e 64 bit .

Aggiungi questi riferimenti:

utilizzando System.Diagnostics;

using System.Management;

Aggiungi questo metodo al tuo progetto:

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

Ora usalo in questo modo:

int RootProcessId = Process.GetCurrentProcess().Id;

GetProcessPath(RootProcessId);

Si noti che se si conosce l'id del processo, questo metodo restituirà l'ExecutePath corrispondente.

Extra, per chi è interessato:

Process.GetProcesses() 

... ti fornirà una serie di tutti i processi attualmente in esecuzione, e ...

Process.GetCurrentProcess()

... ti fornirà il processo corrente, insieme alle loro informazioni, ad es. Id, ecc. e anche controllo limitato, ad esempio Kill, ecc. *




ho usato

System.AppDomain.CurrentDomain.BaseDirectory

quando voglio trovare un percorso relativo a una cartella di applicazioni. Questo funziona sia per ASP.Net che per le applicazioni Winform. Inoltre, non richiede alcun riferimento agli assembly System.Web.




Ho usato questo codice e ottenere la soluzione.

AppDomain.CurrentDomain.BaseDirectory



AppDomain.CurrentDomain.BaseDirectory

Risolverà il problema per fare riferimento ai file di riferimento di terze parti con i pacchetti di installazione.




Probabilmente un po 'tardi, ma vale la pena menzionarlo:

Environment.GetCommandLineArgs()[0];

O più correttamente per ottenere solo il percorso della directory:

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

Modificare:

Molte persone hanno sottolineato che GetCommandLineArgs non è garantito per restituire il nome del programma. Vedi La prima parola sulla riga di comando è il nome del programma solo per convenzione . L'articolo afferma che "Sebbene pochissimi programmi Windows usino questo strano capriccio (non ne sono a conoscenza nemmeno io)". Quindi è possibile "spoofare" GetCommandLineArgs , ma stiamo parlando di un'applicazione console. Le app della console sono in genere veloci e sporche. Quindi questo si adatta alla mia filosofia KISS.




puoi usare questo invece.

System.Environment.CurrentDirectory



Nessuno di questi metodi funziona in casi particolari come l'utilizzo di un collegamento simbolico con l'exe, essi restituiranno la posizione del collegamento non l'exe effettivo.

Quindi puoi usare QueryFullProcessImageName per QueryFullProcessImageName a questo:

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



Se stai cercando un modo compatibile con .NET Core, usa

System.AppContext.BaseDirectory

Questo è stato introdotto in .NET Framework 4.6 e .NET Core 1.0 (e .NET Standard 1.3). Vedi: Proprietà AppContext.BaseDirectory .

Secondo questa pagina ,

Questa è la sostituzione preferita per AppDomain.CurrentDomain.BaseDirectory in .NET Core




La risposta sopra era il 90% di ciò di cui avevo bisogno, ma per me ha restituito un Uri invece di un percorso regolare.

Come spiegato nel post dei forum MSDN, Come convertire il percorso URI in normale filepath? , Ho usato il seguente:

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





Related