获取应用程序文件夹路径的最佳方法

668

我看到有几种方法可以获取应用程序文件夹路径:

  1. Application.StartupPath
  2. System.IO.Path.GetDirectoryName( System.Reflection.Assembly.GetExecutingAssembly().Location)
  3. AppDomain.CurrentDomain.BaseDirectory
  4. System.IO.Directory.GetCurrentDirectory()
  5. Environment.CurrentDirectory
  6. System.IO.Path.GetDirectoryName( System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)
  7. System.IO.Path.GetDirectory(Application.ExecutablePath)

根据不同情况,哪种方法是最好的呢?


11
为什么我们有很多种方法来获取应用程序路径?我认为每种方法都有其原因。 - Leo Vo
1
#6 中有一个错误:应该是 System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase, System.IO.Path.GetDirectoryName(Application.ExecutablePath)。 - BillW
2
太好了,我在一个网站项目中。但是我不想在我的IoC加载库(它与Web无关)中使用Server.MapPath逻辑。 - bkwdesign
1
我们现在拥有可靠的IHostEnvironment.ContentRootPath,通过注入的IHostEnvironment依赖项进行访问(其中包含其他有用的内容)。 - Timo
1
还有Process.GetCurrentProcess().MainModule.FileName - nawfal
2
#4和#5是不正确的。它们返回当前目录,而不是应用程序所在的目录。(它们有时相同,但这只是一个巧合。) - ikegami
11个回答

682

AppDomain.CurrentDomain.BaseDirectory 可能是访问相对于应用程序安装目录的文件最有用的方法。

在 ASP.NET 应用程序中,这将是应用程序根目录,而不是 bin 子文件夹——这可能是您通常想要的。在客户端应用程序中,它将是包含主可执行文件的目录。

在 VSTO 2005 应用程序中,它将是包含您的应用程序的 VSTO 托管程序集的目录,而不是 Excel 可执行文件的路径。

其他方法可能会根据您的环境返回不同的目录——例如,请参见 @Vimvq1987 的答案。

CodeBase 是找到文件的位置,可以是以 http:// 开头的 URL。在这种情况下,Location 可能是程序集下载缓存。不能保证为 GAC 中的程序集设置 CodeBase。

更新 现在(.NET Core、.NET Standard 1.3+ 或 .NET Framework 4.6+),最好使用 AppContext.BaseDirectory 而不是 AppDomain.CurrentDomain.BaseDirectory。两者等效,但 不再支持多个 AppDomains


2
在 Windows XP 32 位系统中进行测试时,它会返回快捷方式的起始位置。 - Joshua Son
1
+1 @Joe,有关VSTO文档级别插件,请参见此处 - user2140173
3
请注意,这将返回一个以反斜杠结尾的路径。当将结果格式化为进程参数传递时,这会给我带来麻烦。 - avenmore
26
如果您正在格式化字符串以构建路径,请考虑改用Path.Combine。这将为您处理尾随反斜杠。 - Joe
1
这个在VS 2017中返回给我的是bin/debug文件夹,而不是根目录。 - SmoveBB
显示剩余6条评论

130
  1. Application.StartupPath和 7. System.IO.Path.GetDirectoryName(Application.ExecutablePath) - 仅适用于Windows窗体应用程序

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

    将会给你一个类似的结果:"C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\Temporary ASP.NET Files\\legal-services\\e84f415e\\96c98009\\assembly\\dl3\\42aaba80\\bcf9fd83_4b63d101" 这里是你正在运行的页面所在的位置。

  3. AppDomain.CurrentDomain.BaseDirectory 对于Web应用程序可能很有用,将返回类似于"C:\\hg\\Services\\Services\\Services.Website\\",这是基本目录,非常有用。

  4. System.IO.Directory.GetCurrentDirectory()和5.Environment.CurrentDirectory

将告诉您进程启动的位置 - 因此对于从Visual Studio以调试模式运行的Web应用程序,例如"C:\\Program Files (x86)\\IIS Express"

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

