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

如何在控制台应用程序中找到应用程序的路径?

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

1205487 次浏览

# 2, # 3 # 4

如果您想要的只是目录,则将其与# 0结合起来。

< br > < p > # 0 # 1System.Reflection.Assembly.GetExecutingAssembly().Location返回正在执行的程序集当前的位置,这可能是也可能不是程序集未执行时的位置。在阴影复制程序集的情况下,您将获得临时目录中的路径。# 1将返回程序集的“永久”路径

你可能会这样做:

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

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

AppDomain.CurrentDomain.BaseDirectory

可能有点晚了,但这个值得提一下:

Environment.GetCommandLineArgs()[0];

或者更准确地获取目录路径:

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

编辑:

相当多的人指出,GetCommandLineArgs并不保证返回程序名。看到# 2。这篇文章确实指出“虽然很少有Windows程序使用这个怪癖(我自己不知道)”。因此,“欺骗”GetCommandLineArgs是可能的,但我们谈论的是控制台应用程序。控制台应用程序通常是快速和肮脏的。所以这符合我的KISS哲学。

<强>编辑从反馈来看,当您使用单元测试系统时,大多数其他解决方案似乎都不起作用。这是有道理的,因为可执行项不是你的应用程序,而是测试系统。我还没有核实过,所以我可能完全错了。如果是这样,我将删除这个编辑

对于任何对asp.net web应用程序感兴趣的人。以下是我用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_5e84cc01p2 = C:\inetpub\SBSPortal_staging\p3 = C:\inetpub\SBSPortal_staging

应用程序在物理上从“C:\inetpub\SBSPortal_staging”运行,所以第一个解决方案绝对不适合web应用程序。

您有两个选项来查找应用程序的目录,具体选择哪个取决于您的目的。

// 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 directorystring path = System.Reflection.Assembly.GetExecutingAssembly().CodeBase;
//once you have the path you get the directory with:var directory = System.IO.Path.GetDirectoryName(path);

Assembly.GetEntryAssembly().LocationAssembly.GetExecutingAssembly().Location

System.IO.Path.GetDirectoryName()结合使用只获取目录。

GetEntryAssembly()GetExecutingAssembly()的路径可以不同,尽管在大多数情况下目录是相同的。

使用GetEntryAssembly(),你必须意识到如果入口模块是非托管的(如c++或VB6可执行文件),它可能会返回null。在这些情况下,可以使用Win32 API中的GetModuleFileName:

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

上面的答案是我需要的90%,但返回了一个Uri,而不是常规路径。

正如在MSDN论坛的帖子中所解释的,如何将URI路径转换为正常的文件路径?,我使用了以下方法:

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

可以使用“解决方案资源管理器”在项目中创建文件夹名称为“资源”,然后可以在“资源”中粘贴文件。

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

你可以用这个代替。

System.Environment.CurrentDirectory

我使用这个如果exe被认为是通过双击它来调用

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

我用过

System.AppDomain.CurrentDomain.BaseDirectory

当我想找到一个相对于应用程序文件夹的路径时。这适用于ASP。Net和winform应用程序。它也不需要任何对System的引用。Web组件。

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

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\

AppDomain.CurrentDomain.BaseDirectory

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

为什么不是p/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());}}}

您可以像使用应用程序一样使用它。StartupPath:

    Console.WriteLine("The path to this executable is: " + AppInfo.StartupPath + "\\" + System.Diagnostics.Process.GetCurrentProcess().ProcessName + ".exe");

在VB.net

My.Application.Info.DirectoryPath

为我工作(应用类型:类库)。不太懂c#…返回路径w/o文件名为字符串

这里有一个可靠的解决方案,适用于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()

...会给你当前的进程,以及他们的信息,如Id等,也有限制控制,如杀死等*

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

因此,不需要更复杂的方法或使用反射。

我已经使用了这段代码并得到了解决方案。

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

如果你正在寻找一种与。net Core兼容的方法,请使用

