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");
// Get normal filepath of this assembly's permanent directory
var path = new Uri(
System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().CodeBase)
).LocalPath;
不少人指出 GetCommandLineArgs 不保证返回程序名称 . 见The first word on the command line is the program name only by convention . 文章确实说明了"Although extremely few Windows programs use this quirk (I am not aware of any myself)" . 所以有可能'spoof' GetCommandLineArgs ,但我们正在谈论一个控制台应用程序 . 控制台应用程序通常很快且很脏 . 所以这符合我的KISS理念 .
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) + @"\";
}
}
8
您有两种选择来查找应用程序的目录,您选择的目录取决于您的目的 .
// 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);
2
对于控制台应用程序,您可以尝试:
System.IO.Directory.GetCurrentDirectory();
输出(在我的本地机器上):
c:\ users \ xxxxxxx \ documents \ visual studio 2012 \ Projects \ ImageHandler \ GetDir \ bin \ Debug
public static string GetApplicationRoot()
{
var exePath = new Uri(System.Reflection.
Assembly.GetExecutingAssembly().CodeBase).LocalPath;
return new FileInfo(exePath).DirectoryName;
}
26 回答
我用过
当我想找到相对于应用程序文件夹的路径时 . 这适用于ASP.Net和winform应用程序 . 它也不需要任何对System.Web程序集的引用 .
如果您正在寻找兼容.NET Core的方法,请使用
这是在.NET Framework 4.6和.NET Core 1.0(以及.NET Standard 1.3)中引入的 . 见:AppContext.BaseDirectory Property .
根据this page,
有许多方法可以获得可执行路径,我们应该使用哪种方法取决于我们的需求,这里有一个讨论不同方法的链接 .
Different ways to get Application Executable Path
我的意思是,为什么不是p / invoke方法?
您可以像Application.StartupPath一样使用它:
上面的答案是我所需要的90%,但是为我返回了一个Uri而不是常规路径 .
正如MSDN论坛帖子How to convert URI path to normal filepath?中所解释的那样,我使用了以下内容:
可能有点晚了,但值得一提:
或者更正确地获取目录路径:
Edit:
不少人指出
GetCommandLineArgs
不保证返回程序名称 . 见The first word on the command line is the program name only by convention . 文章确实说明了"Although extremely few Windows programs use this quirk (I am not aware of any myself)" . 所以有可能'spoof'GetCommandLineArgs
,但我们正在谈论一个控制台应用程序 . 控制台应用程序通常很快且很脏 . 所以这符合我的KISS理念 .将解决问题以使用安装包引用第三方参考文件 .
试试这段简单的代码:
以下行将为您提供一个应用程序路径:
以上解决方案在以下情况下正常运行:
简单的应用程序
在另一个域中,Assembly.GetEntryAssembly()将返回null
DLL作为字节数组从嵌入式资源加载,并作为Assembly.Load(byteArrayOfEmbeddedDll)加载到AppDomain
这是一个可靠的解决方案,适用于 32bit 和 64bit 应用程序 .
添加以下参考:
将此方法添加到您的项目:
现在使用它如下:
请注意,如果您知道进程的id,那么此方法将返回相应的ExecutePath .
Extra, for those interested:
...将为您提供所有当前正在运行的进程的数组,并...
...将为您提供当前流程及其信息,例如Id等,并且还有限的控制,例如杀等等*
System.Reflection.Assembly.GetExecutingAssembly() . Location 1
如果您想要的只是目录,请将其与System.IO.Path.GetDirectoryName相结合 .
这些方法都不能在特殊情况下工作,例如使用exe的符号链接,它们将返回链接的位置而不是实际的exe .
所以可以使用QueryFullProcessImageName解决这个问题:
您有两种选择来查找应用程序的目录,您选择的目录取决于您的目的 .
对于控制台应用程序,您可以尝试:
输出(在我的本地机器上):
或者你可以尝试(最后还有一个额外的反斜杠):
输出:
您可以使用以下代码获取当前的应用程序目录 .
Assembly.GetEntryAssembly().Location
或Assembly.GetExecutingAssembly().Location
与
System.IO.Path.GetDirectoryName()
结合使用仅获取目录 .GetEntryAssembly()
和GetExecutingAssembly()
的路径可以不同,即使大多数情况下目录也是相同的 .使用
GetEntryAssembly()
时,您必须注意,如果输入模块不受管理(即C或VB6可执行文件),则可以返回null
. 在这些情况下,可以使用Win32 API中的GetModuleFileName
:你可以使用这个 .
您可能希望这样做:
您只需添加到项目引用
System.Windows.Forms
,然后像往常一样使用System.Windows.Forms.Application.StartupPath
.因此,不需要更复杂的方法或使用反射 .
如果应该通过双击调用exe来使用它
您可以使用解决方案资源管理器在项目中创建文件夹名称作为资源,然后您可以在资源中粘贴文件 .
我没有看到有人将.Net Core反射提供的LocalPath转换为可用的System.IO路径,所以这是我的版本 .
这将返回完整的“C:\ xxx \ xxx”格式化代码所在的路径 .
我已经使用了这段代码并获得了解决方案 .
对于任何对asp.net网络应用感兴趣的人 . 以下是我对3种不同方法的结果
结果
该应用程序从“C:\ inetpub \ SBSPortal_staging”物理运行,因此第一个解决方案绝对不适合Web应用程序 .
您可以使用以下代码,您将获得应用程序的完整路径:
在VB.net中
适合我(应用程序类型:类库) . 不确定C#...返回没有Filename的路径作为字符串