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

JSm*_*yth 902 .net c# console console-application

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

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

Sam*_*Axe 1136

System.Reflection.Assembly.GetExecutingAssembly().1Location

再加上System.IO.Path.GetDirectoryName如果你想要的是目录.

1 根据Mr.Mindor的评论:
System.Reflection.Assembly.GetExecutingAssembly().Location返回执行程序集当前所在的位置,这可能是也可能不是程序集在不执行时所在的位置.对于卷影复制程序集,您将获得临时目录中的路径.System.Reflection.Assembly.GetExecutingAssembly().CodeBase将返回程序集的"永久"路径.

  • System.Reflection.Assembly.GetExecutingAssembly().Location返回执行程序集**当前**所在的位置,可能是也可能不是程序集在不执行时所在的位置.对于卷影复制程序集,您将获得临时目录中的路径.System.Reflection.Assembly.GetExecutingAssembly().CodeBase将返回程序集的'__permenant__'路径. (240认同)
  • `GetExecutingAssembly`返回**包含当前正在执行的代码**的程序集.这可能不一定是控制台**.exe**assembly.它可能是从完全不同的位置加载的组件.你将不得不使用`GetEntryAssembly`!另请注意,当程序集在GAC中时,不能设置`CodeBase`.更好的选择是`AppDomain.CurrentDomain.BaseDirectory`. (27认同)
  • @SamGoldberg:这取决于它的使用方式:http://stackoverflow.com/q/1068420/391656.或者你可以...新的Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).LocalPath (13认同)
  • 请在4个空格中编写代码,以便复制 (3认同)
  • @farosch:控制台应用程序不存在“应用程序”。 (3认同)
  • 十年后,.NET Core 表示 CodeBase 已过时,我们应该使用 Locaction。 (3认同)
  • 无论出于何种原因,在VS2013中(至少我的副本)intellisense不能通过System.Reflection.Assembly.GetExeuctingAssembly()在那里,但你看不到它. (2认同)
  • 如果你调用dll,System.Reflection.Assembly.GetExecutingAssembly().CodeBase将获得"file:/// C:/Windows/Microsoft.NET/Framework64/v4.0.30319/mscorlib.dll" (2认同)

小智 393

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

AppDomain.CurrentDomain.BaseDirectory
Run Code Online (Sandbox Code Playgroud)

  • 不要使用它.BaseDirectory可以在运行时设置.它不能保证是正确的(就像接受的答案一样). (42认同)
  • @usr是什么让你认为`BaseDirectory`可以在运行时设置?它只有一个吸气剂. (4认同)
  • +1这可能是您想要的答案,因为它可以补偿影子复制. (3认同)
  • @bitbonk它可以在appdomain创建时设置. (3认同)
  • 是不是可以在* .lnk文件的“开始于:”字段中更改BaseDirectory? (2认同)

Mr.*_*dor 159

您有两种方法可以找到应用程序的目录,您选择的目录取决于您的目的.

// 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);
Run Code Online (Sandbox Code Playgroud)

  • 如果您尝试使用所述路径不支持URI格式,请使用`var localDirectory = new Uri(directory).LocalPath;` (14认同)
  • 只是想说,很明显,根据发布的其他选择,有2个以上的选择... (3认同)
  • @Ukuma.Scott 如果路径包含 & 或 #,这不起作用 (2认同)

Ste*_* Mc 78

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

Environment.GetCommandLineArgs()[0];
Run Code Online (Sandbox Code Playgroud)

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

System.IO.Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]);
Run Code Online (Sandbox Code Playgroud)

编辑:

不少人指出,GetCommandLineArgs不保证返回程序名称.请参阅命令行中的第一个单词是仅按惯例的程序名称.文章确实说"虽然极少数Windows程序使用这个怪癖(我自己也不知道)".因此可以"欺骗" GetCommandLineArgs,但我们正在讨论控制台应用程序.控制台应用程序通常很快且很脏.所以这符合我的KISS理念.

  • 您的"简单"解决方案涉及两个方法调用."复杂"解决方案涉及两个方法调用.没有实际区别 - 除了"简单"解决方案在您编写程序时在某些不受您控制的情况下会给您错误答案.为什么要承担风险?使用另外两个方法调用,您的程序将不再复杂,但会更可靠. (5认同)
  • 为我的方案工作,其他解决方案没有,所以感谢提供另一种选择:-)我使用ReSharper测试运行器来运行MS单元测试,我正在测试的代码需要一个特定的.dll才能在执行目录中. ..和Assembly.GetExecutingDirectory()奇怪地返回一个不同的结果. (3认同)

roc*_*ast 43

对于任何对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);
}
Run Code Online (Sandbox Code Playgroud)

结果

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
Run Code Online (Sandbox Code Playgroud)

该应用程序从"C:\ inetpub\SBSPortal_staging"实际运行,因此第一个解决方案绝对不适合Web应用程序.


fiz*_*led 37

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

