| この記事の要点 |
|
結論: exe と同じフォルダに置く
開発環境では動くのに、本番環境に配置すると「DLL が見つからない」エラーになる、というのはよくあるトラブルです。自作 DLL(A.dll)がさらに別の DLL(B.dll)を参照している場合、B.dll はアプリケーションの実行ファイル(.exe)と同じディレクトリに置くのが最も確実で、推奨される方法です。
C:\MyApp\
MyApp.exe ← 起動する実行ファイル
A.dll ← MyApp.exe が参照する DLL
B.dll ← A.dll が参照する DLL(ここに置く)
MyApp.exe.config
Visual Studio でビルドすると、参照設定で「ローカルにコピー(Copy Local)」が有効な DLL は自動で出力フォルダ(bin\Release など)にコピーされます。本番には出力フォルダの中身を丸ごと配置するのが基本です。
最大の落とし穴: 参照元 DLL のフォルダは探されない
「A.dll が使うのだから、A.dll と同じフォルダに B.dll を置けばよい」と考えがちですが、Windows も .NET も、依存 DLL の検索の基準は参照元の DLL の場所ではなく、プロセス(exe)の場所です。
例えば A.dll と B.dll を C:\Shared\Lib に置き、C:\MyApp\MyApp.exe から A.dll を読み込んだ場合、B.dll は C:\MyApp などから探され、C:\Shared\Lib は探されません。プラグイン形式で DLL を別フォルダから読み込む設計のときに特に起こりやすい問題です。
ネイティブ DLL(C/C++ など)の検索順序
C/C++ で作られたネイティブ DLL や、C# から P/Invoke(DllImport)で呼び出す DLL は、Windows のローダーが次の順で検索します(既定の安全な DLL 検索モードが有効な場合)。
- アプリケーションの実行ファイルがあるディレクトリ
- システムディレクトリ(
C:\Windows\System32) - 16 ビットのシステムディレクトリ(
C:\Windows\System) - Windows ディレクトリ(
C:\Windows) - カレントディレクトリ
- 環境変数 PATH に含まれるディレクトリ
この前に、すでにメモリに読み込まれている DLL や、Windows が管理する既知の DLL(KnownDLLs)が優先されます。
各配置場所の比較
| 置き場所 | 評価 | 理由 |
|---|---|---|
| exe と同じフォルダ | 推奨 | 最初に検索される。アプリごとに独立し、他のアプリへ影響しない |
| System32 / SysWOW64 | 非推奨 | 管理者権限が必要。システム全体に影響し、同名 DLL の上書き事故(DLL 地獄)の原因になる |
| PATH に含まれるフォルダ | 条件付き | 複数アプリで共有できるが、PATH の順番や他ソフトの同名 DLL で読み込まれる DLL が変わりうる |
| アプリ固有のフォルダ | 設計次第 | アプリ側が SetDllDirectory や AddDllDirectory で検索先を追加している場合のみ有効 |
64 ビット版 Windows では、System32 が 64 ビット用、SysWOW64 が 32 ビット用です。名前と中身が直感と逆なので注意してください。
.NET アセンブリ(C# の DLL)の場合
C# などで作ったマネージド DLL(アセンブリ)は、ネイティブ DLL とは別の仕組みで探されます。
- .NET Framework: アプリケーションベース(exe のフォルダ)を探し、厳密名付きのものはグローバルアセンブリキャッシュ(GAC)も参照します
- .NET(.NET Core / .NET 5 以降): ビルド時に生成される
アプリ名.deps.jsonに依存関係が記録され、通常は exe と同じフォルダから読み込まれます。dotnet publishの出力フォルダを丸ごと配置すれば必要な DLL がそろいます
サブフォルダに DLL をまとめたい場合(.NET Framework)
exe のフォルダを整理するため lib フォルダに DLL を入れたい場合は、app.config(実行時は MyApp.exe.config)で検索先を追加します。指定できるのはアプリケーションベース配下のサブフォルダだけです。
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="lib;plugins" />
</assemblyBinding>
</runtime>
</configuration>
よくあるエラーと原因
| エラー | 主な原因 |
|---|---|
| FileNotFoundException: ファイルまたはアセンブリ '…'、またはその依存関係の 1 つが読み込めませんでした | .NET の DLL か、その DLL が依存する DLL が exe のフォルダにない |
| DllNotFoundException | P/Invoke で呼ぶネイティブ DLL、またはその依存 DLL が見つからない |
| BadImageFormatException | 32 ビットと 64 ビットの不一致(x86 用 DLL を 64 ビットプロセスで読む等) |
| VCRUNTIME140.dll が見つからない | 本番機に Visual C++ 再頒布可能パッケージが入っていない |
「その依存関係の 1 つ」という文言のとおり、エラーに表示された DLL 自体ではなく、その先の依存 DLL が見つからないケースが多くあります。
どこを探したか確認する方法
- 依存関係を一覧する: Visual Studio の開発者コマンドプロンプトで
dumpbin /dependents A.dllを実行すると、A.dll が必要とするネイティブ DLL の一覧が出ます - 読み込みの試行を記録する: Sysinternals の Process Monitor で対象プロセスを絞り込み、「NAME NOT FOUND」になっている DLL のパスを確認します
- .NET Framework のバインド失敗: アセンブリ バインド ログ ビューアー(fuslogvw.exe)で、どのフォルダを探して失敗したかが分かります
- 本番機と開発機で、exe のフォルダの中身(DLL の数・バージョン・ビット数)を比較します
関連
- DLL ファイル(.dll)とは | Windows 動的リンクライブラリの仕組み・LoadLibrary・DLL Hijacking 対策
- C#・Visual Studioのよくあるエラーと対処まとめ
- C# 入門 — .NET エコシステムと現代の C# 言語
- EXE / DLL / MSI / DMG / DEB / RPM / APK など実行・パッケージ形式総覧
子ページはありません
- ショートカットキー
- dllを参照する方法
- エラー一覧
- 本番環境のdll内で参照しているdllファイルの置き場所
- フォームのタブ切り替え順序を変更する方法
- .suoファイルとは
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript で base URL を取得する方法|window.location.origin
- 4 YouTube Data API v3 エラー一覧|403・400・404 の原因と対処
- 5 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 6 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 7 Spring Frameworkのアノテーション一覧
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- Git pushした変更の取消し|revert・履歴変更と保護の注意点 2026-10-15 23:49:01
- Gitでローカルを戻す前に|reset・restoreの違いと退避範囲 2026-10-15 23:49:01
- Git rebaseの使い方|対象範囲・競合解決・pushの判断 2026-10-15 22:50:59
- Git pullの使い方|取込み先・ff-only・競合とstashの注意点 2026-10-15 22:50:59
- Git pushの使い方|送信先・タグ・force-with-leaseの条件 2026-10-15 22:12:47
- Git remoteの設定・確認・削除|SSH URLとfetch/pushの違い 2026-10-15 22:12:47
- Gitリモートリポジトリの作成|初回push・既存履歴・mirrorの注意 2026-10-15 15:48:16
- Gitのuser.name・user.email設定|local/global・確認と過去履歴の注意 2026-10-15 15:30:07
- LinuxにGitをインストール|配布元・初期設定・TLSと認証の確認 2026-10-15 15:30:06
- Git導入と初回push|Linuxサーバー・Windows/macOS・SSH設定 2026-10-15 14:51:54
- Db2のCREATE INDEX|索引定義・INCLUDEと実行計画の確認 2026-10-15 14:10:22
- Db2の自動採番|IDENTITY・ID取得とRESTARTの注意点 2026-10-15 14:10:22
- 【DB2】特定スキーマの全テーブルの全カラム情報を取得する方法 2026-10-15 13:53:15
- Db2のシーケンスとIDENTITYの違い|採番とカタログの確認SQL 2026-10-15 13:53:15
- Db2で複数カラムをUPDATEする方法|SET・WHEREと更新前の値 2026-10-15 13:53:15