843

コンソールアプリケーションでアプリケーションのパスを確認する方法

Windowsフォーム、 私は使えますApplication.StartupPath現在のパスを見つけるためですが、これはコンソールアプリケーションでは利用できないようです。


  • .NET Frameworkをターゲット(クライアント、開発)マシンにインストールしますか?あなたの答えが真実ならば。そのため、System.Windows.Forms.dllへの参照を追加してApplication.StartupPathを使用できます。将来の例外をさらに排除したい場合は、これが最善の方法です。 - Ehsan Mohammadi
  • AppDomain.BaseDirectoryはアプリディレクトリです。アプリケーションはVS envとWin envで異なる動作をする可能性があることに注意してください。しかし、AppDomainはapplication.pathと同じではないはずですが、これがIISだけではないことを私は願っています。 - Mertuarez

26 답변


1060

System.Reflection.Assembly.GetExecutingAssembly()Location1

と組み合わせるSystem.IO.Path.GetDirectoryName必要なのはディレクトリだけです。

1Mr.Mindorのコメントによると:

System.Reflection.Assembly.GetExecutingAssembly().Location実行中のアセンブリが現在配置されている場所を返します。実行中でない場合は、アセンブリが配置されている場所である場合とそうでない場合があります。シャドウコピーアセンブリの場合は、一時ディレクトリにパスを取得します。System.Reflection.Assembly.GetExecutingAssembly().CodeBaseアセンブリの「恒久的な」パスを返します。


  • System.Reflection.Assembly.GetExecutingAssembly()。Locationは、実行中のアセンブリが存在する場所を返します。現在実行されていないときにアセンブリが配置されている場所である場合とそうでない場合があります。シャドウコピーアセンブリの場合は、一時ディレクトリにパスを取得します。 System.Reflection.Assembly.GetExecutingAssembly()。CodeBaseは'を返します。恒久的な'アセンブリのパス - Mr.Mindor
  • @ SamGoldberg:それは使い方によって異なります。stackoverflow.com/q/1068420/391656。または、できます...新しいUri(System.Reflection.Assembly.GetExecutingAssembly()。CodeBase).LocalPath - Mr.Mindor
  • 何らかの理由で、VS2013(少なくとも私が持っているコピー)ではインテリセンスはSystem.Reflection.Assemblyを越えては動きません。 GetExeuctingAssembly()はありますが、見えません。 - PseudoToad
  • GetExecutingAssemblyそのアセンブリを返します現在実行中のコードが含まれています。これは必ずしもコンソールではないかもしれません。EXEアセンブリ。まったく別の場所からロードされたアセンブリかもしれません。あなたが使用する必要がありますGetEntryAssembly!また注意してくださいCodeBaseアセンブリがGAC内にあるときは設定されない可能性があります。より良い代替手段はAppDomain.CurrentDomain.BaseDirectory。 - bitbonk
  • コピーしやすいように4つのスペースにコードを書いてください - fnc12

374

現在のアプリケーションディレクトリを取得するには、次のコードを使用できます。

AppDomain.CurrentDomain.BaseDirectory


  • これを使用しないでください。 BaseDirectoryは実行時に設定できます。それが正しいことを保証するものではありません(受け入れられている答えがそうであるように)。 - usr
  • +1これはシャドウコピーを補正するので、おそらくあなたが望む答えです。 - George Mauer
  • @usrあなたはそれをどう思いますかBaseDirectory実行時に設定できますか?ゲッターしかありません。 - bitbonk
  • @bitbonkはドメイン作成時に設定できます。 - usr
  • BaseDirectoryを* .lnkファイルの[開始場所]で変更できることがわかりません。フィールド? - Alexander

133

アプリケーションのディレクトリを見つけるには、目的に応じて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);


  • 言いたいことは、他の選択肢がいくつ掲載されているかによって、2つ以上の選択肢があることです。 - vapcguy
  • 上記のパスで何をしようとしてもURI形式をサポートしていない場合は、var localDirectory = new Uri(directory).LocalPath; - Okuma.Scott
  • これは間違っています。実行ファイルは、.NETアセンブリではありません。正しい答えは、環境を確認してコマンドラインを調べることです。 - mark

