Làm cách nào để tìm đường dẫn của ứng dụng trong ứng dụng bảng điều khiển?
Trong Windows Forms , tôi có thể sử dụng Application.StartupPath
để tìm đường dẫn hiện tại, nhưng dường như điều này không có sẵn trong một ứng dụng bảng điều khiển.
Làm cách nào để tìm đường dẫn của ứng dụng trong ứng dụng bảng điều khiển?
Trong Windows Forms , tôi có thể sử dụng Application.StartupPath
để tìm đường dẫn hiện tại, nhưng dường như điều này không có sẵn trong một ứng dụng bảng điều khiển.
Câu trả lời:
System.Reflection.Assembly.GetExecutingAssembly()
. 1Location
Kết hợp với System.IO.Path.GetDirectoryName
nếu tất cả những gì bạn muốn là thư mục.
1 Theo nhận xét của Mr.Mindor:
System.Reflection.Assembly.GetExecutingAssembly().Location
trả về vị trí lắp ráp thực thi hiện tại, có thể hoặc không thể là nơi lắp ráp được đặt khi không thực hiện. Trong trường hợp tập hợp sao chép bóng, bạn sẽ nhận được một đường dẫn trong thư mục tạm thời.System.Reflection.Assembly.GetExecutingAssembly().CodeBase
sẽ trả lại đường dẫn 'vĩnh viễn' của lắp ráp.
GetExecutingAssembly
trả về lắp ráp có chứa mã hiện đang thực thi . Đây có thể không nhất thiết phải là hội đồng điều khiển .exe . Nó có thể là một hội đồng đã được tải từ một vị trí hoàn toàn khác. Bạn sẽ phải sử dụng GetEntryAssembly
! Cũng lưu ý rằng CodeBase
có thể không được đặt khi lắp ráp trong GAC. Sự thay thế tốt hơn là AppDomain.CurrentDomain.BaseDirectory
.
Bạn có thể sử dụng đoạn mã sau để lấy thư mục ứng dụng hiện tại.
AppDomain.CurrentDomain.BaseDirectory
BaseDirectory
có thể được đặt trong thời gian chạy? Nó chỉ có một getter.
Bạn có hai tùy chọn để tìm thư mục của ứng dụng mà bạn chọn sẽ phụ thuộc vào mục đích của bạn.
// 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;
Có lẽ hơi muộn nhưng điều này đáng được đề cập:
Environment.GetCommandLineArgs()[0];
Hay chính xác hơn là chỉ lấy đường dẫn thư mục:
System.IO.Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]);
Biên tập:
Khá nhiều người đã chỉ ra rằng GetCommandLineArgs
không đảm bảo trả lại tên chương trình. Xem Từ đầu tiên trên dòng lệnh là tên chương trình chỉ theo quy ước . Bài báo viết rằng "Mặc dù rất ít chương trình Windows sử dụng cách giải quyết này (tôi không biết về bản thân mình)". Vì vậy, có thể 'giả mạo' GetCommandLineArgs
, nhưng chúng ta đang nói về một ứng dụng giao diện điều khiển. Các ứng dụng Console thường nhanh và bẩn. Vì vậy, điều này phù hợp với triết lý KISS của tôi.
Đối với bất cứ ai quan tâm đến các ứng dụng web asp.net. Dưới đây là kết quả của tôi về 3 phương pháp khác nhau
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);
}
kết quả
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
ứng dụng đang chạy thực tế từ "C: \ inetpub \ SBSPortal_staging", vì vậy giải pháp đầu tiên chắc chắn không phù hợp với các ứng dụng web.
Câu trả lời ở trên là 90% những gì tôi cần, nhưng đã trả lại một Uri thay vì một con đường thông thường cho tôi.
Như đã giải thích trong bài đăng trên diễn đàn MSDN, Làm thế nào để chuyển đổi đường dẫn URI thành filepath bình thường? , Tôi đã sử dụng như sau:
// 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)
, nó sẽ cho bạn ngoại lệ rằng nó không cho phép các đường dẫn URI ...
#
ký tự). Mã định danh và mọi thứ theo sau nó được cắt từ đường dẫn kết quả.
new Uri
và System.IO.Path.GetDirectoryName
? Điều đó cung cấp cho bạn một chuỗi đường dẫn bình thường thay vì a Uri
.
bạn có thể sử dụng cái này thay thế
System.Environment.CurrentDirectory
Nếu bạn đang tìm kiếm một cách tương thích .NET Core, hãy sử dụng
System.AppContext.BaseDirectory
Điều này đã được giới thiệu trong .NET Framework 4.6 và .NET Core 1.0 (và .NET Standard 1.3). Xem: Thuộc tính AppContext.BaseDirectory .
Theo trang này ,
Đây là sự thay thế ưa thích cho AppDomain.CienDomain.BaseDirectory trong .NET Core
Process.GetCurrentProcess().MainModule.FileName
Đối với Ứng dụng Bảng điều khiển, bạn có thể thử điều này:
System.IO.Directory.GetCurrentDirectory();
Đầu ra (trên máy cục bộ của tôi):
c: \ users \ xxxxxxx \ Documents \ visual studio 2012 \ Project \ ImageHandler \ GetDir \ bin \ Debug
Hoặc bạn có thể thử (cuối cùng có một dấu gạch chéo ngược):
AppDomain.CurrentDomain.BaseDirectory
Đầu ra:
c: \ users \ xxxxxxx \ Documents \ visual studio 2012 \ Project \ ImageHandler \ GetDir \ bin \ Debug \
BaseDirectory
thể được đặt trong thời gian chạy. Nó không được đảm bảo là chính xác"
Tôi đã sử dụng mã này và nhận được giải pháp.
AppDomain.CurrentDomain.BaseDirectory
Bạn chỉ có thể thêm vào tài liệu tham khảo dự án của bạn System.Windows.Forms
và sau đó sử dụng System.Windows.Forms.Application.StartupPath
như bình thường.
Vì vậy, không cần cho các phương pháp phức tạp hơn hoặc sử dụng sự phản ánh.
Dòng sau sẽ cung cấp cho bạn một đường dẫn ứng dụng:
var applicationPath = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName)
Giải pháp trên đang hoạt động đúng trong các tình huống sau:
mkbundle
các gói của Mono (không có phương pháp nào khác hoạt động)Tôi sử dụng điều này nếu exe được gọi là bằng cách nhấp đúp vào nó
var thisPath = System.IO.Directory.GetCurrentDirectory();
tôi đã sử dụng
System.AppDomain.CurrentDomain.BaseDirectory
khi tôi muốn tìm một đường dẫn liên quan đến một thư mục ứng dụng. Điều này hoạt động cho cả hai ứng dụng ASP.Net và winform. Nó cũng không yêu cầu bất kỳ tham chiếu nào đến các hội đồng System.Web.
Ý tôi là, tại sao không phương thức 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());
}
}
}
Bạn sẽ sử dụng nó giống như Application.StartupPath:
Console.WriteLine("The path to this executable is: " + AppInfo.StartupPath + "\\" + System.Diagnostics.Process.GetCurrentProcess().ProcessName + ".exe");
Assembly.GetEntryAssembly().Location
hoặc là Assembly.GetExecutingAssembly().Location
Sử dụng kết hợp với System.IO.Path.GetDirectoryName()
để chỉ nhận được thư mục.
Các đường dẫn từ GetEntryAssembly()
và GetExecutingAssembly()
có thể khác nhau, mặc dù trong hầu hết các trường hợp, thư mục sẽ giống nhau.
Với GetEntryAssembly()
bạn phải lưu ý rằng điều này có thể trở lại null
nếu mô-đun nhập không được quản lý (tức là thực thi C ++ hoặc VB6). Trong những trường hợp đó, có thể sử dụng GetModuleFileName
từ API Win32:
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetModuleFileName(HandleRef hModule, StringBuilder buffer, int length);
AppDomain.CurrentDomain.BaseDirectory
Sẽ giải quyết vấn đề để giới thiệu các tệp tham chiếu của bên thứ 3 với các gói cài đặt.
Không có phương pháp nào trong số này hoạt động trong các trường hợp đặc biệt như sử dụng liên kết tượng trưng đến exe, chúng sẽ trả về vị trí của liên kết chứ không phải exe thực tế.
Vì vậy, có thể sử dụng QueryFullProcessImageName để khắc phục điều đó:
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) + @"\";
}
}
Hãy thử dòng mã đơn giản này:
string exePath = Path.GetDirectoryName( Application.ExecutablePath);
Một giải pháp khác là sử dụng các đường dẫn tương đối trỏ đến đường dẫn hiện tại:
Path.GetFullPath(".")
Tôi không thấy ai chuyển đổi LocalPath được cung cấp bởi sự phản chiếu .Net Core thành đường dẫn System.IO có thể sử dụng được nên đây là phiên bản của tôi.
public static string GetApplicationRoot()
{
var exePath = new Uri(System.Reflection.
Assembly.GetExecutingAssembly().CodeBase).LocalPath;
return new FileInfo(exePath).DirectoryName;
}
Điều này sẽ trả lại đường dẫn được định dạng "C: \ xxx \ xxx" đầy đủ đến nơi mã của bạn.
Có nhiều cách để có được đường dẫn thực thi, cái nào chúng ta nên sử dụng nó phụ thuộc vào nhu cầu của chúng ta ở đây là một liên kết thảo luận về các phương thức khác nhau.
Đây là một giải pháp đáng tin cậy hoạt động với các ứng dụng 32 bit và 64 bit .
Thêm các tài liệu tham khảo:
sử dụng System.Diagnostics;
sử dụng System.Man Management;
Thêm phương pháp này vào dự án của bạn:
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;
}
Bây giờ sử dụng nó như vậy:
int RootProcessId = Process.GetCurrentProcess().Id;
GetProcessPath(RootProcessId);
Lưu ý rằng nếu bạn biết id của tiến trình, thì phương thức này sẽ trả về ExecutePath tương ứng.
Thêm, cho những người quan tâm:
Process.GetProcesses()
... sẽ cung cấp cho bạn một mảng của tất cả các quy trình hiện đang chạy và ...
Process.GetCurrentProcess()
... sẽ cung cấp cho bạn quy trình hiện tại, cùng với thông tin của họ, ví dụ như Id, v.v. và cả kiểm soát hạn chế, ví dụ: Kill, v.v. *
Bạn có thể tạo tên thư mục là Tài nguyên trong dự án bằng Solution Explorer, sau đó bạn có thể dán tệp trong Tài nguyên.
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);
}