将告诉您运行代码的.dll所在的位置,对于Web应用程序可能是"file:\\C:\\hg\\Services\\Services\\Services.Website\\bin"

现在以控制台应用程序为例,点2-6将是.exe文件所在的目录。

希望这可以为您节省一些时间。


2
相当确定想要“当前文件夹”只适用于非 Web 应用程序... - Nyerguds
2
这是答案。 - P.Brian.Mackey

64

请注意,这些方法并非都会返回相同的值。在某些情况下,它们可能会返回相同的值,但是请小心,它们的目的是不同的:

Application.StartupPath

返回StartupPath参数(可以在运行应用程序时设置)

System.IO.Directory.GetCurrentDirectory()

返回当前目录,可能是应用程序所在的文件夹,也可能不是。对于Environment.CurrentDirectory也是如此。如果您在DLL文件中使用它,它将返回进程运行的路径(在ASP.NET中尤其如此)。


11
请不要使用GetCurrentDirectory(),为了能够在不同的路径下运行程序! :( - kayleeFrye_onDeck
1
@kayleeFrye_onDeck,你没有给出上一个问题的原因。 - nless

11

对于一个Web应用程序,通常通过当前传入请求的网页调用来获取当前Web应用程序根目录:

HttpContext.Current.Server.MapPath();

System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath;

以上代码说明


9
我通过Win32 API从实际登录的用户会话中启动了一个进程(在任务管理器会话1而不是0)。通过这种方式,我们可以知道哪个变量是最好的。
对于上述7种情况,结果如下:
Path1: C:\Program Files (x86)\MyProgram
Path2: C:\Program Files (x86)\MyProgram
Path3: C:\Program Files (x86)\MyProgram\
Path4: C:\Windows\system32
Path5: C:\Windows\system32
Path6: file:\C:\Program Files (x86)\MyProgram
Path7: C:\Program Files (x86)\MyProgram

也许对于一些与您有类似情况的人来说,当您为自己的情况寻找最佳变量时,这是有帮助的。

6
非常相关的回答。很多人忘记了“工作目录” ≠“程序目录”。 - Nyerguds

6
根据我的经验,最好的方法是将它们结合起来使用。
  1. System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase将为您提供bin文件夹。
  2. Directory.GetCurrentDirectory()在.Net Core中运行良好但在.Net上不起作用,并会为您提供项目的根目录。
  3. System.AppContext.BaseDirectoryAppDomain.CurrentDomain.BaseDirectory在.Net中运行良好但在.Net Core上不起作用,并会为您提供项目的根目录。

在一个旨在面向.Net和.Net core的类库中,我检查哪个框架托管了该库并选择其中之一。


1
关于“will give you the root directory of the project”,不是的,它会给出当前目录,可能是任何目录。 - ikegami

3
为获取简单桌面应用程序的.exe路径,我使用
Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)

该方法返回.exe路径。
请注意,对于几个域,默认域的.exe将被返回,或者由首次调用ExecuteAssembly(String)执行的.exe将被返回;如果入口是非托管的,则返回null

对于GetExecutingAssembly()要小心,它的命名对我来说很令人困惑,因为我期望得到.exe,但它返回放置代码的.dll.exe,所以在GetExecutingAssembly()位于库中的情况下,它会返回该库。


1

我已经成功使用了这个

System.IO.Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName)

它甚至在linqpad.内部工作。


2
这里缺少 GetCurrentProcess 的开括号。顺便说一下,在我的 .net core 项目中,在 Visual Studio 中调试时,它会评估为 C:\Program Files\dotnet,因为 dotnet.exe 就在那里。 - t0b4cc0

-1

将这个 System.IO.Path.GetDirectory(Application.ExecutablePath) 改为 System.IO.Path.GetDirectoryName(Application.ExecutablePath)


-1
如果您知道如何获取根目录:
string rootPath = Path.GetPathRoot(Application.StartupPath)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接