73

おそらく少し遅いですが、これは言及する価値があります。

Environment.GetCommandLineArgs()[0];

もっと正確に言えば、ディレクトリパスだけを取得するのです。

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

編集する

かなり少数の人々がそれを指摘していますGetCommandLineArgsプログラム名を返すことは保証されていません。見るコマンドラインの最初の単語は、慣例によってのみプログラム名です。。この記事には、「ごく少数のWindowsプログラムがこの風変わりなものを使用していますが、私は自分自身を認識していません」と述べています。だから、「なりすまし」することは可能ですGetCommandLineArgsしかし、私たちはコンソールアプリケーションについて話しています。コンソールアプリは通常素早くて汚い。それで、これは私のKISS哲学に適合します。


  • そして多分これ:path = Environment.GetCommandLineArgs()[0] .Substring(0、iniFilePath.LastIndexOf(" \\")+ 1); - fabspro
  • あなたがほのめかす状況は非常に理論的です。コンソールアプリケーションのコンテキストでは、他の方法を使用しても意味がありません。複雑にしないでおく! - Steve Mc
  • @usr mmm - taskmgr cmdlineの列を見てみると、私が言っていることがバックアップされます。 exeファイル名だけでいくつかのシステムサービス。気にしないで。私が言おうとしているのは、コンソールアプリケーションを開発するとき、必要以上に複雑にする必要はないということです。特に私たちがすでに情報を手に入れているときは特にそうです。今、あなたがGetCommandLineArgsをトリックするような方法でコンソールアプリケーションを実行しているなら、あなたはすでにフープを飛び越えています、そしてあなたはおそらくコンソールアプリケーションが正しい方法であるかどうかあなた自身に尋ねる必要があるでしょう。 - Steve Mc
  • あなたの"シンプル"解決策は2つのメソッド呼び出しを含みます。 "複雑"解決策は2つのメソッド呼び出しを含みます。実用的な違いはありません - "シンプル"を除いてあなたがプログラムを書いているときに解決策はあなたの制御下にない特定の状況下であなたに間違った答えを与えることができます。なぜ危険を冒しますか?他の2つのメソッド呼び出しを使用すると、プログラムはこれ以上複雑にはなりませんが、信頼性が増します。 - Chris
  • 私のシナリオではうまくいきましたが、他の解決策では解決できませんでした。別の方法を提供してくれてありがとう:-)私はMS Unitテストを実行するのにReSharperテストランナーを使っていました。 ..and Assembly.GetExecutingDirectory()は奇妙に違う結果を返します。 - wallismark

40

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アプリには適していません。


35

