"マイ コードのみ" を使用してユーザー コードのみをデバッグする
"マイ コードのみ" は Visual Studio のデバッグ機能であり、システム、フレームワーク、およびその他の非ユーザー コードに呼び出しを自動的にステップ オーバーします。 [呼び出し履歴] ウィンドウでは、"マイ コードのみ" によってこれらの呼び出しが [外部コード] フレームに折りたたまれます。
.NET と C++ のプロジェクトでは、"マイ コードのみ" の動作が異なります。
"マイ コードのみ" の有効/無効の切り替え
ほとんどのプログラミング言語では、"マイ コードのみ" は既定で有効になっています。
- Visual Studio で "マイ コードのみ" を有効または無効にするには、[ツール]>[オプション] (または [デバッグ]>[オプション]) >[デバッグ]>[全般] で [マイ コードのみを有効にする] をオンまたはオフにします。
注意
[マイ コードのみを有効にする] は、すべての言語のすべての Visual Studio プロジェクトに適用されるグローバル設定です。
マイ コードのみデバッグ
デバッグ セッション中、 [モジュール] ウィンドウには、デバッガーがマイ コード (ユーザー コード) として扱っているコード モジュールが、そのシンボルの読み込み状態と共に表示されます。 詳細については、「アプリにデバッガーをアタッチする方法について理解を深める」を参照してください。
[呼び出し履歴] ウィンドウまたは [タスク] ウィンドウでは、"マイ コードのみ" によって非ユーザー コードが [External Code]
というラベルが付いた、淡色表示の注釈付きコード フレームに折りたたまれます。
ヒント
[モジュール] 、 [呼び出し履歴] 、 [タスク] 、またはその他のほとんどのデバッグ ウィンドウを開くには、デバッグ セッション中である必要があります。 デバッグ中に、 [デバッグ]>[ウィンドウ] で、開くウィンドウを選択します。
折りたたまれた [外部コード] フレーム内のコードを表示するには、 [呼び出し履歴] ウィンドウまたは [タスク] ウィンドウ内を右クリックし、コンテキスト メニューから [外部コードの表示] を選択します。 [外部コード] フレームが展開された外部コード行で置き換えられます。
Note
[外部コードの表示] は、ユーザーが開いているすべての言語のすべてのプロジェクトに適用される、現在のユーザー プロファイラー設定です。
[呼び出し履歴] ウィンドウで展開されている外部コード行をダブルクリックすると、ソース コード内の呼び出し元のコード行が緑色で強調表示されます。 DLL またはその他のモジュールが見つからないか、読み込まれていない場合、シンボルまたはソースが見つからないというページが表示されることがあります。
Visual Studio 2022 バージョン 17.7 以降では、[呼び出し履歴] ウィンドウで外部コードをダブルクリックすると、.NET コードを自動逆コンパイルできます。 詳細については、「デバッグ中に .NET アセンブリからソース コードを生成する」を参照してください。
.NET での "マイ コードのみ"
.NET プロジェクトでは、"マイ コードのみ" はシンボル ( .pdb) ファイルとプログラムの最適化を使用して、ユーザー コードと非ユーザー コードを分類します。 .NET デバッガーでは、最適化されたバイナリと読み込まれていない .pdb ファイルが非ユーザー コードと見なされます。
次の 3 つのコンパイラ属性も、.NET デバッガーでユーザー コードと見なされるものに影響を与えます。
- DebuggerNonUserCodeAttribute は、適用先のコードがユーザー コードでないことをデバッガーに通知します。
- DebuggerHiddenAttribute は、"マイ コードのみ" がオフになっていても、コードをデバッガーから見えないようにするための属性です。
- DebuggerStepThroughAttribute は、適用先のコードを (ステップ インではなく) ステップ スルーするよう、デバッガーに伝えます。
.NET デバッガーでは、他のすべてのコードがユーザー コードであると見なされます。
.NET のデバッグ中:
- 非ユーザー コードで [デバッグ]>[ステップ イン] を選択すると (または F11 キーを押すと)、コードがユーザー コードの次の行にステップ オーバーされます。
- 非ユーザー コードで [デバッグ]>[ステップ アウト] を選択すると (または Shift+F11 キーを押すと)、ユーザー コードの次の行まで実行されます。
それ以上のユーザー コードがない場合、デバッグはそれが終わるか、別のブレークポイントにヒットするか、エラーがスローされるまで続行されます。
デバッガーが非ユーザー コードで中断した場合 (たとえば、 [デバッグ]>[すべて中断] を使用して非ユーザー コードで一時停止する場合)、 [No Source](ソースがありません) ウィンドウが表示されます。 次に、 [デバッグ]>[ステップ] コマンドを使用して、ユーザー コードの次の行に進むことができます。
ハンドルされない例外が非ユーザー コードで発生した場合、デバッガーは例外が生成されたユーザー コード行で停止します。
初回例外がその例外に対して有効になっている場合、ユーザー コード行の呼び出しがソース コード内で緑で強調表示されます。 [呼び出し履歴] ウィンドウに、 [外部コード] というラベルの注釈付きフレームが表示されます。
C++ での "マイ コードのみ"
Visual Studio 2017 バージョン 15.8 以降では、コードのステップ実行に対して "マイ コードのみ" もサポートされています。 この機能では、/JMC (マイ コードのみのデバッグ) コンパイラ スイッチを使用する必要もあります。 このスイッチは、C++ プロジェクトでは既定で有効になっています。 [呼び出し履歴] ウィンドウと "マイ コードのみ" での呼び出し履歴のサポートには、/JMC スイッチは必要ありません。
ユーザー コードとして分類されるためには、ユーザー コードを含むバイナリの PDB がデバッガーによって読み込まれる必要があります (これを確認するには、 [モジュール] ウィンドウを使用します)。
[呼び出し履歴] ウィンドウなどの呼び出し履歴の動作については、C++ の "マイ コードのみ" では、これらの関数のみが "非ユーザーコード" と見なされます。
- シンボル ファイル内に除去されたソース情報がある関数。
- シンボル ファイルがスタック フレームに対応するソース ファイルがないことを示す関数。
- %VsInstallDirectory%\Common7\Packages\Debugger\Visualizers フォルダー内の *.natjmc ファイル内で指定された関数。
コードのステップ実行動作については、C++ の "マイ コードのみ" では、これらの関数のみが "非ユーザーコード" と見なされます。
- 対応する PDB ファイルがデバッガーに読み込まれていない関数。
- %VsInstallDirectory%\Common7\Packages\Debugger\Visualizers フォルダー内の *.natjmc ファイル内で指定された関数。
Note
"マイ コードのみ" のコードのステップ実行動作については、Visual Studio 15.8 Preview 3 以降では MSVC コンパイラを使用して C++ コードをコンパイルし、/JMC コンパイラ スイッチを有効にする (既定で有効になっています) 必要があります。 詳細については、「C++ の呼び出し履歴とコードのステップ実行動作をカスタマイズする」とこのブログ記事を参照してください。 以前のコンパイラを使用してコンパイルされたコードの場合、 .natstepfilter ファイルは、"マイ コードのみ" に依存しないコードのステップ実行をカスタマイズする唯一の方法です。 C++ ステップ実行動作のカスタマイズに関するセクションを参照してください。
C++ デバッグ中、非ユーザー コードは既定でスキップされます。 C++ のデバッグ中:
- 非ユーザー コードで [デバッグ]、[ステップ イン] の順に選択すると (または F11 キーを押すと)、ステップ インが非ユーザー コードから呼び出される場合、コードまたは実行がユーザー コードの次の行にステップ オーバーします。
- 非ユーザー コードで [デバッグ]>[ステップ アウト] を選択すると (または Shift+F11 キーを押すと)、ユーザー コードの次の行まで実行されます (現在のスタック フレームの外)。
それ以上のユーザー コードがない場合、デバッグはそれが終わるか、別のブレークポイントにヒットするか、エラーがスローされるまで続行されます。
デバッガーによって非ユーザー コードで実行が中断された場合 (たとえば、 [デバッグ]>[すべて中断] を使用して非ユーザー コードで一時停止した場合)、その非ユーザー コードでステップ実行が続行されます。
デバッガーの実行中に例外が発生すると、デバッガーはユーザー コードまたは非ユーザー コードの実行中であっても、その例外で停止します。 [例外設定] ダイアログ ボックスの [ユーザーにハンドルされていないとき] オプションは無視されます。
C++ の呼び出し履歴とコードのステップ実行動作をカスタマイズする
C++ プロジェクトでは、[呼び出し履歴] ウィンドウで非ユーザー コードとして扱うモジュール、ソース ファイル、関数を、*.natjmc ファイルで指定することができます。 最新のコンパイラを使用している場合は、このカスタマイズもコードのステップ実行に適用されます (「C++ での "マイ コードのみ"」を参照)。
- Visual Studio コンピューターのすべてのユーザーの非ユーザー コードを指定するには、 %VsInstallDirectory%\Common7\Packages\Debugger\Visualizers フォルダーに .natjmc ファイルを追加します。
- 個々のユーザーに非ユーザー コードを指定するには、"%USERPROFILE%\My Documents\<Visual Studio のバージョン>\Visualizers" フォルダーに .natjmc ファイルを追加します。
.natjmc ファイルは、次の構文を持つ XML ファイルです。
<?xml version="1.0" encoding="utf-8"?>
<NonUserCode xmlns="http://schemas.microsoft.com/vstudio/debugger/jmc/2015">
<!-- Modules -->
<Module Name="ModuleSpec" />
<Module Name="ModuleSpec" Company="CompanyName" />
<!-- Files -->
<File Name="FileSpec"/>
<!-- Functions -->
<Function Name="FunctionSpec" />
<Function Name="FunctionSpec" Module ="ModuleSpec" />
<Function Name="FunctionSpec" Module ="ModuleSpec" ExceptionImplementation="true" />
</NonUserCode>
Module 要素の属性
属性 | 説明 |
---|---|
Name |
必須です。 モジュールの完全パス。 Windows のワイルドカード文字、? (0 個または 1 個の文字) および * (0 個以上の文字) を使用できます。 たとえば、オブジェクトに適用された<Module Name="?:\3rdParty\UtilLibs\*" /> では、ドライブの \3rdParty\UtilLibs 内のすべてのモジュールを外部コードとして扱うことをデバッガーに指示します。 |
Company |
任意。 実行可能ファイルに埋め込まれているモジュールを発行する会社の名前。 この属性を使用して、モジュールのあいまいさを解消することができます。 |
File 要素の属性
属性 | 説明 |
---|---|
Name |
必須です。 外部コードとして扱うソース ファイルの完全パス。 パスを指定するときに Windows のワイルドカード文字、? および * を使用できます。 |
Function 要素の属性
属性 | 説明 |
---|---|
Name |
必須です。 外部コードとして扱う関数の完全修飾名。 パスを指定するときに Windows のワイルドカード文字の ? と * を使用できます。 |
Module |
省略可能。 関数を含むモジュールの名前または完全パス。 この属性を使用して、同じ名前の関数のあいまいさを解消することができます。 |
ExceptionImplementation |
true に設定すると、この関数ではなく、例外をスローした関数が呼び出し履歴に表示されます。 |
"マイ コードのみ" の設定とは関係なく、C++ のステップ実行動作をカスタマイズする
C++ プロジェクトでは、*.natstepfilter ファイルで NoStepInto 関数としてリストアップすることでステップオーバーする関数を指定できます。 *.natstepfilter ファイルに記述された関数は、"マイ コードのみ" の設定に依存しません。 NoStepInto 関数では、StepInto 関数やその他のユーザー コードを呼び出した場合でも、関数をステップ オーバーするようにデバッガーに指示します。 .natjmc にリストアップされている関数とは異なり、デバッガーは NoStepInto 関数内のユーザー コードの最初の行にステップ インします。
- Visual Studio のすべてのローカル ユーザーに非ユーザー コードを指定するには、 .natstepfilter ファイルを %VsInstallDirectory%\Common7\Packages\Debugger\Visualizers フォルダーに追加します。
- 個々のユーザーに対して非ユーザー コードを指定するには、"%USERPROFILE%\My Documents\<Visual Studio のバージョン>\Visualizers" フォルダーに .natstepfilter ファイルを追加します。
Note
一部のサード パーティの拡張機能は .natstepfilter 機能を無効にすることがあります。
.natstepfilter ファイルは、次の構文を持つ XML ファイルです。
<?xml version="1.0" encoding="utf-8"?>
<StepFilter xmlns="http://schemas.microsoft.com/vstudio/debugger/natstepfilter/2010">
<Function>
<Name>FunctionSpec</Name>
<Action>StepAction</Action>
</Function>
<Function>
<Name>FunctionSpec</Name>
<Module>ModuleSpec</Module>
<Action>StepAction</Action>
</Function>
</StepFilter>
要素 | 説明 |
---|---|
Function |
必須です。 1 つ以上の関数を非ユーザー関数として指定します。 |
Name |
必須です。 一致を照合する完全な関数名を指定する ECMA-262 書式の正規表現。 次に例を示します。<Name>MyNS::MyClass::.*</Name> は、 MyNS::MyClass のすべてのメソッドが非ユーザー コードと見なされることをデバッガーに知らせます。 一致照合では、大文字と小文字が区別されます。 |
Module |
任意。 関数を含むモジュールへの完全パスを指定する ECMA-262 書式の正規表現。 一致では、大文字と小文字を区別しません。 |
Action |
必須です。 大文字と小文字が区別される以下のいずれかの値です。NoStepInto - 関数をステップ オーバーすることをデバッガーに指示します。StepInto - 関数にステップ インし、一致した関数のその他の NoStepInto をオーバーライドすることをデバッガーに指示します。 |
.natstepfilter ファイルと .natjmc ファイルに関する追加情報
Visual Studio 2022 バージョン 17.6 以降では、.natjmc ファイルと .natstepfilter ファイルをソリューションまたはプロジェクトに直接追加できます。
.natstepfilter ファイルと .natjmc ファイルの構文エラー は、デバッガーの [出力] ウィンドウに報告されません。
.natvis ファイルとは異なり、.natstepfilter ファイルと .natjmc ファイルはホット リロードされません。 代わりに、これらのファイルはデバッグ セッションの開始時近くに再度読み込まれます。
テンプレート関数の場合、名前に
<.*>
または<.*
を使用すると役立つことがあります。
JavaScript での "マイ コードのみ"
JavaScript の "マイ コードのみ" では、以下のいずれかの方法でコードを分類することによって、ステップ実行と呼び出し履歴表示が制御されます。
分類 | 説明 |
---|---|
MyCode | ユーザーが所有および制御するユーザー コード。 |
LibraryCode | ユーザーが通常使用し、アプリが正しく機能するために必要なライブラリからの非ユーザー コード (例: jQuery)。 |
UnrelatedCode | 自分が所有していないアプリ内の、アプリが正しく機能するために依存していない非ユーザー コード。 たとえば、広告を表示する広告 SDK は、UnrelatedCode の可能性があります。 |
JavaScript デバッガーでは、次の順序でコードがユーザー コードまたは非ユーザー コードとして分類されます。
既定の分類。
- ホスト提供の
eval
関数に文字列を渡すことで実行されるスクリプトは、MyCode です。 Function
コンストラクターに文字列を渡すことで実行されるスクリプトは、LibraryCode です。- WinJS や Azure SDK などのフレームワーク参照内のスクリプトは、LibraryCode です。
setTimeout
、setImmediate
、またはsetInterval
関数に文字列を渡すことで実行されるスクリプトは、UnrelatedCode です。
- ホスト提供の
現在のプロジェクトの mycode.json ファイルでの分類。
分類の各手順で、前の手順はオーバーライドされます。
他のコードはすべて、MyCode として分類されます。
既定の分類を変更し、特定のファイルと URL をユーザー コードまたは非ユーザー コードとして分類することができます。そのためには、mycode. json という名前の .json ファイルを JavaScript プロジェクトのルート フォルダーに追加します。 「JavaScript のマイ コードのみをカスタマイズする」を参照してください。
- 関数が非ユーザー コードの場合、 [デバッグ]>[ステップ イン] (または F11) は、 [デバッグ]>[ステップ オーバー] (または F10) と同様に動作します。
- ステップが非ユーザー (LibraryCode または UnrelatedCode) コードで始まる場合、ステップ実行は一時的に "マイ コードのみ" が有効でないように動作します。 ユーザー コードに戻ると、"マイ コードのみ" のステップ実行が再び有効になります。
- ユーザー コードのステップ実行によって現在の実行コンテキストがそのままになると、デバッガーは次に実行されるユーザー コード行で停止します。 たとえば、コールバックが LibraryCode コードで実行されると、デバッガーはユーザー コードの次の行が実行されるまで続行されます。
- [ステップ アウト] を選択すると (または Shift+F11 キーを押すと)、ユーザー コードの次の行で停止します。
それ以上のユーザー コードがない場合、デバッグはそれが終わるか、別のブレークポイントにヒットするか、エラーがスローされるまで続行されます。
コードに設定されたブレークポイントは常にヒットしますが、コードは分類されます。
debugger
キーワードが LibraryCode で発生した場合、デバッガーは常に中断されます。debugger
キーワードが UnrelatedCode で発生した場合、デバッガーは停止しません。
MyCode または LibraryCode コードでハンドルされない例外が発生した場合、デバッガーは常に中断されます。
UnrelatedCode でハンドルされない例外が発生し、呼び出し履歴に MyCode または LibraryCode コードがある場合、デバッガーは中断されます。
初回例外がその例外に対して有効になっていて、例外が LibraryCode または UnrelatedCode で発生する場合:
- 例外が処理される場合、デバッガーは中断されません。
- 例外が処理されない場合、デバッガーは中断します。
JavaScript の "マイ コードのみ" をカスタマイズする
単一の JavaScript プロジェクトのユーザー コードと非ユーザー コードを分類するには、プロジェクトのルート フォルダーに mycode.json という名前の .json ファイルを追加します。
mycode.json ファイルに、すべてのキーと値のペアが記述されている必要はありません。 MyCode、Libraries、および Unrelated の値は空の配列にすることができます。
Mycode.json ファイルでは、次の構文が使用されます。
{
"Eval" : "Classification",
"Function" : "Classification",
"ScriptBlock" : "Classification",
"MyCode" : [
"UrlOrFileSpec",
. . .
"UrlOrFileSpec"
],
"Libraries" : [
"UrlOrFileSpec",
. .
"UrlOrFileSpec"
],
"Unrelated" : [
"UrlOrFileSpec",
. . .
"UrlOrFileSpec"
]
}
Eval、Function、および ScriptBlock
Eval、Function、および ScriptBlock のキーと値のペアで、動的に生成されたコードを分類する方法が決まります。
名前 | 説明 |
---|---|
Eval | ホスト提供の eval 関数に文字列を渡すことで実行されるスクリプト。 既定では、Eval スクリプトは MyCode として分類されます。 |
Function | Function コンストラクターに文字列を渡すことで実行されるスクリプト。 既定では、Function スクリプトは LibraryCode として分類されます。 |
ScriptBlock | setTimeout 、setImmediate 、または setInterval 関数に文字列を渡すことで実行されるスクリプト。 既定では、ScriptBlock スクリプトは UnrelatedCode として分類されます。 |
以下のいずれかのキーワードに値を変更できます。
MyCode
では、スクリプトが MyCode として分類されます。Library
では、スクリプトが LibraryCode として分類されます。Unrelated
では、スクリプトが UnrelatedCode として分類されます。
MyCode、Libraries、および Unrelated
MyCode、Libraries、および Unrelated のキーと値のペアでは、分類に含める URL またはファイルを指定します。
名前 | 説明 |
---|---|
MyCode | MyCode として分類される URL またはファイルの配列。 |
Libraries | LibraryCode として分類される URL またはファイルの配列。 |
Unrelated | UnrelatedCode として分類される URL またはファイルの配列。 |
URL またはファイルの文字列には、0 個以上の文字に一致する *
文字を 1 つ以上含めることができます。 *
は、正規表現 .*
と同じです。