デバッグ中に .NET アセンブリからソース コードを生成する

.NET アプリケーションをデバッグするときに、自分が持っていないソース コードを見たくなる場合があります。 たとえば、例外で中断したときや、呼び出し履歴を使用してソースの場所に移動するときなどです。

注意

  • ソース コードの生成 (逆コンパイル) は、.NET アプリケーションでのみ使用でき、オープンソースの ILSpy プロジェクトに基づいています。
  • 逆コンパイルは、Visual Studio 2019 16.5 以降でのみ使用できます。
  • アセンブリまたはモジュールに SuppressIldasmAttribute 属性を適用すると、Visual Studio で逆コンパイルが試みられなくなります。 これは .NET 6 以降では古い属性になっていますが、Visual Studio ではこの属性を認識します。

ソース コードを生成する

デバッグを行っていて、ソース コードが使用できない場合、Visual Studio では、"ソースが見つからない" というドキュメントが表示されるか、またはアセンブリのシンボルがない場合は "シンボルが読み込まれていない" というドキュメントが表示されます。 どちらのドキュメントにも、現在の場所に対する C# のコードを生成する [Decompile source code](ソース コードを逆コンパイルする) オプションがあります。 生成された C# のコードは、他のソース コードと同様に使用できます。 コードの表示、変数の検査、ブレークポイントの設定などを行うことができます。

シンボルが読み込まれていない

次の図は、シンボルが読み込まれていないというメッセージです。

Screenshot of no symbol loaded document

ソースが見つからない

次の図は、ソースが見つからないというメッセージです。

Screenshot of source not found document

自動逆コンパイル コード

Visual Studio 2022 バージョン 17.7 以降、Visual Studio デバッガーでは、外部 .NET コードの自動逆コンパイルがサポートされています。 外部コードにステップ インする場合や [呼び出し履歴] ウィンドウを使用する場合に、自動コンパイルを利用できます。

外部で実装されたコードにステップ インすると、デバッガーによってコードは自動的に逆コンパイルされ、現在の実行ポイントが表示されます。 外部コードにステップ インする場合は、マイ コードのみを無効にする必要があります。

"マイ コードのみ" を無効にしなくても、[呼び出し履歴] ウィンドウから簡単に逆コンパイルできます。

[呼び出し履歴] ウィンドウから自動逆コンパイルするには:

  1. [呼び出し履歴] ウィンドウを開いた状態でデバッグ中に、[外部コードの表示] を選択します。

  2. [呼び出し履歴] ウィンドウで、任意のスタック フレームをダブルクリックします。 デバッガーはコードを逆コンパイルした後、現在の実行ポイントに直接移動して表示します。

    Screenshot of Call Stack window showing external code.

    逆コンパイルされたすべてのコードは、ソリューション エクスプローラーの [外部ソース] ノードにも表示されるため、必要に応じて外部ファイルを簡単に参照できます。

    Screenshot of External Sources node showing decompiled assemblies.

    逆コンパイルされたコードをデバッグし、ブレークポイントを設定できます。

外部コードの自動逆コンパイルを無効にするには、[ツール] > [オプション] > [デバッグ] > [全般] の順に移動し、[必要に応じてソースに自動的に逆コンパイルする (マネージドのみ)] を選択解除します。

アセンブリのソースを生成して埋め込む

特定の場所に対するソース コードを生成するだけでなく、特定の .NET アセンブリに対するすべてのソース コードを生成することもできます。 このタスクを行うには、[モジュール] ウィンドウに移動し、.NET アセンブリのコンテキスト メニューから、[ソースをシンボル ファイルに逆コンパイルする] コマンドを選択します。 Visual Studio によってアセンブリのシンボル ファイルが生成され、ソースがシンボル ファイルに埋め込まれます。 後のステップで、埋め込まれたソース コードを抽出することができます。

Screenshot of assembly context menu in modules window with decompile source command.

埋め込まれたソース コードを抽出して表示する

[モジュール] ウィンドウのコンテキスト メニューにある [Extract Source Code](ソース コードの抽出) コマンドを使用して、シンボル ファイルに埋め込まれたソース ファイルを抽出できます。

Screenshot of assembly context menu in modules window with extract sources command.

抽出されたソース ファイルは、その他のファイルとしてソリューションに追加されます。 Visual Studio のその他のファイル機能は、既定ではオフになっています。 この機能を有効にするには、 [ツール]>[オプション]>[環境]>[ドキュメント]>[その他のファイルをソリューション エクスプローラーに表示する] チェック ボックスをオンにします。 この機能が有効になっていない場合、抽出されたソース コードを開くことができません。

