ここでは、自分自身のアプリケーションの実行ファイルのパスや、実行ファイルのあるフォルダのパスを取得する方法を紹介します。また、VB6のApp.Pathの代わりになる方法を紹介します。
Assembly.GetExecutingAssemblyメソッドが返すAssemblyオブジェクトのLocationプロパティにより、自分自身のアプリケーションの実行ファイルのパスを取得することができます。
'自分自身の実行ファイルのパスを取得する Dim appPath As String = _ System.Reflection.Assembly.GetExecutingAssembly().Location
//自分自身の実行ファイルのパスを取得する string appPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
Assembly.GetExecutingAssemblyメソッドはDLL内で呼び出すと、そのDLLを表すAssemblyを返します。ですので、上記のコードをDLLで呼び出すと、appPathはDLLのパスになります。
Assembly.Locationプロパティの代わりにAssembly.CodeBaseプロパティやAssembly.EscapedCodeBaseプロパティを使ってもパスを取得できます。これらのプロパティはパスをURIで返し、EscapedCodeBaseプロパティはURLエンコードされた文字列を返します。LocationプロパティとCodeBaseプロパティ(あるいはEscapedCodeBaseプロパティ)の違いは下記の補足で説明しますが、片方のプロパティで目的のパスが取得できなくても、もう片方のプロパティで取得できる場合もあります。
なおURIをWindowsで使われる普通のパス形式に変換する方法は、「URIのローカルファイルパスをWindowsのパス形式に変換する」で説明しています。
補足:上記以外のLocationとCodeBase(あるいはEscapedCodeBase)プロパティの違いについては、「Assembly.CodeBase vs. Assembly.Location - Suzanne Cook's .NET CLR Notes - Site Home - MSDN Blogs」に説明があります。これによると、例えばアセンブリがインターネットからダウンロードされた場合、CodeBaseは「http://」で始まる文字列になり、Locationは「C:\」で始まる文字列になるということです。また、ファイルがシャドウコピーされた場合は、CodeBaseはシャドウコピーされる前の場所を返し、Locationはシャドウコピーされた後の場所を返します。(例えばASP.NETにおいては、GetExecutingAssemblyメソッドが返すAssemblyのCodeBaseはbinディレクトリのDLLになり、LocationはHttpRuntime.CodegenDirプロパティが返すディレクトリのDLLになるようです。また、MbUnit.GUIのようなツールを使用した時も違うパスになるようです。)さらに、GACのアセンブリではCodeBaseがセットされないかもしれませんが、Locationは必ずセットされるということです。
これらのプロパティの違いが分かる例を以下に示します。
'「C:\My Application\ClassLibrary1.dll」に書かれた以下のコードを '「C:\My Application\Application.exe」から呼び出した時の結果をコメントに記す Console.WriteLine(System.Reflection.Assembly.GetExecutingAssembly().Location) 'C:\My Application\ClassLibrary1.dll Console.WriteLine(System.Reflection.Assembly.GetExecutingAssembly().CodeBase) 'file:///C:/My Application/ClassLibrary1.DLL Console.WriteLine(System.Reflection.Assembly.GetExecutingAssembly().EscapedCodeBase) 'file:///C:/My%20Application/ClassLibrary1.DLL
//「C:\My Application\ClassLibrary1.dll」に書かれた以下のコードを //「C:\My Application\Application.exe」から呼び出した時の結果をコメントに記す Console.WriteLine(System.Reflection.Assembly.GetExecutingAssembly().Location); //C:\My Application\ClassLibrary1.dll Console.WriteLine(System.Reflection.Assembly.GetExecutingAssembly().CodeBase); //file:///C:/My Application/ClassLibrary1.DLL Console.WriteLine(System.Reflection.Assembly.GetExecutingAssembly().EscapedCodeBase); //file:///C:/My%20Application/ClassLibrary1.DLL
DLL内で使用してもEXEファイルのパスを取得するには、GetExecutingAssemblyメソッドの代わりにAssembly.GetEntryAssemblyメソッドを使用します。
GetEntryAssemblyメソッドはアンマネージコードから呼び出された時などではNULLを返しますので、通常はNULLのチェックが必要です。
先ほどのGetExecutingAssemblyメソッドの使用例をGetEntryAssemblyに置き換えたものを以下に示します。
'「C:\My Application\ClassLibrary1.dll」に書かれた以下のコードを '「C:\My Application\Application.exe」から呼び出した時の結果をコメントに記す Console.WriteLine(System.Reflection.Assembly.GetEntryAssembly().Location) 'C:\My Application\Application.exe Console.WriteLine(System.Reflection.Assembly.GetEntryAssembly().CodeBase) 'file:///C:/My Application/Application.EXE Console.WriteLine(System.Reflection.Assembly.GetEntryAssembly().EscapedCodeBase) 'file:///C:/My%20Application/Application.EXE
//「C:\My Application\ClassLibrary1.dll」に書かれた以下のコードを //「C:\My Application\Application.exe」から呼び出した時の結果をコメントに記す Console.WriteLine(System.Reflection.Assembly.GetEntryAssembly().Location); //C:\My Application\Application.exe Console.WriteLine(System.Reflection.Assembly.GetEntryAssembly().CodeBase); //file:///C:/My Application/Application.EXE Console.WriteLine(System.Reflection.Assembly.GetEntryAssembly().EscapedCodeBase); //file:///C:/My%20Application/Application.EXE
Windowsフォームアプリケーションでは、アプリケーションを開始した実行ファイルのフルパスをApplication.ExecutablePathプロパティで取得できます。また、アプリケーションを開始した実行ファイルのフォルダはApplication.StartupPathプロパティで取得できます。
Application.ExecutablePathプロパティとApplication.StartupPathプロパティは、DLL内で使用したとしても、EXEファイルのパスを返します。
補足:Application.ExecutablePathは、基本的にはAssembly.GetEntryAssemblyメソッドが返すAssemblyのCodeBaseとなり、GetEntryAssemblyメソッドがNULLを返したらWin32 APIのGetModuleFileName関数の結果を返すようです。Application.StartupPathプロパティは、GetModuleFileName関数の結果からフォルダ名を返しているようです。
Console.WriteLine(System.Windows.Forms.Application.ExecutablePath) 'C:\My Application\Application.exe Console.WriteLine(System.Windows.Forms.Application.StartupPath) 'C:\My Application
Console.WriteLine(System.Windows.Forms.Application.ExecutablePath); //C:\My Application\Application.exe Console.WriteLine(System.Windows.Forms.Application.StartupPath); //C:\My Application
.NET Framework 2.0以降のVB.NETでは、「My.Application.Info.DirectoryPath」によってアプリケーションのフォルダを取得できます。これは、Application.StartupPathプロパティとほぼ同等です。
補足:My.Application.Info.DirectoryPathは、基本的には「Assembly.GetEntryAssembly().Location」のフォルダですが、GetEntryAssemblyがNULLを返す時は、「Assembly.GetCallingAssembly().Location」のフォルダとなるようです。
Console.WriteLine(My.Application.Info.DirectoryPath)
'C:\My Application
現在のアプリケーションドメインのベースディレクトリは、「AppDomain.CurrentDomain.BaseDirectory」で取得できます。これは、「AppDomain.CurrentDomain.SetupInformation.ApplicationBase」と同じです。このフォルダは大抵実行ファイルのフォルダと同じになりますが、そうでない可能性もあります。
Console.WriteLine(System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase)
'C:\My Application\
Console.WriteLine(System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase);
//C:\My Application\
MSDNの「App Object Changes in Visual Basic .NET」によると、VB6のApp.Pathに代わるものは「System.Reflection.Assembly.GetExecutingAssembly().Location」とのことです。ただしこれはファイルのフルパスを返しますので、App.Pathと同じようにフォルダのパスのみを取得するのであれば、さらにPath.GetDirectoryNameメソッドを使います。
Public Shared Function GetAppPath() As String Return System.IO.Path.GetDirectoryName( _ System.Reflection.Assembly.GetExecutingAssembly().Location) End Function
public static string GetAppPath() { return System.IO.Path.GetDirectoryName( System.Reflection.Assembly.GetExecutingAssembly().Location); }
また、MSDNの「HOW TO: Determine the Executing Application's Path」によると、「System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase」がApp.Pathの代わりになるとのことです。ただしこの場合、返されるパスはURIになりますので、必要ならば変換が必要になります。その方法は、「URIのローカルファイルパスをWindowsのパス形式に変換する」で説明しています。
Public Shared Function GetAppPath2() As String Dim path As String = _ System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase 'URIを通常のパス形式に変換する Dim u As New Uri(path) path = u.LocalPath + Uri.UnescapeDataString(u.Fragment) Return System.IO.Path.GetDirectoryName(path) End Function
public static string GetAppPath2() { string path = System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase; //URIを通常のパス形式に変換する Uri u = new Uri(path); path = u.LocalPath + Uri.UnescapeDataString(u.Fragment); return System.IO.Path.GetDirectoryName(path); }
補足:「c# - How do I find the current executable filename? - Stack Overflow」によると、Xenocode Postbuildのような仮想化された環境では、上記のどの方法でも正しく実行ファイルのフルパスを取得できないということです。ただし、実行ファイルのフォルダは「Assembly.GetEntryAssembly().Location」で、ファイル名は「Process.GetCurrentProcess().ProcessName」で正しく取得できるのため、この2つを合わせてフルパスを作成できるそうです。