如何在.NET控制台应用程序中获取应用程序的path?

如何在控制台应用程序中find应用程序的path?

在Windows窗体中 ,我可以使用Application.StartupPath来查找当前path,但是在控制台应用程序中似乎不可用。

System.Reflection.Assembly.GetExecutingAssembly()Location 1

如果你想要的只是目录,把它与System.IO.Path.GetDirectoryName结合起来。

1 按照Mindor先生的评论:
System.Reflection.Assembly.GetExecutingAssembly().Location返回执行程序集当前所在的System.Reflection.Assembly.GetExecutingAssembly().Location ,当执行程序集不在的位置时,可能是也可能不是程序集所在的位置。 在阴影复制程序集的情况下,您将在临时目录中获取path。 System.Reflection.Assembly.GetExecutingAssembly().CodeBase将返回程序集的“永久”path。

您可以使用下面的代码来获取当前的应用程序目录。

 AppDomain.CurrentDomain.BaseDirectory 

你有两个select来查找应用程序的目录,你select的目录取决于你的目的。

 // 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); 

可能有点晚,但这是值得一提的:

 Environment.GetCommandLineArgs()[0]; 

或者更正确地得到目录path:

 System.IO.Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]); 

编辑:

不less人已经指出, GetCommandLineArgs不能保证返回程序名。 请参阅命令行中的第一个单词是仅按照惯例的程序名称 。 这篇文章确实指出:“尽pipe极less数Windows程序使用这个怪癖(我自己也不知道)”。 所以有可能“欺骗” GetCommandLineArgs ,但是我们正在讨论一个控制台应用程序。 控制台应用程序通常很快而且很脏。 所以这符合我的KISS理念。

对于任何对asp.netnetworking应用感兴趣的人。 这是我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”运行,所以第一个解决scheme绝对不适合Web应用程序。

上面的答案是我所需要的90%,但是返回了一个Uri,而不是一个正常的path。

正如在MSDN论坛发布的解释, 如何将URIpath转换为正常的文件path? ,我使用了以下内容:

 // Get normal filepath of this assembly's permanent directory var path = new Uri( System.IO.Path.GetDirectoryName( System.Reflection.Assembly.GetExecutingAssembly().CodeBase) ).LocalPath; 

您可能正在寻找这样做:

 System.IO.Path.GetDirectoryName( System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase) 

你可以用这个来代替。

 System.Environment.CurrentDirectory 

对于控制台应用程序,您可以试试这个:

 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 \

我已经使用这个代码并得到解决scheme。

 AppDomain.CurrentDomain.BaseDirectory 

我使用这个,如果exe应该被双击它调用

 var thisPath = System.IO.Directory.GetCurrentDirectory(); 

我用过了

 System.AppDomain.CurrentDomain.BaseDirectory 

当我想find一个相对于应用程序文件夹的path。 这适用于ASP.Net和winform应用程序。 它也不需要任何对System.Web程序集的引用。

您可以简单地添加到您的项目引用System.Windows.Forms ,然后像往常一样使用System.Windows.Forms.Application.StartupPath

所以,不需要更复杂的方法或使用reflection。

我的意思是,为什么不用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().LocationAssembly.GetExecutingAssembly().Location

System.IO.Path.GetDirectoryName()一起使用以仅获取目录。

GetEntryAssembly()GetExecutingAssembly()的path可以是不同的,即使在大多数情况下目录将是相同的。

使用GetEntryAssembly()你必须知道,如果入口模块是非托pipe的(即C ++或VB6可执行文件),这可以返回null 。 在这种情况下,可以使用Win32 API中的GetModuleFileName

 [DllImport("kernel32.dll", CharSet = CharSet.Auto)] public static extern int GetModuleFileName(HandleRef hModule, StringBuilder buffer, int length); 
 AppDomain.CurrentDomain.BaseDirectory 

将解决问题,以引用第三方参考文件与安装包。

在VB.net

 My.Application.Info.DirectoryPath 

适用于我(应用程序types:类库)。 不确定关于C#…以stringforms返回无文件名的path

BR,Daniel

这些方法都没有在特殊情况下工作,如使用符号链接到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) + @"\"; } } 

这是一个可靠的解决scheme,适用于32位64位应用程序。

添加这些引用:

使用System.Diagnostics;

使用System.Management;

将此方法添加到您的项目中:

 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); 

注意,如果你知道进程的id,那么这个方法将返回相应的ExecutePath。

额外,对于那些感兴趣的:

 Process.GetProcesses() 

…会给你一个所有正在运行的进程的数组,并…

 Process.GetCurrentProcess() 

…会给你当前的过程,连同他们的信息,如身份证等,也有限的控制,如杀死等*

您可以使用解决scheme资源pipe理器在项目中创build一个文件夹名称,然后您可以在资源中粘贴一个文件。

 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); }