Visual Studio & .NET - ソースコードを持っていないアセンブリ内にブレークポイントを設置してデバッグしたい
背景
Windows 上で Visual Studio を使っての .NET プログラム開発における話。
何かのトラブルシュート、デバッグの目的で、Visual Studio を使ってのデバッグ実行時に、ソースコードは手元に無い、.NET アセンブリ (.dll ファイル) のみで提供されている・参照しているプログラムコード内にもステップ実行したい場合が、極めて希ではありますが、あったりします。
幸い (?)、.NET のアセンブリは、ある一定の精度で逆コンパイル、つまり、C# 等のソースコードに再現可能です。実際、昔からそのためのツールがいくつか流通しています (自分が好んで使っているのは ILSPy という OSS のツールです)。そしていつの頃からかはよく覚えていないのですが、Visual Studio 上でも、.NET アセンブリを逆コンパイルして、デバッグ実行できるようになっています。とくに、手元のソースコード上でいったんブレークし、そこからステップインしていくだけであれば簡単です。具体的なやり方は以下のとおりです。
ソースコードのないアセンブリ内にステップイン実行するには
まずは Visual Studio を起動して、オプション設定ダイアログ (メニューの [ツール(T)]-[オプション(O)...]) を開き、[デバッグ]-[全般] のカテゴリを開いて、[マイコードのみを有効にする] のチェックボックスを Off に変更し、
[OK] をクリックしてオプション設定ダイアログを閉じます。
以上、たったこれだけです!
この状態で対象のプロジェクトを開いて F5 キーを押すなどしてデバッグ実行を開始し、ひとまずは自分のコード上にブレークポイントを設置しておいてブレーク後に、F11 キーを押すなどしてステップイン実行すると...
ステップイン先のコードはアセンブリでしか提供されていないにもかかわらず、Visual Studio がステップイン先のアセンブリをその場で C# ソースコードに逆コンパイルして、ステップ実行を可能にします。
実に簡単ですね!
ステップイン実行していくには難しいアセンブリ内にブレークポイントを設置するには
しかし他にも、いくつかの依存関係の先にあるアセンブリ内のコードであったり、フレームワークからのコールバックで呼び出されるようなアセンブリ内のコードに、予めブレークポイントを設定しておいて停止させたい場合もあります。このような場合は、ステップインで目的のアセンブリの逆コンパイルに到達するのは極めて困難であったりします。この場合は次のようにします。
まずはこれまでどおり Visual Studio でデバッグ実行を開始します。デバッグ実行が開始されたら、Visual Studio のソリューションエクスプローラーを開き、[外部ソース] のツリーを開きます。[外部ソース] のツリー直下に、目的のアセンブリのノードがあればそのノードをさらに開きますが、まだ見つからない場合は、[ソースのないモジュール] のツリーを開きます。そこで逆コンパイルしてブレークポイントを設置したい目的のアセンブリを探し出し、マウスで右クリックしてコンテキストメニューを開いて、[ソースをシンボル ファイルに逆コンパイルする(E)] をクリックします。
するとそのアセンブリが [外部ソース] ツリー直下に移動し、そのアセンブリのノードを開くと、逆コンパイルで生成可能なソースコード一覧が表示されます。ここから目的のソースコードをダブルクリックすると、Visual Studio がその場で逆コンパイルを実行し、エディタ内に開かれます。あとはお好みの行にブレークポイントを設置、停止させることが可能となります。
簡単ですね!
逆コンパイルされたソースコードの在りか
逆コンパイルされたソースコードは、C:\Users\<user name>\AppData\Local\Temp\.vsdbgsrc
フォルダ内に保存されます。
および、デバッグ実行のためのシンボルファイル (.pdb) は、既定では、C:\Users\<user name>\AppData\Local\Temp\SymbolCache
フォルダ内に保存されます。このようなシンボルファイルのキャッシュ先は、Visual Studio のオプション設定ダイアログ中、[デバッグ]-[シンボル] のカテゴリの設定で変更することができるほか、この設定画面から、シンボルファイルのキャッシュを空にすることも可能です。
VB で作成されたアセンブリは VB のソースコードに逆コンパイルされる?
自分が試した限りにおいては、VB (Visual Basic) で作成されたアセンブリであっても、Visual Studio 上で上記手順で逆コンパイルされた場合は、C# のソースコードに逆コンパイルされました。Visual Studio で開いているプロジェクトが VB プロジェクト (.vbproj) であっても結果は変わらず。F# は試していませんが、おそらくは同じように C# のソースコードとして逆コンパイルされるのではないかと想像しています。逆コンパイル先のソースコードを、VB 等の C# 以外の言語に設定変更できるのかどうかは不明です。自分が愛用している逆コンパイルツール、ILSpy でも、最近のバージョンでは C# にしか逆コンパイルできないようなので (間違ってたらすみません)、他の言語への逆コンパイルはできないのかもしれません。
まとめ
今回紹介したように、Visual Studio 上では、ソースコードが提供されていない、アセンブリ (.dll) のみのプログラムコードであっても、Visual Studio それ自身の機能によってアセンブリを逆コンパイルし、ステップイン実行したりブレークポイントを設置したりすることが容易に可能です。
また今回は紹介していませんが、"Source Link" という仕組みによって、GitHub などから必要に応じてソースコードを入手してデバッグ可能にする機能もあります。逆コンパイルする以外にも方法があるということで補足しておきます。
なお、対象のアセンブリを逆コンパイルしてよいのかどうかは、そのアセンブリの配布時における使用許諾に依ります。Visual Studio や ILSpy などの各種ツールによって、ソースコード提供のないアセンブリを C# ソースコードに逆コンパイルは可能だとしても、そのようなリバースエンジニアリングが禁じられている場合もあります。 この点はくれぐれもご注意ください。
Discussion