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.
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.
Risposte:
System.Reflection.Assembly.GetExecutingAssembly()
. 1Location
Combina questo con System.IO.Path.GetDirectoryName
se tutto ciò che vuoi è la directory.
1 Secondo il commento di Mr.Mindor:
System.Reflection.Assembly.GetExecutingAssembly().Location
restituisce dove si trova l'assembly in esecuzione, che può essere o meno dove si trova l'assembly quando non viene eseguito. Nel caso di assiemi di copie shadow, si otterrà un percorso in una directory temporanea.System.Reflection.Assembly.GetExecutingAssembly().CodeBase
restituirà il percorso 'permanente' dell'assemblaggio.
GetExecutingAssembly
restituisce un assembly che contiene il codice attualmente in esecuzione . Questo potrebbe non essere necessariamente l' assembly .exe della console . Potrebbe essere un assieme che è stato caricato da una posizione completamente diversa. Dovrai usare GetEntryAssembly
! Si noti inoltre che CodeBase
potrebbe non essere impostato quando l'assembly si trova nel GAC. L'alternativa migliore è AppDomain.CurrentDomain.BaseDirectory
.
È possibile utilizzare il seguente codice per ottenere la directory dell'applicazione corrente.
AppDomain.CurrentDomain.BaseDirectory
BaseDirectory
possa essere impostato in fase di esecuzione? Ha solo un getter.
Hai due opzioni per trovare la directory dell'applicazione, che sceglierai dipenderà dal tuo scopo.
// 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;
Probabilmente un po 'in ritardo, ma vale la pena menzionare:
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 il ritorno del nome del programma. Vedere La prima parola nella riga di comando è il nome del programma solo per convenzione . L'articolo afferma che "Sebbene estremamente pochi programmi Windows utilizzino questa stranezza (non ne sono a conoscenza da solo)". 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.
Per chiunque sia interessato alle app web asp.net. Ecco i miei risultati di 3 metodi diversi
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);
}
risultato
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
l'app è fisicamente in esecuzione da "C: \ inetpub \ SBSPortal_staging", quindi la prima soluzione non è assolutamente appropriata per le app Web.
La risposta sopra era il 90% di ciò di cui avevo bisogno, ma mi ha restituito un Uri invece di un percorso regolare per me.
Come spiegato nel post del forum MSDN, Come convertire il percorso URI in normale percorso file? , 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;
File.CreateDirectory(path)
, ti darà l'eccezione che non consente i percorsi URI ...
#
carattere). L'identificatore e tutto ciò che lo segue viene troncato dal percorso risultante.
new Uri
e System.IO.Path.GetDirectoryName
? Questo ti dà una normale stringa di percorso invece di a Uri
.
puoi usare questo invece.
System.Environment.CurrentDirectory
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
Process.GetCurrentProcess().MainModule.FileName
Per le applicazioni console, puoi provare questo:
System.IO.Directory.GetCurrentDirectory();
Uscita (sul mio computer locale):
c: \ utenti \ xxxxxxx \ documenti \ visual studio 2012 \ Progetti \ ImageHandler \ GetDir \ bin \ Debug
Oppure puoi provare (c'è una barra rovesciata aggiuntiva alla fine):
AppDomain.CurrentDomain.BaseDirectory
Produzione:
c: \ utenti \ xxxxxxx \ documenti \ visual studio 2012 \ Progetti \ ImageHandler \ GetDir \ bin \ Debug \
BaseDirectory
Può essere impostato in fase di esecuzione. NON è garantito che sia corretto"
Ho usato questo codice e ho ottenuto la soluzione.
AppDomain.CurrentDomain.BaseDirectory
Puoi semplicemente aggiungere ai riferimenti del tuo progetto System.Windows.Forms
e quindi utilizzare il System.Windows.Forms.Application.StartupPath
solito.
Quindi, non è necessario per metodi più complicati o usando la riflessione.
La seguente riga fornisce un percorso dell'applicazione:
var applicationPath = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName)
La soluzione sopra funziona correttamente nelle seguenti situazioni:
mkbundle
bundle di Mono (nessun altro metodo funziona)Lo uso se si suppone che l'exe venga chiamato facendo doppio clic su di esso
var thisPath = System.IO.Directory.GetCurrentDirectory();
ho usato
System.AppDomain.CurrentDomain.BaseDirectory
quando voglio trovare un percorso relativo a una cartella di applicazioni. Funziona sia con ASP.Net che con applicazioni winform. Inoltre non richiede alcun riferimento agli assembly System.Web.
Voglio dire, perché non un 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");
Assembly.GetEntryAssembly().Location
o Assembly.GetExecutingAssembly().Location
Utilizzare in combinazione con System.IO.Path.GetDirectoryName()
per ottenere solo la directory.
I percorsi da GetEntryAssembly()
e GetExecutingAssembly()
possono essere diversi, anche se nella maggior parte dei casi la directory sarà la stessa.
Con GetEntryAssembly()
te devi essere consapevole che questo può tornare null
se il modulo di ingresso non è gestito (cioè eseguibile C ++ o VB6). In questi casi è possibile utilizzare GetModuleFileName
dall'API Win32:
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetModuleFileName(HandleRef hModule, StringBuilder buffer, int length);
AppDomain.CurrentDomain.BaseDirectory
Risolverà il problema per fare riferimento ai file di riferimento di terze parti con i pacchetti di installazione.
Nessuno di questi metodi funziona in casi speciali come l'uso di un collegamento simbolico con l'exe, restituiranno la posizione del collegamento non l'exe effettivo.
Quindi puoi usare QueryFullProcessImageName per aggirare 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) + @"\";
}
}
Prova questa semplice riga di codice:
string exePath = Path.GetDirectoryName( Application.ExecutablePath);
Un'altra soluzione sta usando percorsi relativi che puntano al percorso corrente:
Path.GetFullPath(".")
Non ho visto nessuno convertire il LocalPath fornito da .Net Core reflection in un percorso System.IO utilizzabile, quindi ecco la mia versione.
public static string GetApplicationRoot()
{
var exePath = new Uri(System.Reflection.
Assembly.GetExecutingAssembly().CodeBase).LocalPath;
return new FileInfo(exePath).DirectoryName;
}
Ciò restituirà il percorso completo "C: \ xxx \ xxx" formattato dove si trova il tuo codice.
Esistono molti modi per ottenere il percorso eseguibile, quello che dovremmo usare dipende dalle nostre esigenze qui è un link che discute metodi diversi.
Diversi modi per ottenere il percorso eseguibile dell'applicazione
Ecco una soluzione affidabile che funziona con applicazioni a 32 e 64 bit .
Aggiungi questi riferimenti:
utilizzando System.Diagnostics;
utilizzando 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 così:
int RootProcessId = Process.GetCurrentProcess().Id;
GetProcessPath(RootProcessId);
Si noti che se si conosce l'id del processo, questo metodo restituirà ExecutePath corrispondente.
Extra, per chi è interessato:
Process.GetProcesses()
... ti darà una serie di tutti i processi attualmente in esecuzione, e ...
Process.GetCurrentProcess()
... ti fornirà il processo corrente, insieme alle loro informazioni, ad esempio Id, ecc. e anche un controllo limitato, ad esempio Kill, ecc. *
È possibile creare un nome di cartella come Risorse all'interno del progetto utilizzando Esplora soluzioni, quindi è possibile incollare un file all'interno delle Risorse.
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);
}