简体   繁体   English

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

[英]How can I get the application's path in a .NET console application?

How do I find the application's path in a console application?如何在控制台应用程序中找到应用程序的路径?

In Windows Forms , I can use Application.StartupPath to find the current path, but this doesn't seem to be available in a console application.Windows Forms中,我可以使用Application.StartupPath来查找当前路径,但这似乎在控制台应用程序中不可用。

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

Combine that with System.IO.Path.GetDirectoryName if all you want is the directory.如果您只需要目录,请将其与System.IO.Path.GetDirectoryName结合使用。

1 As per Mr.Mindor's comment: 1根据 Mr.Mindor 的评论:
System.Reflection.Assembly.GetExecutingAssembly().Location returns where the executing assembly is currently located, which may or may not be where the assembly is located when not executing. System.Reflection.Assembly.GetExecutingAssembly().Location返回正在执行的程序集当前所在的位置,这可能是也可能不是该程序集未执行时所在的位置。 In the case of shadow copying assemblies, you will get a path in a temp directory.在卷影复制程序集的情况下,您将在临时目录中获得一个路径。 System.Reflection.Assembly.GetExecutingAssembly().CodeBase will return the 'permanent' path of the assembly. System.Reflection.Assembly.GetExecutingAssembly().CodeBase将返回程序集的“永久”路径。

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

AppDomain.CurrentDomain.BaseDirectory

You have two options for finding the directory of the application, which you choose will depend on your purpose.您有两个选项可用于查找应用程序的目录,具体选择取决于您的目的。

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

Probably a bit late but this is worth a mention:可能有点晚了,但值得一提的是:

Environment.GetCommandLineArgs()[0];

Or more correctly to get just the directory path:或者更正确地获取目录路径:

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

Edit:编辑:

Quite a few people have pointed out that GetCommandLineArgs is not guaranteed to return the program name.不少人指出, GetCommandLineArgs不能保证返回程序名称。 See The first word on the command line is the program name only by convention .请参阅命令行上的第一个单词只是约定俗成的程序名称 The article does state that "Although extremely few Windows programs use this quirk (I am not aware of any myself)".文章确实指出“尽管极少数 Windows 程序使用此怪癖(我自己不知道)”。 So it is possible to 'spoof' GetCommandLineArgs , but we are talking about a console application.因此可以“欺骗” GetCommandLineArgs ,但我们谈论的是控制台应用程序。 Console apps are usually quick and dirty.控制台应用程序通常又快又脏。 So this fits in with my KISS philosophy.所以这符合我的 KISS 哲学。

For anyone interested in asp.net web apps.对于任何对 asp.net 网络应用程序感兴趣的人。 Here are my results of 3 different methods这是我使用 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);
}

result结果

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

the app is physically running from "C:\\inetpub\\SBSPortal_staging", so the first solution is definitely not appropriate for web apps.该应用程序从“C:\\inetpub\\SBSPortal_staging”实际运行,因此第一个解决方案绝对不适合网络应用程序。

The answer above was 90% of what I needed, but returned a Uri instead of a regular path for me.上面的答案是我需要的 90%,但返回了一个 Uri 而不是我的常规路径。

As explained in the MSDN forums post, How to convert URI path to normal filepath?如 MSDN 论坛帖子中所述, 如何将 URI 路径转换为普通文件路径? , I used the following: ,我使用了以下内容:

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

You may be looking to do this:您可能希望这样做:

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

If you are looking for a .NET Core compatible way, use如果您正在寻找与 .NET Core 兼容的方式,请使用

System.AppContext.BaseDirectory

This was introduced in .NET Framework 4.6 and .NET Core 1.0 (and .NET Standard 1.3).这是在 .NET Framework 4.6 和 .NET Core 1.0(以及 .NET Standard 1.3)中引入的。 See: AppContext.BaseDirectory Property .请参阅: AppContext.BaseDirectory 属性

According to this page ,根据这个页面

This is the prefered replacement for AppDomain.CurrentDomain.BaseDirectory in .NET Core这是 .NET Core 中 AppDomain.CurrentDomain.BaseDirectory 的首选替代品

你可以用这个代替。

System.Environment.CurrentDirectory

For Console Applications, you can try this:对于控制台应用程序,您可以试试这个:

System.IO.Directory.GetCurrentDirectory();

Output (on my local machine):输出(在我的本地机器上):

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