Screenshot of tools option page with miscellaneous files option enabled.

抽出されたソース ファイルは、ソリューション エクスプローラーの [その他のファイル] に表示されます。

Screenshot of solution explorer with miscellaneous files.

.NET ライブラリ、または SourceLink に対して有効になっている NuGet パッケージの場合は、ソース コードにステップ インし、ブレークポイントを設定し、デバッガーのすべての機能を使用することもできます。 詳細については、Source Link を使用してデバッグと診断を有効にする と、SourceLink を使用したデバッグ時の生産性の向上 を参照してください。

既知の制限事項

中断モードが必要である

逆コンパイルを使用してソース コードを生成できるのは、デバッガーが中断モードになっていて、アプリケーションが一時停止されている場合だけです。 Visual Studio が中断モードになるのは、たとえば、ブレークポイントにヒットしたときや、例外が発生したときです。 [すべて中断] コマンド (Break all icon) を使用することで、次のコード実行時に Visual Studio で中断を簡単にトリガーできます。

逆コンパイルに関する制限事項

.NET アセンブリで使用される中間形式 (IL) からソース コードを生成するときは、固有の制限がいくつかあります。 そのため、生成されたソース コードは元のソース コードのようには見えません。 異なっているのは、ほとんどが、元のソース コードの情報が実行時に必要のない箇所です。 たとえば、空白文字、コメント、ローカル変数の名前などの情報は、実行時には必要ありません。 生成されたソースは、元のソース コードの代わりとしてではなく、プログラムの実行方法を理解するために使用することをお勧めします。

最適化されたアセンブリまたはリリース アセンブリをデバッグする

コンパイラの最適化を使用してコンパイルされたアセンブリから逆コンパイルされたコードをデバッグする場合、次の問題が発生する可能性があります。

  • ブレークポイントは、一致するソースの場所に常にバインドされるとは限りません。
  • ステップ実行では、正しい場所に常にステップするとは限りません。
  • ローカル変数の名前が正確ではない可能性があります。
  • 一部の変数は、評価に使用できない場合があります。

詳細については、GitHub の次のイシューを参照してください: 「ICSharpCode.Decompiler の VS デバッガーへの統合」。

逆コンパイルの信頼性

比較的低い割合ではありますが、逆コンパイルの試みが失敗する可能性があります。 この動作は、ILSpy でのシーケンス ポイントの null 参照エラーが原因です。 これらの問題をキャッチし、逆コンパイルの試行を適切に失敗させることによって、この障害は軽減されています。

詳細については、GitHub の次のイシューを参照してください: 「ICSharpCode.Decompiler の VS デバッガーへの統合」。

非同期コードに関する制限事項

非同期/待機コード パターンが使用されているモジュールの逆コンパイルの結果は、不完全または完全な失敗となる可能性があります。 非同期/待機および一時停止ステート マシンの ILSpy による実装は、部分的にのみ実装されています。

詳細については、GitHub の次のイシューを参照してください: 「PDB ジェネレーターの状態」。

マイ コードのみ

マイ コードのみ (JMC) の設定を使用すると、システム、フレームワーク、ライブラリ、その他の非ユーザーの呼び出しを、Visual Studio にステップオーバーさせることができます。 デバッグ セッション中、 [モジュール] ウィンドウには、デバッガーでマイ コード (ユーザー コード) として扱われているコード モジュールが表示されます。

最適化された、またはリリースのモジュールを逆コンパイルすると、非ユーザー コードが生成されます。 たとえば、逆コンパイルされた非ユーザー コードでデバッガーが中断した場合、ソースなしウィンドウが表示されます。 "マイ コードのみ" を無効にするには、[ツール]>[オプション] (または [デバッグ]>[オプション]) >[デバッグ]>[全般] に移動し、[マイ コードのみを有効にする] をオフにします。

抽出されたソース

アセンブリから抽出されたソース コードには、次の制限があります。

  • 生成されるファイルの名前と場所は構成できません。
  • ファイルは一時的なものであり、Visual Studio によって削除されます。
  • ファイルは単一のフォルダーに配置され、元のソースで使用されていたフォルダー階層は使用されません。
  • 各ファイルのファイル名には、ファイルのチェックサム ハッシュが含まれます。

C# のコードのみが生成される

逆コンパイルでは、C# のソース コード ファイルのみが生成されます。 他の言語でファイルを生成するオプションはありません。