現在実行しているDLLのパスを取得する。(GetExecutingAssembly )

.Net Frameworkでは、アプリケーションの配置はXCopyによる配置が主流であるためExeとDLLの場所が異なる場合は、あまり多くありません。殆どの場合、Exeの場所を求めれば課題を解決することができるため、DLLのパスを取得する必要性は以前ほどなくなってきています。


アンマネージドDLLの一種であるActiveX DLLはシステム全体で1箇所のみの配置で、「DLLの位置を基準に、サブフォルダの設定ファイルを読み込む」などといった用途でDLLのパスを取得する事が多くありました。そんな時、アンマネージドDLLではDLLのパスを取得する際に GetModuleFileName を使ってパスを取得していました。


使用用途は以前より限られてくるものの .Net Framework の DLLでのパスの取得方法について整理してみました。


まず、DLLのパスの取得に利用できそうなメソッドがAssemblyクラスの次の3メソッドです。



Assembly.GetEntryAssembly メソッド
既定のアプリケーション ドメインで実行できるプロセスを取得します。
他のアプリケーション ドメインでは、AppDomain.ExecuteAssembly で実行された最初の実行可能ファイルです。



Assembly.GetCallingAssembly メソッド
現在実行中のメソッドを呼び出したメソッドの Assembly を返します。



Assembly.GetExecutingAssembly メソッド
現在実行中のコードを格納しているアセンブリを取得します。


MSDNの説明文を読む限り、GetEntryAssembly(Exeのパス)、GetCallingAssembly(呼び出し元のパス)、GetExecutingAssembly(DLLのパス)のように読み取れます。実際にサンプルコードを作成して、どのような値が取得できるのか、また落とし穴はないか検証してみたいと思います。


検証方法としてはExeとDLLをそれぞれ作成し、DLL側で上記3メソッドを呼び出す処理を実装。Exeから呼び出して結果を確認するという事をしてみたいと思います。



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AssembleyPathTest
{
class Program
{
static void Main(string[] args)
{

Console.WriteLine(String.Format("GetEntryAssembly:{0}", AssembleyPath.AssembleyPathResolve.GetEntryAssembly().ToString()));
Console.WriteLine(String.Format("GetCallingAssembly:{0}", AssembleyPath.AssembleyPathResolve.GetCallingAssembly().ToString()));
Console.WriteLine(String.Format("GetExecutingAssembly:{0}", AssembleyPath.AssembleyPathResolve.GetExecutingAssembly().ToString()));

Console.ReadLine();

}
}
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AssembleyPath
{
public class AssembleyPathResolve
{

public static string GetEntryAssembly()
{
return System.Reflection.Assembly.GetEntryAssembly().Location;
}

public static string GetCallingAssembly()
{
return System.Reflection.Assembly.GetCallingAssembly().Location;
}

public static string GetExecutingAssembly()
{
return System.Reflection.Assembly.GetExecutingAssembly().Location;
}

}
}


検証結果は、以下となりました。パスを取得するには予想通りGetExecutingAssemblyが適切なようです。



GetEntryAssembly:C:\AssembleyPathTest.exe
GetCallingAssembly:C:\AssembleyPathTest.exe
GetExecutingAssembly:C:\AssembleyPath.dll


GetEntryAssemblyとGetCallingAssemblyが同じになっていますが上記のExeとDLLの間にもうひとつアセンブリを挟むとGetCallingAssemblyは挟んだDLL名を返すようになります。(検証済み)