上記の答えは私が必要としていたものの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;


  • 問題のexeファイルがWindowsサービスで、現在のディレクトリがC:\ Windows \ system32を返す場合もこれはうまく機能します。上記のコードはexeファイルの実際の場所を返します - DaImTo
  • あなたがそれから何かをやろうとする場合を除いてFile.CreateDirectory(path)URIパスを許可しないという例外が発生します。 - vapcguy
  • 残念ながら、これはフラグメント識別子を含むパスに対しては機能しません(#キャラクター)。識別子とそれに続くすべてのものは、結果のパスから切り捨てられます。 - Mark
  • 交換しないのはなぜですかnew UriそしてSystem.IO.Path.GetDirectoryName?それはあなたの代わりに通常のパス文字列を与えるUri。 - Timo
  • これが一番いいと思います。この同じアプローチはどんな環境でも私には確実に働きました。プロダクション、ローカルでのデバッグ、単体テスト...単体テストに含めたコンテンツファイル(「content - 新しい場合はコピー」)を開きますか?そこにあります。 - Timo

27

あなたはこれをすることを探しているかもしれません:

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


20

代わりにこれを使うことができます。

System.Environment.CurrentDirectory


  • これは実行可能ファイルのフォルダを取得します - Iain
  • 何かがDirectory.SetCurrentDirectory()と呼ばれていない限り... - Matthew Watson
  • @ MatthewWatsonまたはもっと簡単には、プログラムは別のフォルダから実行された... - Ohad Schneider

18

コンソールアプリケーションの場合は、これを試すことができます。

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¥


13

私はこのコードを使い、解決策を見つけました。

AppDomain.CurrentDomain.BaseDirectory


9

.NET Coreと互換性のある方法を探しているなら、

System.AppContext.BaseDirectory

これは、.NET Framework 4.6および.NET Core 1.0(および.NET Standard 1.3)で導入されました。見る:AppContext.BaseDirectoryプロパティ

によるこのページ

これは.NET CoreでのAppDomain.CurrentDomain.BaseDirectoryの推奨置換です。


7

exeファイルがそれをダブルクリックして呼び出されることになっている場合、私はこれを使用します

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


  • ランダムなディレクトリになる可能性があるため、これは正しくありません。 - amuliar

7

利用した

System.AppDomain.CurrentDomain.BaseDirectory

アプリケーションフォルダへの相対パスを見つけたいとき。これは、ASP.Netとwinformの両方のアプリケーションで機能します。 System.Webアセンブリへの参照も必要ありません。


7

あなたは単にあなたのプロジェクト参照に追加することができますSystem.Windows.FormsそれからSystem.Windows.Forms.Application.StartupPathいつものように 。

そのため、より複雑な方法やリフレクションを使用する必要はありません。


  • 私はそれを使いました、そしてそれはうまくいきます。しかし、私は自分のユニットテストプロジェクトでそれを使った方法を使いました。もちろん、C:¥PROGRAM FILES(X86)¥MICROSOFT VISUAL STUDIO 14.0¥COMMON7¥IDE¥COMMONEXTENSIONS¥MICROSOFT¥TESTWINDOWで自分のファイルを探していたため、失敗しました。 - ainasiart

6

つまり、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");


  • これほど多くの.NETがあるのにp / invokeを実行するのはなぜでしょうか。 - ProfK
  • なぜですか? - user3596865
  • @ user3596865は、Windowsへの強い依存関係が必要であり、DNXまたはMonoと互換性がないためです。そして、おそらく将来のWindowsバージョンでは大きな変化があります。繰り返しになりますが、なぜここでpinvokeを使うべきなのでしょうか。 - Ben

4

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


4

AppDomain.CurrentDomain.BaseDirectory

サードパーティの参照ファイルをインストールパッケージで参照することで問題を解決します。


  • この答えは5年前にすでに示唆されています。 - P-L

3

VB.netで

My.Application.Info.DirectoryPath

私のために動作します(アプリケーションタイプ:クラスライブラリ)。 C#についてよくわからない... ファイル名なしのパスを文字列として返します。


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


2

次の簡単なコードを試してください。

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


2

次の行はあなたにアプリケーションパスを与えるでしょう:

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

上記の解決策は、以下の状況で適切に機能しています。

  • シンプルなアプリ
  • Assembly.GetEntryAssembly()がnullを返す別のドメイン内
  • DLLはバイト配列としてEmbeddedリソースからロードされ、Assembly.Load(byteArrayOfEmbeddedDll)としてAppDomainにロードされます。


0

.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"形式のパスが返されます。


0

実行可能パスを取得する方法は多数ありますが、必要に応じて使用する方法は、さまざまな方法について説明したリンクです。

アプリケーション実行可能パスを取得するためのさまざまな方法


0

次のコードを使用すると、アプリケーションのフルパスを取得できます。

 class Program
{
    static void Main(string[] args)
    {
        string AppPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
        WriteLine($"ApplicationPath ---{AppPath}");
        //OutPut// //ApplicationPath---C:\Users\TestUser\source\repos\ThreadStack\ThreadStack\bin\Debug\ThreadStack.exe
        ReadLine();
    }
}  


-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など、また制限された管理。殺害など


-5

ソリューションエクスプローラーを使用してプロジェクト内にリソースとしてフォルダー名を作成してから、リソース内にファイルを貼り付けることができます。

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


  • Environment.CurrentDirectoryの使用は非常に間違っています。使用しないでください。このパスは実行時に変わる可能性があります。起動時でさえ、それは非決定的です。 - usr

リンクされた質問


関連する質問

最近の質問