正如MSDN论坛帖子中所解释的,如何将URI路径转换为普通文件路径?,我使用了以下内容:

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

  • 不幸的是,这对于包含片段标识符(“#”字符)的路径不起作用。标识符及其后面的所有内容都会从结果路径中被截断。 (2认同)

PSU*_*rdi 27

您可能希望这样做:

System.IO.Path.GetDirectoryName(
    System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)
Run Code Online (Sandbox Code Playgroud)


小智 22

你可以使用这个.

System.Environment.CurrentDirectory
Run Code Online (Sandbox Code Playgroud)

  • @MatthewWatson甚至更简单,该程序是从另一个文件夹执行的... (4认同)

F.A*_*ves 19

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

System.IO.Directory.GetCurrentDirectory();
Run Code Online (Sandbox Code Playgroud)

输出(在我的本地机器上):

c:\ users\xxxxxxx\documents\visual studio 2012\Projects\ImageHandler\GetDir\bin\Debug

或者你可以尝试(最后还有一个额外的反斜杠):

AppDomain.CurrentDomain.BaseDirectory
Run Code Online (Sandbox Code Playgroud)

输出:

c:\ users\xxxxxxx\documents\visual studio 2012\Projects\ImageHandler\GetDir\bin\Debug \


Dej*_*jan 16

如果您正在寻找兼容.NET Core的方法,请使用

System.AppContext.BaseDirectory
Run Code Online (Sandbox Code Playgroud)

这是在.NET Framework 4.6和.NET Core 1.0(以及.NET Standard 1.3)中引入的.请参阅:AppContext.BaseDirectory属性.

根据这个页面,

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

  • 另请参阅 https://github.com/dotnet/runtime/issues/13051 了解独立的 dotnet 控制台应用程序。这里建议使用 Process.GetCurrentProcess().MainModule.FileName (3认同)

Tri*_*ion 14

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

AppDomain.CurrentDomain.BaseDirectory
Run Code Online (Sandbox Code Playgroud)


fru*_*ero 8

您可以简单地添加到项目引用中System.Windows.Forms,然后System.Windows.Forms.Application.StartupPath 照常使用.

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


dev*_*747 7

如果应该通过双击调用exe来使用它

var thisPath = System.IO.Directory.GetCurrentDirectory();
Run Code Online (Sandbox Code Playgroud)

  • 这是不正确的,因为您可以在结果中获得随机目录. (5认同)

小智 7

我用过

System.AppDomain.CurrentDomain.BaseDirectory
Run Code Online (Sandbox Code Playgroud)

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


jmi*_*mik 7

对于.NET 6,有Environment.ProcessPath。

请参阅https://learn.microsoft.com/en-us/dotnet/api/system.environment.processpath?view=net-6.0

  • @ErikMcKelvey 他们提供了一个解决方案和对文档的引用,说明这实际上是一个解决方案。如果不使用链接,您将如何引用解决方案? (2认同)

use*_*865 6

我的意思是,为什么不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());
                }
            }
    }
Run Code Online (Sandbox Code Playgroud)

您可以像Application.StartupPath一样使用它:

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

  • @ user3596865因为它需要与Windows硬依赖,并且与DNX或Mono不兼容.也许未来的Windows版本可能会发生重大变化.再说一遍:为什么我们应该在这里使用pinvoke? (7认同)
  • 因为为什么不呢? (4认同)
  • .NET太多时,为什么要p / invoke? (2认同)

use*_*375 6

下一行将为您提供一个应用程序路径:

var applicationPath = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName)
Run Code Online (Sandbox Code Playgroud)

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

  • 简单的应用程序
  • 在另一个域中,Assembly.GetEntryAssembly()将返回null
  • DLL从嵌入式资源作为字节数组加载,并作为Assembly.Load(byteArrayOfEmbeddedDll)加载到AppDomain。
  • 使用Mono的mkbundle捆绑包(其他方法无效)

  • 在 Linux 上的调试器下,返回:/usr/share/dotnet (2认同)

Her*_*man 5

Assembly.GetEntryAssembly().Location 要么 Assembly.GetExecutingAssembly().Location

与组合使用System.IO.Path.GetDirectoryName()仅获取目录。

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

随着GetEntryAssembly()你要知道,这可以返回null,如果输入模块未被管理(即C ++或VB6可执行文件)。在这种情况下,可以使用GetModuleFileNameWin32 API:

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


小智 5

AppDomain.CurrentDomain.BaseDirectory
Run Code Online (Sandbox Code Playgroud)

将解决此问题以引用带有安装包的第 3 方参考文件。

  • 这个答案已经在 5 年前被提出过,甚至不止一次。 (11认同)

dba*_*dba 5

在VB.net

My.Application.Info.DirectoryPath
Run Code Online (Sandbox Code Playgroud)

为我工作(应用程序类型:类库)。不确定C#...将不带文件名的路径作为字符串返回


mar*_*che 5

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

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

   return new FileInfo(exePath).DirectoryName;
       
}
Run Code Online (Sandbox Code Playgroud)

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


Don*_* V. 5

使用 .NET Core 3 及更高版本,您将获得 .dll 而不是 .exe 文件。要获取您可以使用的 .exe 文件路径。

var appExePath = Process.GetCurrentProcess().MainModule.FileName;
Run Code Online (Sandbox Code Playgroud)