Comment trouver le chemin de l'application dans une application console?
Dans Windows Forms , je peux utiliser Application.StartupPath
pour trouver le chemin actuel, mais cela ne semble pas être disponible dans une application console.
System.Reflection.Assembly.GetExecutingAssembly()
. Location
1
Combinez cela avec System.IO.Path.GetDirectoryName
si tout ce que vous voulez, c'est le répertoire.
1 Selon le commentaire de Mr.Mindor:
System.Reflection.Assembly.GetExecutingAssembly().Location
renvoie l'emplacement où se trouve actuellement l'assemblage d'exécution, qui peut ou non être celui où se trouve l'assembly lorsqu'il n'est pas en cours d'exécution. Dans le cas d'assemblages avec clichés instantanés, vous obtiendrez un chemin dans un répertoire temporaire.System.Reflection.Assembly.GetExecutingAssembly().CodeBase
renverra le chemin "permanent" de l'Assemblée.
Vous pouvez utiliser le code suivant pour obtenir le répertoire de l'application en cours.
AppDomain.CurrentDomain.BaseDirectory
Vous avez le choix entre deux options pour trouver le répertoire de l'application. Votre choix dépendra de votre objectif.
// 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);
Probablement un peu tard, mais cela mérite une mention:
Environment.GetCommandLineArgs()[0];
Ou plus correctement pour obtenir uniquement le chemin du répertoire:
System.IO.Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]);
Modifier:
Quelques personnes ont fait remarquer qu'il n'est pas garanti que GetCommandLineArgs
renvoie le nom du programme. Voir Le premier mot sur la ligne de commande est le nom du programme uniquement par convention . L'article indique que "Bien que très peu de programmes Windows utilisent cette bizarrerie (je n'en connais aucun moi-même)". Il est donc possible de "spoofer" GetCommandLineArgs
, mais nous parlons d'une application console. Les applications de la console sont généralement rapides et sales. Cela correspond donc à ma philosophie KISS.
Pour toute personne intéressée par les applications web asp.net. Voici mes résultats de 3 méthodes différentes
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);
}
résultat
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'application fonctionne physiquement à partir de "C:\inetpub\SBSPortal_staging", de sorte que la première solution n'est certainement pas appropriée pour les applications Web.
La réponse ci-dessus était 90% de ce dont j'avais besoin, mais m'a renvoyé un Uri au lieu d'un chemin normal.
Comme expliqué dans le message MSDN sur les forums, Comment convertir le chemin URI en chemin de fichier normal? , j’ai utilisé les éléments suivants:
// Get normal filepath of this Assembly's permanent directory
var path = new Uri(
System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().CodeBase)
).LocalPath;
Vous voulez peut-être faire ceci:
System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)
vous pouvez utiliser celui-ci à la place.
System.Environment.CurrentDirectory
Pour les applications console, vous pouvez essayer ceci:
System.IO.Directory.GetCurrentDirectory();
Sortie (sur ma machine locale):
c:\utilisateurs\xxxxxxx\documents\visual studio 2012\Projets\ImageHandler\GetDir\bin\Debug
Ou vous pouvez essayer (il y a une barre oblique inverse à la fin):
AppDomain.CurrentDomain.BaseDirectory
Sortie:
c:\utilisateurs\xxxxxxx\documents\visual studio 2012\Projets\ImageHandler\GetDir\bin\Debug \
J'ai utilisé ce code et obtenir la solution.
AppDomain.CurrentDomain.BaseDirectory
Si vous recherchez une méthode compatible avec .NET Core, utilisez
System.AppContext.BaseDirectory
Cela a été introduit dans .NET Framework 4.6 et .NET Core 1.0 (et .NET Standard 1.3). Voir: Propriété AppContext.BaseDirectory .
Selon cette page ,
Ceci est le remplacement préféré pour AppDomain.CurrentDomain.BaseDirectory dans .NET Core
Vous pouvez simplement ajouter à vos références de projet System.Windows.Forms
puis utiliser le System.Windows.Forms.Application.StartupPath
comme d'habitude.
Donc, pas besoin de méthodes plus compliquées ou en utilisant la réflexion.
J'ai utilisé
System.AppDomain.CurrentDomain.BaseDirectory
quand je veux trouver un chemin relatif à un dossier d'applications. Cela fonctionne pour les applications ASP.Net et Winform. De plus, il ne nécessite aucune référence aux assemblys System.Web.
J'utilise ceci si l'exe est censé s'appeler en double cliquant dessus
var thisPath = System.IO.Directory.GetCurrentDirectory();
Je veux dire, pourquoi pas une méthode 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());
}
}
}
Vous l'utiliseriez exactement comme Application.StartupPath:
Console.WriteLine("The path to this executable is: " + AppInfo.StartupPath + "\\" + System.Diagnostics.Process.GetCurrentProcess().ProcessName + ".exe");
La ligne suivante vous donnera un chemin d’application:
var applicationPath = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName)
La solution ci-dessus fonctionne correctement dans les situations suivantes:
mkbundle
de Mono (aucune autre méthode ne fonctionne)dans VB.net
My.Application.Info.DirectoryPath
travaille pour moi (Type d'application: Bibliothèque de classes). Pas sûr de C # ... Renvoie le chemin sans nom de fichier sous forme de chaîne
Assembly.GetEntryAssembly().Location
ou Assembly.GetExecutingAssembly().Location
Utiliser en combinaison avec System.IO.Path.GetDirectoryName()
pour obtenir uniquement le répertoire.
Les chemins de GetEntryAssembly()
et GetExecutingAssembly()
peuvent être différents, même si dans la plupart des cas, le répertoire sera le même.
Avec GetEntryAssembly()
, vous devez savoir que cela peut renvoyer null
si le module d’entrée est non géré (c-à-d un exécutable C++ ou VB6). Dans ces cas, il est possible d'utiliser GetModuleFileName
à partir de l'API Win32:
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetModuleFileName(HandleRef hModule, StringBuilder buffer, int length);
AppDomain.CurrentDomain.BaseDirectory
Résoudre le problème en faisant référence aux fichiers de référence tiers avec les packages d'installation.
Essayez cette simple ligne de code:
string exePath = Path.GetDirectoryName( Application.ExecutablePath);
Aucune de ces méthodes ne fonctionne dans des cas particuliers, comme l'utilisation d'un lien symbolique vers l'exe, elles renverront l'emplacement du lien et non l'exe.
Donc peut utiliser QueryFullProcessImageName pour contourner cela:
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) + @"\";
}
}
Une autre solution consiste à utiliser des chemins relatifs pointant vers le chemin actuel:
Path.GetFullPath(".")
Vous pouvez utiliser le code suivant, vous obtiendrez le chemin complet de l'application:
class Program
{
static void Main(string[] args)
{
string AppPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
WriteLine($"ApplicationPath ---{AppPath}");
//OutPut// //ApplicationPath---C:\Users\TestUser\source\repos\ThreadStack\ThreadStack\bin\Debug\ThreadStack.exe
ReadLine();
}
}
Il existe de nombreuses façons d’obtenir un chemin d’exécutable, celui que nous devrions utiliser dépend de nos besoins. Voici un lien qui décrit différentes méthodes.
Différentes façons d'obtenir le chemin de l'exécutable de l'application
Je n'ai vu personne convertir le chemin LocalPath fourni par .Net Core reflection en un chemin System.IO utilisable. Voici donc ma version.
public static string GetApplicationRoot()
{
var exePath = new Uri(System.Reflection.
Assembly.GetExecutingAssembly().CodeBase).LocalPath;
return new FileInfo(exePath).DirectoryName;
}
Cela renverra le chemin complet formaté "C:\xxx\xxx" à l'endroit où se trouve votre code.