ฉันจะค้นหาเส้นทางของแอปพลิเคชันในแอปพลิเคชันคอนโซลได้อย่างไร
ในWindows Formsฉันสามารถใช้Application.StartupPath
เพื่อค้นหาเส้นทางปัจจุบัน แต่ดูเหมือนจะไม่สามารถใช้ได้ในแอปพลิเคชันคอนโซล
ฉันจะค้นหาเส้นทางของแอปพลิเคชันในแอปพลิเคชันคอนโซลได้อย่างไร
ในWindows Formsฉันสามารถใช้Application.StartupPath
เพื่อค้นหาเส้นทางปัจจุบัน แต่ดูเหมือนจะไม่สามารถใช้ได้ในแอปพลิเคชันคอนโซล
คำตอบ:
System.Reflection.Assembly.GetExecutingAssembly()
. 1Location
รวมกับSystem.IO.Path.GetDirectoryName
ถ้าทั้งหมดที่คุณต้องการคือไดเรกทอรี
1 ตามความคิดเห็นของ Mr.Mindor:
System.Reflection.Assembly.GetExecutingAssembly().Location
ส่งคืนที่แอสเซมบลีที่กำลังดำเนินการอยู่ซึ่งอาจหรือไม่อาจเป็นที่แอสเซมบลีที่ตั้งอยู่เมื่อไม่ดำเนินการ ในกรณีของชุดประกอบการคัดลอกเงาคุณจะได้รับเส้นทางในไดเรกทอรีชั่วคราวSystem.Reflection.Assembly.GetExecutingAssembly().CodeBase
จะกลับเส้นทาง 'ถาวร' ของแอสเซมบลี
GetExecutingAssembly
ส่งกลับแอสเซมบลีที่ประกอบด้วยรหัสที่กำลังดำเนินการอยู่ ซึ่งอาจไม่จำเป็นต้องเป็นชุดประกอบของ. exe มันอาจเป็นชุดประกอบที่ถูกโหลดจากตำแหน่งที่แตกต่างกันโดยสิ้นเชิง คุณจะต้องใช้GetEntryAssembly
! โปรดทราบด้วยว่าCodeBase
อาจไม่สามารถตั้งค่าได้เมื่อการชุมนุมอยู่ใน GAC AppDomain.CurrentDomain.BaseDirectory
ทางเลือกที่ดีกว่าคือ
คุณสามารถใช้รหัสต่อไปนี้เพื่อรับไดเรกทอรีแอปพลิเคชันปัจจุบัน
AppDomain.CurrentDomain.BaseDirectory
BaseDirectory
สามารถตั้งค่าได้ที่ runtime? มันมีเพียงทะเยอทะยาน
คุณมีสองตัวเลือกในการค้นหาไดเรกทอรีของแอปพลิเคชันซึ่งคุณเลือกจะขึ้นอยู่กับวัตถุประสงค์ของคุณ
// 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;
อาจจะช้าไปหน่อย แต่ก็คุ้มค่าที่จะกล่าวถึง:
Environment.GetCommandLineArgs()[0];
หรืออย่างถูกต้องมากขึ้นเพื่อรับเส้นทางไดเรกทอรี:
System.IO.Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]);
แก้ไข:
มีบางคนที่ชี้ให้เห็นว่าGetCommandLineArgs
ไม่รับประกันว่าจะคืนชื่อโปรแกรม ดูคำแรกในบรรทัดคำสั่งคือชื่อโปรแกรมโดยการประชุมเท่านั้น บทความกล่าวว่า "แม้ว่าโปรแกรม Windows บางโปรแกรมเท่านั้นที่ใช้การเล่นโวหารนี้ (ฉันไม่รู้ตัวเลย)" ดังนั้นจึงเป็นไปได้ที่จะ 'หลอก' GetCommandLineArgs
แต่เรากำลังพูดถึงคอนโซลแอปพลิเคชัน แอปคอนโซลมักจะรวดเร็วและสกปรก ดังนั้นสิ่งนี้จึงสอดคล้องกับปรัชญา KISS ของฉัน
สำหรับทุกคนที่สนใจแอปเว็บ asp.net นี่คือผลลัพธ์ของฉันจาก 3 วิธีที่แตกต่างกัน
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);
}
ผลลัพธ์
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
แอปพลิเคชันทำงานจาก "C: \ inetpub \ SBSPortal_staging" ดังนั้นทางออกแรกจึงไม่เหมาะสำหรับเว็บแอป
คำตอบข้างต้นคือ 90% ของสิ่งที่ฉันต้องการ แต่คืน Uri แทนเส้นทางปกติสำหรับฉัน
ตามที่อธิบายไว้ในโพสต์ฟอรัม MSDN จะแปลงพา ธ URI เป็น filepath ปกติได้อย่างไร ฉันใช้สิ่งต่อไปนี้:
// 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)
มันจะให้คุณยกเว้นว่ามันไม่อนุญาตให้ใช้เส้นทางของ URI ...
#
อักขระ) ตัวระบุและทุกสิ่งที่ตามมาจะถูกตัดทอนจากเส้นทางที่เกิดขึ้น
new Uri
และSystem.IO.Path.GetDirectoryName
? นั่นจะให้สตริงพา ธ ปกติกับUri
คุณ
คุณอาจต้องการทำสิ่งนี้:
System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)
คุณสามารถใช้อันนี้แทน
System.Environment.CurrentDirectory
หากคุณกำลังมองหาวิธีที่เข้ากันได้กับ. NET Core ให้ใช้
System.AppContext.BaseDirectory
สิ่งนี้ถูกนำมาใช้ใน. NET Framework 4.6 และ. NET Core 1.0 (และ. NET Standard 1.3) ดู: AppContext.BaseDirectory ทรัพย์สิน
ตามหน้านี้ ,
นี่คือการแทนที่ที่ต้องการสำหรับ AppDomain.CurrentDomain.BaseDirectory ใน. NET Core
Process.GetCurrentProcess().MainModule.FileName
สำหรับแอปพลิเคชั่นคอนโซลคุณสามารถลอง:
System.IO.Directory.GetCurrentDirectory();
เอาท์พุท (บนเครื่องท้องถิ่นของฉัน):
c: \ users \ xxxxxxx \ Documents \ visual studio 2012 \ Projects \ ImageHandler \ GetDir \ bin \ Debug
หรือคุณสามารถลอง (มีแบ็กสแลชเพิ่มเติมในตอนท้าย):
AppDomain.CurrentDomain.BaseDirectory
เอาท์พุท:
c: \ users \ xxxxxxx \ Documents \ visual studio 2012 \ Projects \ ImageHandler \ GetDir \ bin \ Debug \
BaseDirectory
สามารถตั้งค่าที่ runtime ไม่รับประกันว่าจะถูกต้อง"
ฉันใช้รหัสนี้และได้รับการแก้ไข
AppDomain.CurrentDomain.BaseDirectory
คุณสามารถเพิ่มการอ้างอิงโครงการของคุณSystem.Windows.Forms
แล้วใช้System.Windows.Forms.Application.StartupPath
ตามปกติ
ดังนั้นไม่จำเป็นต้องใช้วิธีการที่ซับซ้อนมากขึ้นหรือใช้การสะท้อนกลับ
ฉันใช้มันถ้า exe ควรจะถูกเรียกโดยดับเบิลคลิก
var thisPath = System.IO.Directory.GetCurrentDirectory();
ฉันได้ใช้
System.AppDomain.CurrentDomain.BaseDirectory
เมื่อฉันต้องการค้นหาพา ธ ที่สัมพันธ์กับโฟลเดอร์แอปพลิเคชัน สิ่งนี้ใช้ได้กับทั้งแอปพลิเคชัน ASP.Net และ winform นอกจากนี้ยังไม่ต้องการการอ้างอิงใด ๆ ถึงแอสเซมบลี System.Web
บรรทัดต่อไปนี้จะให้เส้นทางแอปพลิเคชันแก่คุณ:
var applicationPath = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName)
วิธีการแก้ปัญหาข้างต้นทำงานอย่างถูกต้องในสถานการณ์ต่อไปนี้:
mkbundle
รวมกลุ่มของโมโน(ไม่มีวิธีการอื่นที่ใช้งานได้)ฉันหมายความว่าทำไมไม่ใช้วิธี 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());
}
}
}
คุณจะใช้มันเหมือนกับ Application.StartupPath:
Console.WriteLine("The path to this executable is: " + AppInfo.StartupPath + "\\" + System.Diagnostics.Process.GetCurrentProcess().ProcessName + ".exe");
Assembly.GetEntryAssembly().Location
หรือ Assembly.GetExecutingAssembly().Location
ใช้ร่วมกับSystem.IO.Path.GetDirectoryName()
เพื่อให้ได้ไดเรกทอรีเท่านั้น
เส้นทางจากGetEntryAssembly()
และGetExecutingAssembly()
อาจแตกต่างกันแม้ว่าในกรณีส่วนใหญ่ไดเรกทอรีจะเหมือนกัน
ด้วยGetEntryAssembly()
คุณต้องระวังว่าสิ่งนี้สามารถส่งคืนnull
หากโมดูลรายการไม่ได้รับการจัดการ (เช่น C ++ หรือ VB6 ปฏิบัติการ) ในกรณีเหล่านั้นเป็นไปได้ที่จะใช้GetModuleFileName
จาก Win32 API:
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetModuleFileName(HandleRef hModule, StringBuilder buffer, int length);
ใน VB.net
My.Application.Info.DirectoryPath
เหมาะกับฉัน (Application Type: Class Library) ไม่แน่ใจเกี่ยวกับ C # ... ส่งคืนพา ธ ที่ไม่มีชื่อไฟล์เป็นสตริง
AppDomain.CurrentDomain.BaseDirectory
จะแก้ไขปัญหาให้อ้างอิงไฟล์อ้างอิงบุคคลที่สามพร้อมแพ็คเกจการติดตั้ง
ไม่มีวิธีการเหล่านี้ทำงานในกรณีพิเศษเช่นการใช้ลิงก์สัญลักษณ์ไปยัง exe พวกเขาจะคืนตำแหน่งของลิงก์ไม่ใช่ exe จริง
ดังนั้นสามารถใช้QueryFullProcessImageNameเพื่อหลีกเลี่ยง:
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) + @"\";
}
}
ลองใช้โค้ดที่เรียบง่ายนี้:
string exePath = Path.GetDirectoryName( Application.ExecutablePath);
โซลูชันอื่นกำลังใช้พา ธ สัมพัทธ์ที่ชี้ไปยังพา ธ ปัจจุบัน:
Path.GetFullPath(".")
ฉันไม่เห็นใครแปลง LocalPath ที่จัดหาโดย. Net Core reflection ไปเป็นเส้นทาง System.IO ที่ใช้งานได้ดังนั้นนี่คือเวอร์ชันของฉัน
public static string GetApplicationRoot()
{
var exePath = new Uri(System.Reflection.
Assembly.GetExecutingAssembly().CodeBase).LocalPath;
return new FileInfo(exePath).DirectoryName;
}
สิ่งนี้จะส่งคืนพา ธ ที่จัดรูปแบบ "C: \ xxx \ xxx" แบบเต็มไปยังที่ที่โค้ดของคุณอยู่
มีหลายวิธีในการรับพา ธ ที่สามารถใช้งานได้ซึ่งเราควรใช้มันขึ้นอยู่กับความต้องการของเราที่นี่คือลิงค์ที่อธิบายวิธีการต่าง ๆ
นี่คือโซลูชันที่เชื่อถือได้ซึ่งทำงานกับแอปพลิเคชัน32 บิตและ64 บิต
เพิ่มการอ้างอิงเหล่านี้:
ใช้ System.Diagnostics;
ใช้ระบบการจัดการ
เพิ่มวิธีนี้ในโครงการของคุณ:
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;
}
ตอนนี้ใช้มันเพื่อ:
int RootProcessId = Process.GetCurrentProcess().Id;
GetProcessPath(RootProcessId);
โปรดสังเกตว่าถ้าคุณทราบรหัสของกระบวนการแล้ววิธีนี้จะส่งคืน ExecutePath ที่สอดคล้องกัน
พิเศษสำหรับผู้ที่สนใจ:
Process.GetProcesses()
... จะทำให้คุณมีกระบวนการที่กำลังทำงานอยู่ทั้งหมดและ ...
Process.GetCurrentProcess()
... จะให้กระบวนการปัจจุบันพร้อมกับข้อมูลของพวกเขาเช่น Id และอื่น ๆ และยังมีการควบคุมที่ จำกัด เช่น Kill เป็นต้น *
คุณสามารถสร้างชื่อโฟลเดอร์เป็นทรัพยากรภายในโครงการโดยใช้ Solution Explorer จากนั้นคุณสามารถวางไฟล์ภายในทรัพยากร
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);
}