Or you can try (there's an additional backslash in the end):或者你可以尝试(最后有一个额外的反斜杠):

AppDomain.CurrentDomain.BaseDirectory

Output:输出:

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

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

AppDomain.CurrentDomain.BaseDirectory

Following line will give you an application path:以下行将为您提供一个应用程序路径:

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

Above solution is working properly in the following situations:上述解决方案在以下情况下正常工作:

  • simple app简单的应用程序
  • in another domain where Assembly.GetEntryAssembly() would return null在另一个域中,其中 Assembly.GetEntryAssembly() 将返回 null
  • DLL is loaded from Embedded resources as a byte array and loaded to AppDomain as Assembly.Load(byteArrayOfEmbeddedDll) DLL 作为字节数组从嵌入式资源加载,并作为 Assembly.Load(byteArrayOfEmbeddedDll) 加载到 AppDomain
  • with Mono's mkbundle bundles (no other methods work)使用 Mono 的mkbundle包(没有其他方法有效)

You can simply add to your project references System.Windows.Forms and then use the System.Windows.Forms.Application.StartupPath as usual .您可以简单地将System.Windows.Forms添加到您的项目引用中,然后像往常一样使用System.Windows.Forms.Application.StartupPath

So, not need for more complicated methods or using the reflection.所以,不需要更复杂的方法或使用反射。

I have used我用过了

System.AppDomain.CurrentDomain.BaseDirectory

when I want to find a path relative to an applications folder.当我想找到相对于应用程序文件夹的路径时。 This works for both ASP.Net and winform applications.这适用于 ASP.Net 和 winform 应用程序。 It also does not require any reference to System.Web assemblies.它还不需要对 System.Web 程序集的任何引用。

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

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

I mean, why not ap/invoke method?我的意思是,为什么不使用 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());
                }
            }
    }

You would use it just like the Application.StartupPath:您可以像 Application.StartupPath 一样使用它:

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

in VB.net在 VB.net 中

My.Application.Info.DirectoryPath

works for me (Application Type: Class Library).对我有用(应用程序类型:类库)。 Not sure about C#... Returns the path w/o Filename as string不确定 C#... 以字符串形式返回不带文件名的路径

Assembly.GetEntryAssembly().Location or Assembly.GetExecutingAssembly().Location Assembly.GetEntryAssembly().LocationAssembly.GetExecutingAssembly().Location

Use in combination with System.IO.Path.GetDirectoryName() to get only the directory.System.IO.Path.GetDirectoryName()结合使用以仅获取目录。

The paths from GetEntryAssembly() and GetExecutingAssembly() can be different, even though for most cases the directory will be the same. GetEntryAssembly()GetExecutingAssembly()的路径可以不同,即使在大多数情况下目录是相同的。

With GetEntryAssembly() you have to be aware that this can return null if the entry module is unmanaged (ie C++ or VB6 executable).使用GetEntryAssembly()您必须注意,如果入口模块是非托管的(即 C++ 或 VB6 可执行文件),这可能会返回null In those cases it is possible to use GetModuleFileName from the Win32 API:在这些情况下,可以使用 Win32 API 中的GetModuleFileName

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetModuleFileName(HandleRef hModule, StringBuilder buffer, int length);
AppDomain.CurrentDomain.BaseDirectory

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

I didn't see anyone convert the LocalPath provided by .Net Core reflection into a usable System.IO path so here's my version.我没有看到任何人将 .Net Core 反射提供的 LocalPath 转换为可用的 System.IO 路径,所以这是我的版本。

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

   return new FileInfo(exePath).DirectoryName;
       
}

This will return the full C:\\\\xxx\\\\xxx formatted path to where your code is.这将返回完整的C:\\\\xxx\\\\xxx格式路径到您的代码所在的位置。

试试这行简单的代码:

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

With .NET Core 3 and above you will get the .dll and not the .exe file.使用 .NET Core 3 及更高版本,您将获得 .dll 而不是 .exe 文件。 To get the .exe file path you can use.要获取您可以使用的 .exe 文件路径。

var appExePath = Process.GetCurrentProcess().MainModule.FileName;

None of these methods work in special cases like using a symbolic link to the exe, they will return the location of the link not the actual exe.这些方法在特殊情况下都不起作用,例如使用指向 exe 的符号链接,它们将返回链接的位置而不是实际的 exe。

So can useQueryFullProcessImageName to get around that:所以可以使用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) + @"\";
    }
}

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

另一种解决方案是使用指向当前路径的相对路径:

Path.GetFullPath(".")

There are many ways to get executable path, which one we should use it depends on our needs here is a link which discuss different methods.有很多方法可以获得可执行路径,我们应该使用哪种方法取决于我们的需要,这里是一个讨论不同方法的链接。

Different ways to get Application Executable Path 获取应用程序可执行路径的不同方式

我将它用于控制台 + net 6

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

The techniques, and pitfalls, keep changing.技术和陷阱不断变化。 The below assumes you're running a .NET 6 console app on linux (on win/mac the results will follow a similar pattern, just replace /usr/share/ and /home/username/ with the standard locations for your OS).下面假设您在 linux 上运行 .NET 6 控制台应用程序(在 win/mac 上,结果将遵循类似的模式,只需将/usr/share//home/username/替换为您的操作系统的标准位置)。

Demo:演示:

