Jak znaleźć ścieżkę aplikacji w aplikacji konsoli?
W Windows Forms mogę użyć Application.StartupPath
do znalezienia bieżącej ścieżki, ale wydaje się, że nie jest ona dostępna w aplikacji konsolowej.
Jak znaleźć ścieżkę aplikacji w aplikacji konsoli?
W Windows Forms mogę użyć Application.StartupPath
do znalezienia bieżącej ścieżki, ale wydaje się, że nie jest ona dostępna w aplikacji konsolowej.
Odpowiedzi:
System.Reflection.Assembly.GetExecutingAssembly()
. 1Location
Połącz to z, System.IO.Path.GetDirectoryName
jeśli wszystko, czego chcesz, to katalog.
1 Zgodnie z komentarzem Mr.Mindor:
System.Reflection.Assembly.GetExecutingAssembly().Location
zwraca miejsce, w którym aktualnie znajduje się zespół wykonujący, który może, ale nie musi być, gdzie znajduje się zespół, gdy nie jest wykonywany. W przypadku zestawów kopiujących w tle otrzymasz ścieżkę do katalogu tymczasowego.System.Reflection.Assembly.GetExecutingAssembly().CodeBase
zwróci „stałą” ścieżkę zestawu.
GetExecutingAssembly
zwraca zestaw, który zawiera aktualnie wykonywany kod . To niekoniecznie musi być zestaw .exe konsoli . Może to być zespół, który został załadowany z zupełnie innej lokalizacji. Będziesz musiał użyć GetEntryAssembly
! Należy również pamiętać, że CodeBase
może nie być ustawiony, gdy zestaw znajduje się w GAC. Lepszą alternatywą jest AppDomain.CurrentDomain.BaseDirectory
.
Możesz użyć następującego kodu, aby uzyskać bieżący katalog aplikacji.
AppDomain.CurrentDomain.BaseDirectory
BaseDirectory
można to ustawić w czasie wykonywania? Ma tylko getter.
Masz dwie opcje znalezienia katalogu aplikacji, który wybierzesz zależy od celu.
// 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;
Prawdopodobnie trochę późno, ale warto o tym wspomnieć:
Environment.GetCommandLineArgs()[0];
Lub bardziej poprawnie, aby uzyskać tylko ścieżkę do katalogu:
System.IO.Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]);
Edytować:
Sporo osób zauważyło, że GetCommandLineArgs
nie ma gwarancji zwrócenia nazwy programu. Zobacz Pierwsze słowo w wierszu poleceń to nazwa programu tylko zgodnie z konwencją . Artykuł stwierdza, że „Chociaż bardzo niewiele programów Windows używa tego dziwactwa (sam nie jestem świadomy)”. Można więc „sfałszować” GetCommandLineArgs
, ale mówimy o aplikacji konsolowej. Aplikacje konsolowe są zwykle szybkie i brudne. To pasuje do mojej filozofii KISS.
Dla wszystkich zainteresowanych aplikacjami internetowymi asp.net. Oto moje wyniki 3 różnych metod
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);
}
wynik
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
aplikacja działa fizycznie z „C: \ inetpub \ SBSPortal_staging”, więc pierwsze rozwiązanie zdecydowanie nie jest odpowiednie dla aplikacji internetowych.
Powyższa odpowiedź wyniosła 90% tego, czego potrzebowałem, ale zwróciło mi Uri zamiast zwykłej ścieżki dla mnie.
Jak wyjaśniono w poście na forach MSDN, jak przekonwertować ścieżkę URI na normalną ścieżkę do pliku? , Użyłem następujących:
// 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)
, da ci wyjątek, że nie zezwala na ścieżki URI ...
#
znak). Identyfikator i wszystko po nim jest obcinane ze ścieżki wynikowej.
new Uri
i System.IO.Path.GetDirectoryName
? To daje normalny ciąg ścieżki zamiast Uri
.
możesz zamiast tego użyć tego.
System.Environment.CurrentDirectory
Jeśli szukasz sposobu zgodnego z .NET Core, użyj
System.AppContext.BaseDirectory
Zostało to wprowadzone w .NET Framework 4.6 i .NET Core 1.0 (i .NET Standard 1.3). Zobacz: Właściwość AppContext.BaseDirectory .
Według tej strony ,
Jest to preferowany zamiennik AppDomain.CurrentDomain.BaseDirectory w .NET Core
Process.GetCurrentProcess().MainModule.FileName
W przypadku aplikacji konsolowych możesz spróbować:
System.IO.Directory.GetCurrentDirectory();
Dane wyjściowe (na moim komputerze lokalnym):
c: \ users \ xxxxxxx \ dokumenty \ visual studio 2012 \ Projekty \ ImageHandler \ GetDir \ bin \ Debug
Lub możesz spróbować (na końcu jest dodatkowy ukośnik odwrotny):
AppDomain.CurrentDomain.BaseDirectory
Wynik:
c: \ users \ xxxxxxx \ dokumenty \ visual studio 2012 \ Projekty \ ImageHandler \ GetDir \ bin \ Debug \
BaseDirectory
Można to ustawić w środowisku uruchomieniowym. NIE gwarantuje się poprawności”
Użyłem tego kodu i otrzymałem rozwiązanie.
AppDomain.CurrentDomain.BaseDirectory
Możesz po prostu dodać do referencji do projektu, System.Windows.Forms
a następnie użyć System.Windows.Forms.Application.StartupPath
jak zwykle.
Nie potrzeba więc bardziej skomplikowanych metod ani korzystania z odbicia.
Używam tego, jeśli exe ma zostać wywołany przez podwójne kliknięcie
var thisPath = System.IO.Directory.GetCurrentDirectory();
używałem
System.AppDomain.CurrentDomain.BaseDirectory
kiedy chcę znaleźć ścieżkę względem folderu aplikacji. Działa to zarówno dla aplikacji ASP.Net, jak i winform. Nie wymaga również żadnego odniesienia do zestawów System.Web.
Następująca linia poda ścieżkę aplikacji:
var applicationPath = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName)
Powyższe rozwiązanie działa poprawnie w następujących sytuacjach:
mkbundle
(żadne inne metody nie działają)Mam na myśli, dlaczego nie zastosować metody 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());
}
}
}
Użyłbyś go tak jak Application.StartupPath:
Console.WriteLine("The path to this executable is: " + AppInfo.StartupPath + "\\" + System.Diagnostics.Process.GetCurrentProcess().ProcessName + ".exe");
Assembly.GetEntryAssembly().Location
lub Assembly.GetExecutingAssembly().Location
Użyj w połączeniu z, System.IO.Path.GetDirectoryName()
aby uzyskać tylko katalog.
Te ścieżki GetEntryAssembly()
i GetExecutingAssembly()
mogą być różne, chociaż w większości przypadków katalog będzie taka sama.
Ze GetEntryAssembly()
trzeba mieć świadomość, że to może powrócić null
, gdy moduł wejścia jest niekontrolowana (czyli C ++ lub VB6 wykonywalny). W takich przypadkach można korzystać GetModuleFileName
z interfejsu API Win32:
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetModuleFileName(HandleRef hModule, StringBuilder buffer, int length);
AppDomain.CurrentDomain.BaseDirectory
Rozwiązuje problem polegający na odsyłaniu plików referencyjnych innych firm z pakietami instalacyjnymi.
Żadna z tych metod nie działa w szczególnych przypadkach, takich jak użycie dowiązania symbolicznego do pliku exe, zwracają one lokalizację łącza, a nie faktyczny plik exe.
Więc można użyć QueryFullProcessImageName, aby obejść ten problem :
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) + @"\";
}
}
Wypróbuj tę prostą linię kodu:
string exePath = Path.GetDirectoryName( Application.ExecutablePath);
Innym rozwiązaniem jest użycie ścieżek względnych wskazujących bieżącą ścieżkę:
Path.GetFullPath(".")
Nie widziałem, żeby ktokolwiek konwertował ścieżkę LocalPath dostarczoną przez odbicie .Net Core na użyteczną ścieżkę System.IO, więc oto moja wersja.
public static string GetApplicationRoot()
{
var exePath = new Uri(System.Reflection.
Assembly.GetExecutingAssembly().CodeBase).LocalPath;
return new FileInfo(exePath).DirectoryName;
}
Zwróci to pełną ścieżkę w formacie „C: \ xxx \ xxx” do miejsca, w którym znajduje się kod.
Istnieje wiele sposobów na uzyskanie ścieżki wykonywalnej, z której powinniśmy skorzystać, zależnie od naszych potrzeb. Link do dyskusji na temat różnych metod.
Oto niezawodne rozwiązanie, które działa z aplikacjami 32 - bitowymi i 64 - bitowymi .
Dodaj te referencje:
using System.Diagnostics;
using System.Management;
Dodaj tę metodę do swojego projektu:
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;
}
Teraz użyj go w następujący sposób:
int RootProcessId = Process.GetCurrentProcess().Id;
GetProcessPath(RootProcessId);
Zauważ, że jeśli znasz identyfikator procesu, ta metoda zwróci odpowiednią ścieżkę ExecutePath.
Dodatkowo dla zainteresowanych:
Process.GetProcesses()
... da ci tablicę wszystkich aktualnie uruchomionych procesów i ...
Process.GetCurrentProcess()
... da ci bieżący proces, wraz z jego informacjami, np. Id, itp., a także ograniczoną kontrolę, np. Kill itp. *
Możesz utworzyć nazwę folderu jako Zasoby w projekcie za pomocą Eksploratora rozwiązań, a następnie możesz wkleić plik w Zasobach.
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);
}