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.
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.
Réponses:
System.Reflection.Assembly.GetExecutingAssembly()
. 1Location
Combinez cela avec System.IO.Path.GetDirectoryName
si tout ce que vous voulez est le répertoire.
1 Selon le commentaire de M.Mindor:
System.Reflection.Assembly.GetExecutingAssembly().Location
retourne où se trouve actuellement l'assemblage d'exécution, qui peut ou non être situé là où l'assemblage se trouve lorsqu'il n'est pas en cours d'exécution. Dans le cas des assemblys de copie miroir, vous obtiendrez un chemin dans un répertoire temporaire.System.Reflection.Assembly.GetExecutingAssembly().CodeBase
retournera le chemin «permanent» de l'assemblage.
GetExecutingAssembly
retourne l'assembly qui contient le code en cours d'exécution . Il ne s'agit pas nécessairement de l' assembly .exe de la console . Il peut s'agir d'un assemblage qui a été chargé à partir d'un emplacement totalement différent. Vous devrez utiliser GetEntryAssembly
! Notez également que cela CodeBase
peut ne pas être défini lorsque l'assembly est dans le GAC. La meilleure alternative est AppDomain.CurrentDomain.BaseDirectory
.
Vous pouvez utiliser le code suivant pour obtenir le répertoire d'application actuel.
AppDomain.CurrentDomain.BaseDirectory
BaseDirectory
peut être défini lors de l'exécution? Il n'a qu'un getter.
Vous avez deux options pour trouver le répertoire de l'application, que vous choisirez 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);
var localDirectory = new Uri(directory).LocalPath;
Probablement un peu en retard mais cela vaut la peine d'être mentionné:
Environment.GetCommandLineArgs()[0];
Ou plus correctement pour obtenir uniquement le chemin du répertoire:
System.IO.Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]);
Éditer:
Beaucoup de gens ont souligné qu'il GetCommandLineArgs
n'est pas garanti de retourner 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 pas moi-même)". Il est donc possible de «falsifier» GetCommandLineArgs
, mais nous parlons d'une application console. Les applications de 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 s'exécute physiquement à partir de "C: \ inetpub \ SBSPortal_staging", donc la première solution n'est certainement pas appropriée pour les applications Web.
La réponse ci-dessus était de 90% de ce dont j'avais besoin, mais a renvoyé un Uri au lieu d'un chemin normal pour moi.
Comme expliqué dans le message des forums MSDN, comment convertir le chemin URI en chemin de fichier normal? , J'ai utilisé ce qui suit:
// 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)
ça, cela vous donnera l'exception qu'il n'autorise pas les chemins URI ...
#
caractère). L'identifiant et tout ce qui le suit est tronqué du chemin résultant.
new Uri
et System.IO.Path.GetDirectoryName
? Cela vous donne une chaîne de chemin normale au lieu d'un Uri
.
vous pouvez utiliser celui-ci à la place.
System.Environment.CurrentDirectory
Si vous recherchez un moyen 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: AppContext.BaseDirectory, propriété .
Selon cette page ,
Il s'agit du remplacement préféré d'AppDomain.CurrentDomain.BaseDirectory dans .NET Core
Process.GetCurrentProcess().MainModule.FileName
Pour les applications console, vous pouvez essayer ceci:
System.IO.Directory.GetCurrentDirectory();
Sortie (sur ma machine locale):
c: \ users \ xxxxxxx \ documents \ visual studio 2012 \ Projects \ ImageHandler \ GetDir \ bin \ Debug
Ou vous pouvez essayer (il y a une barre oblique inverse supplémentaire à la fin):
AppDomain.CurrentDomain.BaseDirectory
Production:
c: \ users \ xxxxxxx \ documents \ visual studio 2012 \ Projects \ ImageHandler \ GetDir \ bin \ Debug \
BaseDirectory
peut être réglé au moment de l'exécution. Il n'est PAS garanti d'être correct"
J'ai utilisé ce code et j'ai trouvé la solution.
AppDomain.CurrentDomain.BaseDirectory
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 d'utiliser la réflexion.
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
bundles de Mono (aucune autre méthode ne fonctionne)J'utilise ceci si l'exe est censé être appelé en double-cliquant dessus
var thisPath = System.IO.Directory.GetCurrentDirectory();
j'ai utilisé
System.AppDomain.CurrentDomain.BaseDirectory
quand je veux trouver un chemin par rapport à un dossier d'applications. Cela fonctionne pour les applications ASP.Net et Winform. Il ne nécessite également aucune référence aux assemblys System.Web.
Je veux dire, pourquoi ne pas utiliser la méthode 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());
}
}
}
Vous l'utiliseriez comme Application.StartupPath:
Console.WriteLine("The path to this executable is: " + AppInfo.StartupPath + "\\" + System.Diagnostics.Process.GetCurrentProcess().ProcessName + ".exe");
Assembly.GetEntryAssembly().Location
ou Assembly.GetExecutingAssembly().Location
À utiliser en combinaison avec System.IO.Path.GetDirectoryName()
pour obtenir uniquement le répertoire.
Les chemins depuis 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 être conscient que cela peut retourner null
si le module d'entrée n'est pas géré (c'est-à-dire 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ésoudra le problème pour référencer les fichiers de référence tiers avec les packages d'installation.
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 réel.
Vous pouvez donc 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) + @"\";
}
}
Essayez cette simple ligne de code:
string exePath = Path.GetDirectoryName( Application.ExecutablePath);
Une autre solution consiste à utiliser des chemins relatifs pointant vers le chemin actuel:
Path.GetFullPath(".")
Je n'ai vu personne convertir le LocalPath fourni par la réflexion .Net Core en un chemin System.IO utilisable alors voici 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 d'accès complet au format "C: \ xxx \ xxx" à l'emplacement de votre code.
Il existe de nombreuses façons d'obtenir un chemin exécutable, lequel nous devrions utiliser en fonction de nos besoins. Voici un lien qui décrit différentes méthodes.
Différentes façons d'obtenir le chemin exécutable de l'application
Voici une solution fiable qui fonctionne avec des applications 32 bits et 64 bits .
Ajoutez ces références:
en utilisant System.Diagnostics;
en utilisant System.Management;
Ajoutez cette méthode à votre projet:
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;
}
Maintenant, utilisez-le comme ceci:
int RootProcessId = Process.GetCurrentProcess().Id;
GetProcessPath(RootProcessId);
Notez que si vous connaissez l'id du processus, cette méthode renverra le chemin ExecutePath correspondant.
Extra, pour ceux qui sont intéressés:
Process.GetProcesses()
... vous donnera un tableau de tous les processus en cours d'exécution, et ...
Process.GetCurrentProcess()
... vous donnera le processus en cours, ainsi que leurs informations, par exemple Id, etc. et également un contrôle limité, par exemple Kill, etc. *
Vous pouvez créer un nom de dossier en tant que ressources dans le projet à l'aide de l'Explorateur de solutions, puis vous pouvez coller un fichier dans les ressources.
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);
}