programing

에서 응용 프로그램의 경로를 가져오려면 어떻게 해야 합니까?NET 콘솔 애플리케이션?

lovejava 2023. 5. 4. 17:51

에서 응용 프로그램의 경로를 가져오려면 어떻게 해야 합니까?NET 콘솔 애플리케이션?

콘솔 응용 프로그램에서 응용 프로그램의 경로를 찾으려면 어떻게 해야 합니까?

Windows Forms에서 사용할 수 있는 기능Application.StartupPath현재 경로를 찾지만 콘솔 응용 프로그램에서는 사용할 수 없는 것 같습니다.

System.Reflection.Assembly.GetExecutingAssembly().Location1

디렉토리만 원하는 경우 이를 와 결합합니다.

1Mindor씨의 논평에 따르면:
System.Reflection.Assembly.GetExecutingAssembly().Location실행 중인 어셈블리가 현재 있는 위치를 반환합니다. 이 위치는 실행 중이지 않을 때 어셈블리가 있는 위치일 수도 있고 아닐 수도 있습니다.섀도 복사 어셈블리의 경우 임시 디렉터리의 경로를 얻을 수 있습니다. 어셈블리의 '영구적' 경로를 반환합니다.

다음 코드를 사용하여 현재 응용 프로그램 디렉터리를 가져올 수 있습니다.

AppDomain.CurrentDomain.BaseDirectory

응용프로그램 디렉토리를 찾는 데는 두 가지 옵션이 있으며, 사용자의 목적에 따라 선택할 수 있습니다.

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

조금 늦었을 수도 있지만, 이것은 언급할 가치가 있습니다.

Environment.GetCommandLineArgs()[0];

또는 디렉터리 경로만 가져오는 것이 더 정확합니다.

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

편집:

이 그것을 지적했습니다.GetCommandLineArgs프로그램 이름을 반환하는 것이 보장되지 않습니다.참고 항목명령줄의 번째 단어는 규약에 의한 프로그램 이름입니다.이 문서에는 "극소수의 Windows 프로그램에서 이 특이점을 사용하지만 (나는 나 자신을 알지 못합니다)"라고 나와 있습니다.그래서 '스푸핑'하는 것이 가능합니다.GetCommandLineArgs콘솔 애플리케이션에 대해 이야기하고 있습니다.콘솔 앱은 일반적으로 빠르고 더럽습니다.그래서 이것은 저의 KISS 철학과 일치합니다.

편집 피드백을 보면 유닛 테스트 시스템을 사용할 때 대부분의 다른 솔루션이 작동하지 않는 것 같습니다.실행 가능한 항목이 응용 프로그램이 아니라 테스트 시스템이기 때문에 이러한 종류의 작업이 타당합니다.저는 이것을 확인하지 못했기 때문에 완전히 틀릴 수 있습니다.그렇다면 이 편집 내용을 삭제하겠습니다.

asp.net 웹 앱에 관심이 있는 모든 사람을 위한 것입니다.여기 세 가지 다른 방법의 결과가 있습니다.

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\"에서 물리적으로 실행되고 있습니다."SBS Portal_staging". 따라서 첫 번째 솔루션은 웹 애플리케이션에 적합하지 않습니다.

위의 답변은 제가 필요한 것의 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;

만약 당신이 a를 찾고 있다면.NET Core 호환 방법, 사용

System.AppContext.BaseDirectory

이 기능은 에서 도입되었습니다.NET Framework 4.6 및 .NET Core 1.0(및 .NET 표준 1.3).AppContext를 참조하십시오.기본 디렉터리 속성입니다.

페이지에 따르면,

AppDomain의 기본 대체 버전입니다.현재 도메인.기본 디렉토리입니다.NET 코어

다음과 같은 작업을 수행할 수 있습니다.

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

당신은 이것을 대신 사용할 수 있습니다.

System.Environment.CurrentDirectory

콘솔 응용 프로그램의 경우 다음을 시도할 수 있습니다.

System.IO.Directory.GetCurrentDirectory();

출력(내 로컬 컴퓨터에서):

c:\users\xxxxxxx\documents\visual studio 2012\Projects\ImageHandler\GetDir\bin\디버깅

또는 다음과 같이 시도할 수 있습니다(결국 백슬래시가 추가됨).

AppDomain.CurrentDomain.BaseDirectory

출력:

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

나는 이 코드를 사용했고 해결책을 얻었습니다.

AppDomain.CurrentDomain.BaseDirectory

다음 행에 응용 프로그램 경로가 표시됩니다.

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