Console.WriteLine("Path.GetDirectoryName(Process.GetCurrentProcess()?.MainModule?.FileName) = " + Path.GetDirectoryName(Process.GetCurrentProcess()?.MainModule?.FileName));
Console.WriteLine("Path.GetDirectoryName(Environment.ProcessPath)                           = " + Path.GetDirectoryName(Environment.ProcessPath));
Console.WriteLine("Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)          = " + Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
Console.WriteLine("Path.GetDirectoryName(Environment.GetCommandLineArgs()[0])               = " + Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]));
Console.WriteLine("AppDomain.CurrentDomain.BaseDirectory                                    = " + AppDomain.CurrentDomain.BaseDirectory);
Console.WriteLine("System.AppContext.BaseDirectory                                          = " + System.AppContext.BaseDirectory);

Results:结果:

Path.GetDirectoryName(Process.GetCurrentProcess()?.MainModule?.FileName) = /usr/share/dotnet
Path.GetDirectoryName(Environment.ProcessPath)                           = /usr/share/dotnet
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)          = /home/username/myproject/bin/Debug/net6.0
Path.GetDirectoryName(Environment.GetCommandLineArgs()[0])               = /home/username/myproject/bin/Debug/net6.0
AppDomain.CurrentDomain.BaseDirectory                                    = /home/username/myproject/bin/Debug/net6.0/
System.AppContext.BaseDirectory                                          = /home/username/myproject/bin/Debug/net6.0/

Each approach has its own pros and cons - see the other answers to learn in which uses cases to use which approach.每种方法都有其优点和缺点 - 请参阅其他答案以了解在哪些用例中使用哪种方法。

I run my .NET 6 console app with dotnet myapp , so I use:我用dotnet myapp运行我的 .NET 6 控制台应用程序,所以我使用:

Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)

In .NET 6, my WPF app ( <TargetFramework>net6.0-windows</TargetFramework> ) returns the .dll file path for Assembly.GetEntryAssembly()..Location instead of the .exe file. In .NET 6, my WPF app ( <TargetFramework>net6.0-windows</TargetFramework> ) returns the .dll file path for Assembly.GetEntryAssembly()..Location instead of the .exe file. They introduced System.Environment.ProcessPath for this purpose:他们为此引入了System.Environment.ProcessPath

var path = Environment.ProcessPath; // Note it may be null

Returns the path of the executable that started the currently executing process.返回启动当前执行进程的可执行文件的路径。 Returns null when the path is not available.当路径不可用时返回null

See discussion for it here and here .请参阅此处此处的讨论。

Here is a reliable solution that works with 32bit and 64bit applications.这是一个适用于32 位64 位应用程序的可靠解决方案。

Add these references:添加这些参考:

using System.Diagnostics;使用 System.Diagnostics;

using System.Management;使用 System.Management;

Add this method to your project:将此方法添加到您的项目中:

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

Now use it like so:现在像这样使用它:

int RootProcessId = Process.GetCurrentProcess().Id;

GetProcessPath(RootProcessId);

Notice that if you know the id of the process, then this method will return the corresponding ExecutePath.注意,如果你知道进程的id,那么这个方法会返回对应的ExecutePath。

Extra, for those interested:额外的,对于那些有兴趣的人:

Process.GetProcesses() 

...will give you an array of all the currently running processes, and... ...将为您提供所有当前正在运行的进程的数组,并且...

Process.GetCurrentProcess()

...will give you the current process, along with their information eg Id, etc. and also limited control eg Kill, etc.* ...将为您提供当前进程,以及他们的信息(例如 Id 等)以及有限的控制(例如 Kill 等)*

You can create a folder name as Resources within the project using Solution Explorer,then you can paste a file within the Resources.您可以使用解决方案资源管理器在项目中创建一个文件夹名称作为资源,然后您可以在资源中粘贴一个文件。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在 .NET 控制台应用程序中获取路径 - how to get the path in a .NET console application 如何获取.NET应用程序的路径(而不是启动应用程序的应用程序的路径) - How do I get my .NET application's path (not the path of the application that started my application) 如何以编程方式获取另一个应用程序的安装路径? - How can I get another application's installation path programmatically? 如何在.Net控制台应用程序中获取承载令牌? - how do i get a bearer token in a .Net console application? 我怎样才能端到端地测试这个 .net 核心控制台应用程序? - How can I end to end test this .net core console application? 如何在 a.Net 6 控制台应用程序中读取 appsettings.json? - How can I read the appsettings.json in a .Net 6 console application? 如何获取控制台应用程序窗口的句柄 - How do I get the handle of a console application's window 如何在 C# 控制台应用程序中获取光标处的字符? - How can I get the character at the cursor in a C# console application? 如何获取当前用户的“Application Data”文件夹的路径? - How can i get the path of the current user's “Application Data” folder? 如何获取 .Net Core 控制台应用程序的 .exe 文件所在目录的路径? - How to get the path of the directory where the .exe file for a .Net Core console application is located?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM