C#: EXEと異なるフォルダにあるDLLを参照する方法

目次

はじめに

 C#アプリケーションを開発する場合、DLL形式の外部ライブラリやアセンブリを使用することが一般的です。しかし、これらのDLLが実行ファイル(EXE)と同じフォルダーになく、別の場所から参照する必要がある場合があります。
 今回は、C#でEXEと異なるフォルダにあるDLLを参照するいくつかの方法について説明します。

方法

 C#で、EXEと異なるフォルダに配置したDLLを参照する場合、以下のような方法があります。

  1. App.configにdllのパスを指定する
  2. AppDomain.CurrentDomain.AssemblyResolveイベントを使用してdllのパスを指定する
  3. SetDllDirectory関数を使用してdllのパスを指定する
  4. アセンブリのコードベースを使用してDLLを参照する方法

App.configにdllのパスを指定する

 App.configにdllのパスを指定する方法は、App.configに以下のようにdllのパスを記述します。

<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <probing privatePath="C:\MyDlls"/>
    </assemblyBinding>
  </runtime>
</configuration>

 上記の例では、EXEと同じフォルダに配置されている「MyDlls」フォルダにあるdllを参照しています。
 この方法は、アプリケーションを起動する際にdllを探索するため、dllが見つからない場合にはdllがあるフォルダを指定することで解決することができます。

ただし、注意点として、

  • App.configファイルが正しく記述されていること。
  • privatePath属性で指定したフォルダが存在し、dllが存在すること。
  • フォルダは、相対パスで指定する必要がある。
  • .NET Framework のバージョンによっては、この方法が使用できないこと。

これらを考慮して使用することが必要です。

AssemblyResolveイベントを使用する方法

 この方法は、アプリケーションで参照しているdllが見つからない場合に、独自にdllを探索し、参照することができるようにするものです。

 以下に、AssemblyResolveイベントを使用してdllのパスを指定する方法の例を示します。

AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);

static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    string dllName = args.Name.Contains(",") ? args.Name.Substring(0, args.Name.IndexOf(',')) : args.Name.Replace(".dll", "");
    dllName = dllName.Replace(".", "_");

    if (dllName.EndsWith("_resources")) return null;
    string file = @"MyDlls\" + dllName + ".dll";
    return File.Exists(file) ? Assembly.LoadFile(file) : null;
}

 上記の例では、アプリケーションが参照するdllが見つからない場合に、独自にdllを探索するために、AssemblyResolveイベントを使用しています。
 そして、EXEと同じフォルダに配置されている「MyDlls」フォルダにあるdllを参照しています。
 この方法は、dllが見つからない場合にはdllがあるフォルダを指定することで解決することができます。

ただし、注意点として、

  • 指定したフォルダが存在し、dllが存在すること。
  • フォルダは、相対パスで指定する必要がある。

これらを考慮して使用することが必要です。

 この方法は、App.configにdllのパスを指定する方法と比較して、dllが見つからない場合にもアプリケーションがクラッシュするような事故を防ぐことができます。
 ただし、この方法は、dllが見つからない場合に独自にdllを探索するため、dllが正しくない場合にアプリケーションがクラッシュする可能性があるため、dllが正しいことを確認することが重要です。

SetDllDirectory関数を使用する方法

 SetDllDirectory関数を使用してdllのパスを指定する方法は、以下のようにdllのパスを指定します。

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern bool SetDllDirectory(string lpPathName);

....

SetDllDirectory("C:\\MyDlls");

 ただし、SetDllDirectory関数は、アプリケーションのスタートアップ時に1回だけ実行することができるので、DLLを配置するフォルダを変更した場合は、アプリケーションを再起動する必要があります。
 また、SetDllDirectory関数はWindows APIのため、非Windows環境では使用できない点にも注意が必要です。

💡C#などの.NET言語から、Win32 APIや、C++によって作成されたDLLを呼び出すための仕組みを、P/Invoke (Platform Invocation Services) と呼びます。
P/Invokeについては、👇の記事が詳しいです。

アセンブリのコードベースを使用してDLLを参照する方法

 アセンブリのコードベースを使用するには、アセンブリに「file://」プロトコルを使用しなければならないこと、指定したDLLが実際に存在することを確認することが必要です。
 以下は、アセンブリのコードベースを使用してDLLを参照する方法の例です。

[assembly: AssemblyCodeBase("file:///C:/MyDlls/MyLibrary.dll")]

 上記の例では、EXEが配置されているフォルダとは異なるフォルダの「C:/MyDlls/MyLibrary.dll」にあるDLLを参照しています。
 ただし、この方法は、.NET Framework 4.0以降で使用できなくなっているので、新しいプロジェクトでは使用しない方が良いでしょう。

まとめ

 EXEと異なるフォルダにあるDLLを参照する方法は、簡単に実装することができますが、環境によってはうまく動作しないことがあるので、他の方法と比較して適した方法を選ぶことが重要です。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

■管理者について:
 物事のしくみや構造理解に強みを持っているフリーランスのシステムエンジニアです。日々の小さな気づきや仕事のTipsをブログで共有していきます。

■お仕事依頼:
 システム開発は直接請負のみ承ります。
 自社のシステム開発が未経験の企業様向けのサポートも行っています。

■免責事項:
 このブログ上で紹介される情報は私個人の見解に基づくものであり、多くの実験的な試行を含む為、必ずしも正確であるとは限りません。あくまで自己責任において、ご自身の手で確認してください。

目次