위 솔루션은 다음과 같은 상황에서 올바르게 작동합니다.

  • 간단한 앱
  • 의회가 있는 다른 도메인에서.GetEntryAssembly()가 null을 반환합니다.
  • DLL은 Embedded 리소스에서 바이트 배열로 로드되고 AppDomain에 Assembly로 로드됩니다.로드(바이트 배열OfEmbeddedDll)
  • 모와함께와 mkbundle수 없음)을 사용합니다.

에 간단히 할 수 .System.Windows.Forms그런 다음 사용합니다.System.Windows.Forms.Application.StartupPath때처럼

따라서, 더 복잡한 방법이나 반사를 사용할 필요가 없습니다.

사용한 적이 있습니다.

System.AppDomain.CurrentDomain.BaseDirectory

응용 프로그램 폴더와 관련된 경로를 찾고자 할 때이것은 두 ASP 모두에 대해 작동합니다.Net 및 Winform 애플리케이션.또한 시스템에 대한 참조도 필요하지 않습니다.웹 어셈블리.

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

애플리케이션과 마찬가지로 사용할 수 있습니다.시작 경로:

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

에서 제공한 LocalPath를 변환하는 사용자를 보지 못했습니다.코어 반사를 사용 가능한 시스템으로 변환합니다.IO 경로는 다음과 같습니다.

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

   return new FileInfo(exePath).DirectoryName;
       
}

전체값을반다니합환▁the▁full다가 반환됩니다.C:\\xxx\\xxx코드가 있는 위치에 대한 형식화된 경로입니다.

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

EXE를 두 번 클릭하여 호출해야 하는 경우 사용합니다.

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

VB.net 에서

My.Application.Info.DirectoryPath

사용할 수 있습니다(응용 프로그램 유형: 클래스 라이브러리).C#에 대해서는 잘 모르겠습니다...파일 이름이 없는 경로를 문자열로 반환합니다.

AppDomain.CurrentDomain.BaseDirectory

타사 참조 파일을 설치 패키지와 함께 참조하는 문제를 해결합니다.

.NET Core 3 이상에서는 .exe 파일이 아닌 .dll을 얻을 수 있습니다.사용할 수 있는 .exe 파일 경로를 가져옵니다.

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

다음과 같은 간단한 코드 행을 사용해 보십시오.

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

.NET 6에는 환경이 있습니다.프로세스 경로.

https://learn.microsoft.com/en-us/dotnet/api/system.environment.processpath?view=net-6.0 을 참조하십시오.

이러한 메소드는 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) + @"\";
    }
}

Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName)내가 시도한 모든 사건에서 나를 위해 일한 유일한 사람입니다.

.NET 6에서, 내 WPF 앱 (<TargetFramework>net6.0-windows</TargetFramework>) 를 반환합니다..dll파일 경로:Assembly.GetEntryAssembly()!.Location대신에.exe파일. 그들은 다음과 같은 목적으로 도입했습니다.

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

현재 실행 프로세스를 시작한 실행 파일의 경로를 반환합니다.돌아온다null경로를 사용할 수 없는 경우.

여기와 여기에서 토론을 참조하십시오.

기술과 함정은 계속해서 변화합니다.다음은 를 실행하는 것으로 가정합니다.리눅스의 NET 6 콘솔 앱(윈/맥의 경우 결과가 유사한 패턴을 따를 것입니다. 그냥 교체하십시오./usr/share/그리고./home/username/OS의 표준 위치를 사용합니다.).

데모:

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("typeof(SomeType).Assembly.Location                                       = " + typeof(SomeType).Assembly.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);

결과:

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
typeof(SomeType).Assembly.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/

각 접근 방식에는 장단점이 있습니다. 다른 답변을 참조하여 어떤 접근 방식을 사용할 때 사례를 사용하는지 알아보십시오.

제가 운영합니다.NET 6 콘솔 앱과 함께 사용dotnet myapp그래서 저에게 효과가 있는 것은 다음 중 하나입니다.

typeof(SomeType).Assembly.Location
// or
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)

콘솔 + 넷 6에 사용합니다.

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

다음은 32비트64비트 응용 프로그램에서 작동하는 안정적인 솔루션입니다.

다음 참조를 추가합니다.

시스템을 사용합니다.진단;

시스템을 사용합니다.관리;

이 메서드를 프로젝트에 추가합니다.

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 등 및 제한된 제어(예: 킬 등)*

솔루션 탐색기를 사용하여 프로젝트 내에 리소스로 폴더 이름을 생성한 다음 리소스 내에 파일을 붙여넣을 수 있습니다.

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

언급URL : https://stackoverflow.com/questions/837488/how-can-i-get-the-applications-path-in-a-net-console-application