1072

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

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

4

28 回答 28

1294

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

System.IO.Path.GetDirectoryName如果您想要的只是目录,请将其结合起来。

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

于 2009-05-07T23:09:06.277 回答
448

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

AppDomain.CurrentDomain.BaseDirectory
于 2009-05-08T19:03:47.270 回答
204

您有两个选项可用于查找应用程序的目录,您的选择将取决于您的目的。

// 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);
于 2011-10-14T18:27:47.700 回答
90

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

Environment.GetCommandLineArgs()[0];

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

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

编辑:

不少人指出,GetCommandLineArgs不保证返回程序名。请参阅命令行上的第一个单词是程序名,只是按照惯例。该文章确实指出“尽管极少数 Windows 程序使用此怪癖(我自己不知道)”。所以“欺骗”是可能的GetCommandLineArgs,但我们谈论的是控制台应用程序。控制台应用程序通常又快又脏。所以这符合我的 KISS 理念。

于 2011-05-21T13:27:27.373 回答
51

对于任何对 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);
}

结果

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”物理运行的,所以第一个解决方案绝对不适合网络应用程序。

于 2011-10-06T19:42:16.337 回答
47

上面的答案是我需要的 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;
于 2012-04-13T20:20:44.323 回答
32

您可能希望这样做:

System.IO.Path.GetDirectoryName(
    System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)
于 2009-05-07T23:10:02.687 回答
32

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

System.AppContext.BaseDirectory

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

根据这个页面

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

于 2018-02-02T02:14:02.597 回答
24

你可以改用这个。

System.Environment.CurrentDirectory
于 2012-11-15T20:06:43.180 回答
21

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

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\

于 2014-06-18T21:34:34.553 回答
17

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

AppDomain.CurrentDomain.BaseDirectory
于 2017-01-31T08:17:40.380 回答
13

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

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

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

  • 简单的应用程序
  • 在 Assembly.GetEntryAssembly() 将返回 null 的另一个域中
  • DLL 作为字节数组从嵌入式资源加载并作为 Assembly.Load(byteArrayOfEmbeddedDll) 加载到 AppDomain
  • 使用 Mono 的mkbundle捆绑包(没有其他方法有效)
于 2018-02-23T19:24:42.163 回答
9

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

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

于 2016-04-26T10:26:09.210 回答
8

我用过

System.AppDomain.CurrentDomain.BaseDirectory

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

于 2014-04-07T16:57:01.990 回答
7

我的意思是,为什么不使用 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");
于 2014-07-24T20:56:42.093 回答
6

Assembly.GetEntryAssembly().Location或者Assembly.GetExecutingAssembly().Location

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

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

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

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetModuleFileName(HandleRef hModule, StringBuilder buffer, int length);
于 2012-03-29T12:41:00.607 回答
6

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

var thisPath = System.IO.Directory.GetCurrentDirectory();
于 2013-02-15T18:19:39.760 回答
6

在 VB.net

My.Application.Info.DirectoryPath

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

于 2015-04-12T12:08:30.987 回答
5
AppDomain.CurrentDomain.BaseDirectory

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

于 2014-07-14T06:43:49.480 回答
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;
       
}

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

于 2018-02-07T19:03:49.133 回答
4

试试这个简单的代码行:

 string exePath = Path.GetDirectoryName( Application.ExecutablePath);
于 2017-11-20T09:42:03.820 回答
4

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

var appExePath = Process.GetCurrentProcess().MainModule.FileName;
于 2021-03-05T15:22:50.240 回答
2

这些方法在特殊情况下都不起作用,例如使用指向 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) + @"\";
    }
}
于 2017-02-05T08:54:41.953 回答
2

Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName) 在我尝试过的每一种情况下,它都是唯一对我有用的。

于 2020-06-18T12:40:14.103 回答
1

对于 .NET 6,有 Environment.ProcessPath。

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

于 2021-11-24T13:26:42.707 回答
0

我将它用于控制台 + 网络 6

Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)
于 2021-09-29T09:34:22.267 回答
-1

这是一个适用于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 等,以及有限的控制,例如 Kill 等。*

于 2016-03-09T10:35:58.967 回答
-6

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

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);
}
于 2012-05-28T11:36:12.690 回答