Bagaimana cara menemukan jalur aplikasi di aplikasi konsol?
Di Windows Forms , saya dapat menggunakan Application.StartupPath
untuk menemukan jalur saat ini, tetapi ini sepertinya tidak tersedia di aplikasi konsol.
Bagaimana cara menemukan jalur aplikasi di aplikasi konsol?
Di Windows Forms , saya dapat menggunakan Application.StartupPath
untuk menemukan jalur saat ini, tetapi ini sepertinya tidak tersedia di aplikasi konsol.
Jawaban:
System.Reflection.Assembly.GetExecutingAssembly()
. 1Location
Kombinasikan dengan System.IO.Path.GetDirectoryName
jika yang Anda inginkan adalah direktori.
1 Sesuai komentar Mr.Mindor:
System.Reflection.Assembly.GetExecutingAssembly().Location
mengembalikan tempat majelis pelaksana saat ini berada, yang mungkin atau mungkin tidak di mana majelis berada saat tidak menjalankan. Dalam kasus rakitan penyalinan bayangan, Anda akan mendapatkan lintasan di direktori temp.System.Reflection.Assembly.GetExecutingAssembly().CodeBase
akan mengembalikan jalur 'permanen' majelis.
GetExecutingAssembly
mengembalikan perakitan yang berisi kode yang saat ini dieksekusi . Ini mungkin belum tentu merupakan konsol .exe . Mungkin perakitan yang telah dimuat dari lokasi yang sama sekali berbeda. Anda harus menggunakan GetEntryAssembly
! Perhatikan juga bahwa CodeBase
mungkin tidak diatur ketika perakitan di GAC. Alternatif yang lebih baik adalah AppDomain.CurrentDomain.BaseDirectory
.
Anda dapat menggunakan kode berikut untuk mendapatkan direktori aplikasi saat ini.
AppDomain.CurrentDomain.BaseDirectory
BaseDirectory
dapat diatur saat runtime? Ini hanya memiliki rajin dan giat.
Anda memiliki dua opsi untuk menemukan direktori aplikasi, yang Anda pilih tergantung pada tujuan Anda.
// 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;
Mungkin agak terlambat tapi ini layak disebutkan:
Environment.GetCommandLineArgs()[0];
Atau lebih tepatnya untuk mendapatkan hanya jalur direktori:
System.IO.Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]);
Edit:
Beberapa orang telah menunjukkan bahwa GetCommandLineArgs
tidak dijamin untuk mengembalikan nama program. Lihat Kata pertama pada baris perintah adalah nama program hanya dengan konvensi . Artikel itu menyatakan bahwa "Meskipun sangat sedikit program Windows menggunakan kekhasan ini (saya sendiri tidak mengetahui adanya)". Jadi dimungkinkan untuk 'spoof' GetCommandLineArgs
, tetapi kita berbicara tentang aplikasi konsol. Aplikasi konsol biasanya cepat dan kotor. Jadi ini cocok dengan filosofi KISS saya.
Bagi siapa pun yang tertarik dengan aplikasi web asp.net. Berikut adalah hasil saya dari 3 metode berbeda
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);
}
hasil
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
aplikasi ini berjalan secara fisik dari "C: \ inetpub \ SBSPortal_staging", jadi solusi pertama jelas tidak sesuai untuk aplikasi web.
Jawaban di atas adalah 90% dari yang saya butuhkan, tetapi mengembalikan Uri alih-alih jalur reguler untuk saya.
Seperti yang dijelaskan dalam posting forum MSDN, Bagaimana cara mengubah jalur URI ke file normal? , Saya menggunakan yang berikut ini:
// 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)
, itu akan memberi Anda pengecualian bahwa itu tidak memungkinkan jalur URI ...
#
karakter). Identifier dan semua yang mengikutinya terpotong dari jalur yang dihasilkan.
new Uri
dan System.IO.Path.GetDirectoryName
? Itu memberi Anda string jalur normal, bukan a Uri
.
Anda dapat menggunakan yang ini sebagai gantinya.
System.Environment.CurrentDirectory
Jika Anda mencari cara .NET Core yang kompatibel, gunakan
System.AppContext.BaseDirectory
Ini diperkenalkan di .NET Framework 4.6 dan .NET Core 1.0 (dan .NET Standard 1.3). Lihat: AppContext.BaseDirectory Property .
Menurut halaman ini ,
Ini adalah pengganti yang lebih disukai untuk AppDomain.CurrentDomain.BaseDirectory di .NET Core
Process.GetCurrentProcess().MainModule.FileName
Untuk Aplikasi Konsol, Anda dapat mencoba ini:
System.IO.Directory.GetCurrentDirectory();
Output (pada mesin lokal saya):
c: \ users \ xxxxxxx \ document \ visual studio 2012 \ Projects \ ImageHandler \ GetDir \ bin \ Debug
Atau Anda dapat mencoba (ada backslash tambahan pada akhirnya):
AppDomain.CurrentDomain.BaseDirectory
Keluaran:
c: \ users \ xxxxxxx \ document \ visual studio 2012 \ Projects \ ImageHandler \ GetDir \ bin \ Debug \
BaseDirectory
Dapat diatur saat runtime. TIDAK dijamin benar"
Saya telah menggunakan kode ini dan mendapatkan solusinya.
AppDomain.CurrentDomain.BaseDirectory
Anda cukup menambahkan referensi proyek Anda System.Windows.Forms
dan kemudian menggunakan System.Windows.Forms.Application.StartupPath
seperti biasa.
Jadi, tidak perlu metode yang lebih rumit atau menggunakan refleksi.
Baris berikut akan memberi Anda jalur aplikasi:
var applicationPath = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName)
Solusi di atas berfungsi dengan baik dalam situasi berikut:
mkbundle
bundel Mono (tidak ada metode lain yang berfungsi)Saya menggunakan ini jika exe seharusnya dipanggil dengan mengklik dua kali
var thisPath = System.IO.Directory.GetCurrentDirectory();
Saya sudah menggunakan
System.AppDomain.CurrentDomain.BaseDirectory
ketika saya ingin mencari jalur relatif ke folder aplikasi. Ini berfungsi baik untuk aplikasi ASP.Net maupun winform. Itu juga tidak memerlukan referensi ke System.Web rakitan.
Maksud saya, mengapa tidak ap / memanggil metode?
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());
}
}
}
Anda akan menggunakannya seperti Application.StartupPath:
Console.WriteLine("The path to this executable is: " + AppInfo.StartupPath + "\\" + System.Diagnostics.Process.GetCurrentProcess().ProcessName + ".exe");
Assembly.GetEntryAssembly().Location
atau Assembly.GetExecutingAssembly().Location
Gunakan bersama dengan System.IO.Path.GetDirectoryName()
untuk mendapatkan hanya direktori.
Path dari GetEntryAssembly()
dan GetExecutingAssembly()
dapat berbeda, meskipun untuk sebagian besar kasus direktori akan sama.
Dengan GetEntryAssembly()
Anda harus menyadari bahwa ini dapat kembali null
jika modul entri tidak dikelola (yaitu C ++ atau VB6 dapat dieksekusi). Dalam kasus tersebut, dimungkinkan untuk menggunakan GetModuleFileName
dari Win32 API:
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetModuleFileName(HandleRef hModule, StringBuilder buffer, int length);
AppDomain.CurrentDomain.BaseDirectory
Akan menyelesaikan masalah untuk merujuk file referensi pihak ke-3 dengan paket instalasi.
Tidak satu pun dari metode ini bekerja dalam kasus khusus seperti menggunakan tautan simbolis ke exe, mereka akan mengembalikan lokasi tautan bukan exe yang sebenarnya.
Jadi dapat menggunakan QueryFullProcessImageName untuk menyiasati itu:
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) + @"\";
}
}
Coba baris kode sederhana ini:
string exePath = Path.GetDirectoryName( Application.ExecutablePath);
Solusi lain adalah menggunakan jalur relatif yang menunjuk ke jalur saat ini:
Path.GetFullPath(".")
Saya tidak melihat siapa pun mengonversi LocalPath yang disediakan oleh .Net Core refleksi ke jalur System.IO yang dapat digunakan jadi inilah versi saya.
public static string GetApplicationRoot()
{
var exePath = new Uri(System.Reflection.
Assembly.GetExecutingAssembly().CodeBase).LocalPath;
return new FileInfo(exePath).DirectoryName;
}
Ini akan mengembalikan path lengkap yang diformat "C: \ xxx \ xxx" ke tempat kode Anda.
Ada banyak cara untuk mendapatkan jalur yang dapat dieksekusi, yang mana yang harus kita gunakan tergantung pada kebutuhan kita di sini adalah tautan yang membahas berbagai metode.
Berikut ini adalah solusi andal yang bekerja dengan 32bit dan 64bit aplikasi .
Tambahkan referensi ini:
menggunakan System.Diagnostics;
menggunakan System.Management;
Tambahkan metode ini ke proyek Anda:
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;
}
Sekarang gunakan seperti ini:
int RootProcessId = Process.GetCurrentProcess().Id;
GetProcessPath(RootProcessId);
Perhatikan bahwa jika Anda mengetahui id proses, maka metode ini akan mengembalikan ExecutePath yang sesuai.
Ekstra, bagi yang berminat:
Process.GetProcesses()
... akan memberi Anda array dari semua proses yang sedang berjalan, dan ...
Process.GetCurrentProcess()
... akan memberi Anda proses saat ini, bersama dengan informasi mereka misalnya Id, dll. dan juga kendali terbatas mis. Kill, dll. *
Anda dapat membuat nama folder sebagai Sumber Daya dalam proyek menggunakan Solution Explorer, lalu Anda dapat menempelkan file di dalam Sumber Daya.
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);
}