System.AppContext.BaseDirectory

这是在。net Framework 4.6和。net Core 1.0(和。net Standard 1.3)中引入的。看到:# 0。

根据这个页面

这是。net Core中AppDomain.CurrentDomain.BaseDirectory的首选替代品

我没有看到任何人将. net Core反射提供的LocalPath转换为可用的系统。IO路径,这是我的版本。

public static string GetApplicationRoot(){var exePath = new Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath;
return new FileInfo(exePath).DirectoryName;       
}

这将返回代码所在的完整的C:\\xxx\\xxx格式路径。

下面一行将给出应用程序路径:

var applicationPath = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName)

上述解决方案在以下情况下正常工作:

  • 简单的应用
  • 在另一个域,Assembly.GetEntryAssembly()将返回null
  • DLL以字节数组的形式从嵌入式资源加载,并以Assembly.Load的形式加载到AppDomain。
  • 使用Mono的mkbundle捆绑包(没有其他方法工作)
< p > # 0

?

在。net Core 3及以上版本中,你会得到。dll文件而不是。exe文件。获取您可以使用的.exe文件路径。

var appExePath = Process.GetCurrentProcess().MainModule.FileName;

我将此用于console + net 6

Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)

对于。net 6,有Environment.ProcessPath。

看到# 0

技术和陷阱一直在变化。下面假设你在linux上运行一个。net 6控制台应用程序(在win/mac上,结果将遵循类似的模式,只需将/usr/share//home/username/替换为操作系统的标准位置)。

演示:

Console.WriteLine("Path.GetDirectoryName(Process.GetCurrentProcess()?.MainModule?.FileName) = " + Path.GetDirectoryName(Process.GetCurrentProcess()?.MainModule?.FileName));Console.WriteLine("Path.GetDirectoryName(Environment.ProcessPath)                           = " + Path.GetDirectoryName(Environment.ProcessPath));Console.WriteLine("Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)          = " + Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));Console.WriteLine("typeof(SomeType).Assembly.Location                                       = " + typeof(SomeType).Assembly.Location);Console.WriteLine("Path.GetDirectoryName(Environment.GetCommandLineArgs()[0])               = " + Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]));Console.WriteLine("AppDomain.CurrentDomain.BaseDirectory                                    = " + AppDomain.CurrentDomain.BaseDirectory);Console.WriteLine("System.AppContext.BaseDirectory                                          = " + System.AppContext.BaseDirectory);

结果:

Path.GetDirectoryName(Process.GetCurrentProcess()?.MainModule?.FileName) = /usr/share/dotnetPath.GetDirectoryName(Environment.ProcessPath)                           = /usr/share/dotnetPath.GetDirectoryName(Assembly.GetExecutingAssembly().Location)          = /home/username/myproject/bin/Debug/net6.0typeof(SomeType).Assembly.Location                                       = /home/username/myproject/bin/Debug/net6.0Path.GetDirectoryName(Environment.GetCommandLineArgs()[0])               = /home/username/myproject/bin/Debug/net6.0AppDomain.CurrentDomain.BaseDirectory                                    = /home/username/myproject/bin/Debug/net6.0/System.AppContext.BaseDirectory                                          = /home/username/myproject/bin/Debug/net6.0/

每种方法都有其优点和缺点-请参阅其他答案以了解在哪种情况下使用哪种方法。

我用dotnet myapp运行我的.NET 6控制台应用程序,所以对我来说工作(可靠)是:

typeof(SomeType).Assembly.Location// orPath.GetDirectoryName(Assembly.GetExecutingAssembly().Location)

在。net 6中,我的WPF应用程序(<TargetFramework>net6.0-windows</TargetFramework>)为Assembly.GetEntryAssembly()!.Location返回.dll文件路径,而不是.exe文件。他们引入了第5条:

var path = Environment.ProcessPath; // Note it may be null

返回启动当前执行进程的可执行文件的路径。当路径不可用时返回null

参见讨论在这里在这里