2.

C# / .NET で DLL を参照する完全ガイド(プロジェクト参照 / NuGet /

編集
この記事の要点
  • C#/.NET の DLL 参照は 4 種類: ① プロジェクト参照(同 .sln 内)/ ② アセンブリ参照(DLL ファイルを直接)/ ③ NuGet パッケージ / ④ 動的ロード
  • Visual Studio: ソリューションエクスプローラ → 参照 → 右クリック → 参照の追加。.csproj には または が追加
  • 実行時に動的ロードしたいなら Assembly.LoadFrom("path.dll")GetType()Activator.CreateInstance()
  • Win32 API など ネイティブ DLL を呼ぶには PInvoke: [DllImport("user32.dll")] static extern int MessageBox(...)
  • x86 / x64 ビット数が一致しないと BadImageFormatException。プロジェクトのターゲットプラットフォームと DLL のビット数を揃える

DLL 参照の 4 つの方法

方法用途追加先解決タイミング
プロジェクト参照同じ .sln 内の別プロジェクトビルド時
アセンブリ参照ローカル DLL ファイルビルド時
NuGet パッケージ公開ライブラリ復元時
動的ロードプラグイン機構不要実行時
PInvoke (ネイティブ)Win32 API 等属性で指定初回呼出時

方法1: Visual Studio で参照追加

  1. ソリューションエクスプローラで対象プロジェクトを開く
  2. 依存関係 / 参照 を右クリック → 参照の追加 (Add Reference)
  3. 左ペインで アセンブリ / プロジェクト / 参照 (Browse) を選択
  4. DLL を選んで OK

結果として .csproj には次のような行が追加されます:



  
    net8.0
    x64
  

  
  
    
      ..\libs\MyLibrary.dll
      true  
    
  

  
  
    
  

  
  
    
  

方法2: NuGet で参照(推奨)

# パッケージマネージャコンソール
Install-Package Newtonsoft.Json -Version 13.0.3

# .NET CLI
dotnet add package Newtonsoft.Json --version 13.0.3

# 復元
dotnet restore

# 一覧確認
dotnet list package

方法3: Assembly.LoadFrom で動的ロード

プラグイン機構や、ビルド時に存在しない DLL を実行時に読み込むとき:

using System;
using System.Reflection;

class Program {
    static void Main() {
        // DLL を実行時に読み込む
        Assembly asm = Assembly.LoadFrom(@"C:\plugins\MyPlugin.dll");

        // クラスを取得
        Type t = asm.GetType("MyPlugin.Greeter");
        if (t == null) {
            Console.WriteLine("型が見つかりません");
            return;
        }

        // インスタンス生成
        object instance = Activator.CreateInstance(t);

        // メソッド呼出
        MethodInfo method = t.GetMethod("SayHello");
        string result = (string)method.Invoke(instance, new object[] { "World" });
        Console.WriteLine(result);

        // 全ての public 型を列挙
        foreach (Type type in asm.GetExportedTypes()) {
            Console.WriteLine(type.FullName);
        }
    }
}

LoadFrom は依存 DLL も同じディレクトリから自動解決します。完全に分離したいなら AssemblyLoadContext(.NET Core+)を使います。

方法4: PInvoke でネイティブ DLL を呼ぶ

Win32 API や C++ 製の DLL を呼ぶ場合は [DllImport] 属性:

using System;
using System.Runtime.InteropServices;

class Program {
    // user32.dll の MessageBox を宣言
    [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    static extern int MessageBox(IntPtr hWnd, string text, string caption, uint type);

    // kernel32.dll の GetTickCount
    [DllImport("kernel32.dll")]
    static extern uint GetTickCount();

    // 自作 C++ DLL の関数
    [DllImport("MyNative.dll", CallingConvention = CallingConvention.Cdecl)]
    static extern int Add(int a, int b);

    static void Main() {
        MessageBox(IntPtr.Zero, "Hello", "Title", 0);
        Console.WriteLine($"起動からの経過: {GetTickCount()} ms");
        Console.WriteLine($"Add(3, 4) = {Add(3, 4)}");
    }
}

よくあるエラーと対処

エラー原因対処
FileNotFoundExceptionDLL がランタイムから見えない出力ディレクトリ / GAC / プロセスの PATH を確認
BadImageFormatExceptionx86/x64 ビット数不一致PlatformTarget を DLL に揃える
FileLoadException (Strong name)署名違い・バージョン違いapp.config の bindingRedirect で吸収
EntryPointNotFoundExceptionPInvoke で関数名が違うEntryPointCharSet を確認、dumpbin /exports で実関数名確認
DllNotFoundExceptionネイティブ DLL が見つからない実行ディレクトリ / System32 / PATH に配置

GAC(グローバルアセンブリキャッシュ)

.NET Framework のみ。複数アプリで共有する DLL を登録します:

# 開発者コマンドプロンプトで
gacutil /i MyLibrary.dll
gacutil /l MyLibrary
gacutil /u MyLibrary

# 物理パス
# C:\Windows\Microsoft.NET\assembly\GAC_MSIL\

.NET Core / .NET 5+ は GAC を廃止。アプリ単位の自己完結配置が推奨です。

FAQ

Q: DLL を入れ替えたが古いまま
A: ビルド出力ディレクトリ (bin/Debug/...) に古い DLL がコピーされている可能性。dotnet clean → 再ビルド。

Q: NuGet と直接参照のどちらを使うべき
A: 公開済みなら NuGet 一択。バージョン管理・依存解決・チーム共有が楽。社内 DLL は社内 NuGet サーバ(Azure Artifacts / Nexus / ProGet)に登録。

Q: AnyCPU プロジェクトで PInvoke すると落ちる
A: 実行時のプロセスビット数(OS が 64bit なら 64bit)と DLL のビット数が違うため。PlatformTarget を明示してください。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. ショートカットキー
  2. dllを参照する方法
  3. エラー一覧
  4. 本番環境のdll内で参照しているdllファイルの置き場所
  5. フォームのタブ切り替え順序を変更する方法
  6. .suoファイルとは