提问



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


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

最佳参考


System.Reflection.Assembly.GetExecutingAssembly()Location 1 [49] [50]


如果您想要的只是目录,请将其与System.IO.Path.GetDirectoryName结合使用。[51]



   1 根据Mr.Mindor的评论:

  System.Reflection.Assembly.GetExecutingAssembly().Location返回执行程序集当前所在的位置,这可能是也可能不是程序集在不执行时所处的位置。对于卷影复制程序集,您将在临时目录中获取路径。 System.Reflection.Assembly.GetExecutingAssembly().CodeBase将返回集会的永久路径。[52]


其它参考1


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


AppDomain.CurrentDomain.BaseDirectory

其它参考2


您有两种选择来查找应用程序的目录,您选择的目录取决于您的目的。


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

其它参考3


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


Environment.GetCommandLineArgs()[0];


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


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





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

其它参考4


对于任何对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物理运行,因此第一个解决方案绝对不适合Web应用程序。

其它参考5


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


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


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

其它参考6


您可能希望这样做:


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

其它参考7


你可以使用这个。


System.Environment.CurrentDirectory

其它参考8


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


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 \\


其它参考9


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


AppDomain.CurrentDomain.BaseDirectory

其它参考10


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


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

其它参考11


我用过


System.AppDomain.CurrentDomain.BaseDirectory


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

其它参考12


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


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

其它参考13


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


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


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

其它参考14


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

其它参考15


AppDomain.CurrentDomain.BaseDirectory


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

其它参考16


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


System.AppContext.BaseDirectory


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


根据这个页面,[56]



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


其它参考17


这些方法都不能在特殊情况下工作,例如使用exe的符号链接,它们将返回链接的位置而不是实际的exe。


所以可以使用QueryFullProcessImageName来解决这个问题:[57]


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) + @"\";
    }
}

其它参考18


试试这段简单的代码:


 string exePath = Path.GetDirectoryName( Application.ExecutablePath);

其它参考19


在VB.net中


My.Application.Info.DirectoryPath


适合我(应用程序类型:类库)。不确定C#...
返回没有Filename为string的路径

其它参考20


我没有看到任何人将.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格式化路径。

其它参考21


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


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


以上解决方案在以下情况下正常运行:



  • 简单的应用

  • 在另一个域中,Assembly.GetEntryAssembly()将返回null

  • DLL从嵌入式资源作为字节数组加载,并作为Assembly.Load(byteArrayOfEmbeddedDll)加载到AppDomain


其它参考22


有许多方法可以获得可执行路径,我们应该使用哪种方法取决于我们的需求,这里有一个讨论不同方法的链接。


获取应用程序可执行路径的不同方法[58]

其它参考23


这是一个可靠的解决方案,适用于 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等,并且还有限的控制,例如杀等等*

其它参考24


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


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