C# サンプル集 |
Visual Basic 中学校 > C# サンプル集 > C# サンプル集目次 >
実行中のプログラムのパスを取得する
2020/8/2
「実行中のプログラムのパス」とは深く考えるといろいろな状況や意味があり、この単純な質問に単純な答えで回答することはできません。
ここで紹介する例があなたの環境に適したあなたの欲しい答えを取得するものであるかどうか、重要なシステムで使用する場合は事前に確認をお願いします。
1.実行を開始したexe/dllのパスを取得する
この例は A.exeで実行してもB.dllで実行してもC.dllで実行しても A.exeのパスを返します。
string appPath = AppDomain.CurrentDomain.BaseDirectory.TrimEnd('\\'); |
この例を実行すると appPath は次のような値になります。
C:\Users\rucio\Source\Repos\AppPathTest\AppPathTest\bin\Debug
BaseDirecotryプロパティは本来はアセンブリを探す起点となるパスです。これは実行の起点となるパス(A.exeのパス)と一致するようです。私が試した範囲でも100%一致します。他にもこの方法で実行パスを取得しているプログラマーは多数いるようです。
2.実行しているプログラムが格納されているexe/dllのパスを取得する
この例はA.exeに記述すればA.exeのパスを、B.dll、C.dllに記述すればそれぞれB.dll、C.dllのパスを返します。このパスは「コードベース」(後述)のパスです。
System.Reflection.Assembly executionAsm = System.Reflection.Assembly.GetExecutingAssembly(); string executingPath = System.IO.Path.GetDirectoryName(new Uri(executionAsm.CodeBase).LocalPath); |
この例を実行すると executingPath の値は次のようになります。
C:\Users\rucio\Source\Repos\AppPathTest\AppPathTest\bin\Debug
コードベースについて
多くの場合、実行しているプログラム格納されているexe/dllパスが、実際にそのexe/dllを実行しているパスですが、ホスティングされている場合など、実際に実行するdllが存在するパスと、そのdllが取得された場所(コードベース)は異なる場合があります。
たとえば、Visual StudioでWebアプリケーションをデバッグ実行すると、コンパイルされたdllファイルはプロジェクトのbinフォルダーに生成されます。これがコードベースとなります。たとえば、次のようなパスです。
コードベースのパスの例
C:\Users\rucio\Source\Repos\AppPathTest\AppPathTestWeb\bin\AppPathTestWeb.dll
開発用Webサーバーはこれを別の場所にコピーして実行します。たとえば、次のような場所です。
実際に実行されているパスの例
C:\Users\rucio\AppData\Local\Temp\Temporary ASP.NET Files\vs\f1cbab9f\fdff6b1d\assembly\dl3\4acbe833\0c6900e9_7e31d601\AppPathTestWeb.dll
この例が取得しているのは上記のコードベースの方です。
私の経験上は、実際に実行されているパスを取得するよりもコードベースを取得したほうが役に立ちます。なぜなら、人間が配置して、置いてあると認識しているパスはコードベースの方だからです。1つ目の例で紹介しているAppDomainの例もこのコードベースの方を指しています。
3.実行しているexe/dllのパスを取得する
上記の例で言う、実際に実行されているパスを取得します。
この例はA.exeに記述すればA.exeのパスを、B.dll、C.dllに記述すればそれぞれB.dll、C.dllのパスを返します。
System.Reflection.Assembly executionAsm = System.Reflection.Assembly.GetExecutingAssembly(); string actualPath = System.IO.Path.GetDirectoryName(executionAsm.Location); |
この例をWebアプリケーションで実行すると actualPath の値は次のようになります。
C:\Users\rucio\AppData\Local\Temp\Temporary ASP.NET Files\vs\f1cbab9f\fdff6b1d\assembly\dl3\4acbe833\e0f47427_8e31d601
備考
その他にもいろいろな方法があります。
実行パスを取得する方法の候補 | 評価 | 何を取得? | 難点 |
---|---|---|---|
AppDomain.CurrentDomain.BaseDirectory(例1で紹介) | A | 実行の起点であるファイルのパス | 本来は実行パスを取得する目的ではない。 |
Reflection.Assembly.GetExecutingAssembly().CodeBase(例2で紹介) | A | 実行しているファイルのパス | |
Reflection.Assembly.GetExecutingAssembly().Location(例3で紹介) | B | 実行しているファイルのパス | 自動的にコピーされた場所を指している場合がある。 |
Environment.GetCommandLineArgs()[0] | C | 実行の起点であるファイルのパス | Webアプリなどホスティング環境ではホストを示す。 |
Application.StartupPath | C | 実行の起点であるファイルのパス | Windowsフォームアプリ専用。 |
Reflection.Assembly.GetEntryAssembly().Location (or CodeBase) | C | 実行の起点であるファイルのパス | Webアプリなどで使用できない。 |
Environment.CurrentDirectory | E | (カレントディレクトリー) | 実行状況によって値が異なる。 |
Diagnostics.Process.GetCurrentProcess().MainModule.FileName | D | 実行の起点であるファイルのパス | Webアプリなどホスティング環境では意味が違う。 |
System.AppContext.BaseDirectory | B | 実行の起点であるファイルのパス | 本来は実行パスを取得する目的ではない。古い環境で使用できない。 |
Windows API の GetModuleFileName | D | 実行の起点であるファイルのパス | Webアプリなどホスティング環境では意味が違う。 |
this.GetType().Assembly.Location | C | 実行しているファイルのパス | Webアプリなどではフレームワークが自動生成したファイルをさす場合がある。 |
A:これを使っておけばいいと思いますよ。よくわからない人はこれを使いましょう。
B:お好みならこちらを使っても良いです。
C:特定の状況では役に立ちます。
D:役に立つときもありますが、使用に注意が必要なので手を出さない方が無難です。
E:実行パスを取得する方法としては役に立ちません。
コンソールアプリケーションやWindowsフォームアプリケーションのように自分自身が主体となって実行される場合と、ライブラリのように他から呼び出される場合、Webアプリケーションやサービスのように何か別のものにホストされて動作する場合、単体テストから呼び出される場合、さらにはアンマネージドのプログラムから呼び出される場合などいろいろな状況があります。
AppDomain.CurrentDomain.BaseDirectoryはあらゆる状況で使用できる(と思う)ので、A評価にしています。もっと状況が絞れるのであれば他の方法でも問題ありません。たとえば、WindowsフォームアプリケーションではApplication.StartupPathは簡潔でわかりやすいです。
Reflection.Assembly.GetEntryAssembly().Location
多くの場合、これで実行を開始した起点となる(exeまたはdll)の場所を取得できて便利です。
アンマネージドコードから呼び出された場合、GetEntryAssemblyは null を返す場合があるのでその場合だけ注意が必要です。
Webアプリケーションでは null になるようです。
Environment.GetCommandLineArgs()[0]
コンソールアプリケーションやWindowsフォームアプリケーションでは、実行の起点であるファイルのフルパスを指すものとして役に立ちます。
しかし、Webアプリケーションのようなホスティングされた環境ではWebサーバーのようなホスト元の実行ファイルを指します。
たとえば、Visual Studio 2019でWebアプリケーションとして実行するとこの値は C:\Program Files (x86)\IIS Express\iisexpress.exe のようになります。
Application.StartupPath
Windowsフォームアプリケーションの場合、Application.StartupPath は簡単に実行を開始した起点となるexeのパスを取得できて便利です。
System.Environment.CurrentDirectory
これは作業フォルダーを取得する方法なので実行パスを取得する方法としては使用すべきではありません。
作業フォルダーとexe/dllのある場所は一致する方が多いですが、コマンドから起動したり、ショートカットから起動したりすると一致しない場合も珍しくありません。
Diagnostics.Process.GetCurrentProcess().MainModule.FileName
これが役に立つ場合も多いですが、Webアプリケーションのようなホスティングされた環境ではWebサーバーのようなホスト元の実行ファイルを指します。
たとえば、Visual Studio 2019でWebアプリケーションとして実行するとこの値は C:\Program Files (x86)\IIS Express\iisexpress.exe のようになります。
System.AppContext.BaseDirectory
これはおそらく実行の起点となるexe/dllのパスを取得するものとして使用できます。
ただ、比較的新しいメソッドで .NET Frameworkだと4.6以上が必要です。
Windows API の GetModuleFileName
このAPIはWindowsでしか使用できません。Webアプリケーションのようなホスティングされた環境ではWebサーバーのようなホスト元の実行ファイルを指します。
WindowsフォームのApplication.StartupPathは内部でこのAPIを呼び出しています。
this.GetType().Assembly.Location
ASP.NET WebフォームではASPXファイルとコードビハインドで記述されたプログラムが実行時に結合されてビルドされます。このビルドされたファイルのパスを指すようです。
このケースではAssembly.GetExecutingAssemblyの方は結合前のファイルを指すようです。