DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

自分のアプリケーションの実行ファイルのパスを取得する
VB6のApp.Pathと同じ事を行うには?

VB6のApp.Pathは、自分自身のアプリケーションの実行ファイルがあるフォルダのパスを返します。ここでは、実行ファイルがあるフォルダのパスや、実行ファイルのパスを取得する方法を紹介します。

Assembly.GetExecutingAssemblyやGetEntryAssemblyメソッドを使う

MSDNによると、VB6のApp.Pathに代わるものは、「System.Reflection.Assembly.GetExecutingAssembly().Location」とのことです。ただしこれはフォルダ名ではなく、実行ファイルのフルパスになります。よってVB6のApp.Pathと同じものということになると、次のようにPath.GetDirectoryNameメソッドでフォルダ名の部分を取得します。

VB.NET
コードを隠すコードを選択
Public Shared Function GetAppPath() As String
    Return System.IO.Path.GetDirectoryName( _
        System.Reflection.Assembly.GetExecutingAssembly().Location)
End Function
C#
コードを隠すコードを選択
public static string GetAppPath()
{
    return System.IO.Path.GetDirectoryName(
        System.Reflection.Assembly.GetExecutingAssembly().Location);
}

「Assembly.GetExecutingAssembly().Location」をDLL内で呼び出すと、DLLのフルパスを返します。このような場合でもEXEファイルのフルパスを取得できるようにするには、「Assembly.GetEntryAssembly().Location」を使います。

つまり、上記の例でもDLLがあるフォルダのパスを返します。EXEファイルのあるフォルダのパスを返すようにするには、GetExecutingAssemblyの代わりにGetEntryAssemblyを使います。ただしAssembly.GetEntryAssemblyメソッドはアンマネージコードから呼び出されるとNULLを返しますので、NULLのチェックが必要です。

以下にAssembly.GetEntryAssemblyメソッドを使った例を示します。ここではGetEntryAssemblyがNULLを返した時に空白文字列を返すようにしています。

VB.NET
コードを隠すコードを選択
Public Shared Function GetExeAppPath() As String
    Dim asm As System.Reflection.Assembly = _
        System.Reflection.Assembly.GetEntryAssembly()
    If asm Is Nothing Then
        Return ""
    Else
        Return System.IO.Path.GetDirectoryName(asm.Location)
    End If
End Function
C#
コードを隠すコードを選択
public static string GetExeAppPath()
{
    System.Reflection.Assembly asm = System.Reflection.Assembly.GetEntryAssembly();
    if (asm == null)
        return "";
    else
        return System.IO.Path.GetDirectoryName(asm.Location);
}
補足:Assembly.Locationではなく、Assembly.CodeBaseでもアセンブリの場所を取得できます。両者の違いについては、「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になるようです。)さらに、GACのアセンブリではCodeBaseがセットされないかもしれませんが、Locationは必ずセットされるということです。

GetExecutingAssemblyとGetEntryAssembly、及び、Location、CodeBase、EscapedCodeBaseプロパティの違いを示す例を紹介します。

VB.NET
コードを隠すコードを選択
'「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

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#
コードを隠すコードを選択
//「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

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

Application.ExecutablePathとStartupPathプロパティを使う

Windowsフォームアプリケーションでは(そうでなくても可能ですが)、アプリケーションを開始した実行ファイルのフルパスをApplication.ExecutablePathプロパティで、アプリケーションを開始した実行ファイルのフォルダをApplication.StartupPathプロパティで取得できます。

補足:Application.ExecutablePathは、基本的にはAssembly.GetEntryAssemblyメソッドが返すAssemblyのCodeBaseとなり、GetEntryAssemblyメソッドがNULLを返したらWin32 APIのGetModuleFileName関数の結果を返すようです。Application.StartupPathプロパティは、GetModuleFileName関数の結果からフォルダ名を返しているようです。
VB.NET
コードを隠すコードを選択
Console.WriteLine(System.Windows.Forms.Application.ExecutablePath)
'C:\My Application

Console.WriteLine(System.Windows.Forms.Application.StartupPath)
'C:\My Application\Application.exe
C#
コードを隠すコードを選択
Console.WriteLine(System.Windows.Forms.Application.ExecutablePath);
//C:\My Application

Console.WriteLine(System.Windows.Forms.Application.StartupPath);
//C:\My Application\Application.exe

VB.NETで、My.Application.Info.DirectoryPathプロパティを使う

.NET Framework 2.0以降のVB.NETでは、「My.Application.Info.DirectoryPath」によってアプリケーションのフォルダを取得できます。

補足:My.Application.Info.DirectoryPathは、基本的には「Assembly.GetEntryAssembly().Location」ですが、GetEntryAssemblyがNULLを返す時は、「Assembly.GetCallingAssembly().Location」です。
VB.NET
コードを隠すコードを選択
Console.WriteLine(My.Application.Info.DirectoryPath)
'C:\My Application

AppDomain.CurrentDomain.BaseDirectoryプロパティを使う

現在のアプリケーションドメインのベースディレクトリは、「AppDomain.CurrentDomain.BaseDirectory」で取得できます。これは、「AppDomain.CurrentDomain.SetupInformation.ApplicationBase」と同じです。このフォルダは大抵実行ファイルのフォルダと同じになりますが、そうでない可能性もあります。

VB.NET
コードを隠すコードを選択
Console.WriteLine(System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase)
'C:\My Application\
C#
コードを隠すコードを選択
Console.WriteLine(System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase);
//C:\My Application\
補足:「c# - How do I find the current executable filename? - Stack Overflow」によると、Xenocode Postbuildのような仮想化された環境では、上記のどの方法でも正しく実行ファイルのフルパスを取得できないということです。ただし、実行ファイルのフォルダは「Assembly.GetEntryAssembly().Location」で、ファイル名は「Process.GetCurrentProcess().ProcessName」で正しく取得できるのため、この2つを合わせてフルパスを作成できるそうです。
  • 履歴:
  • 2011/11/22 説明を大幅に書き加えた。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • Windows Vista以降でUACが有効になっていると、ファイルへの書き込みに失敗する可能性があります。詳しくは、こちらをご覧ください。