14

Visual Studio が例外を処理する方法を制御できることはわかっています。例外の種類と、それらが最終的に [例外] ダイアログを使用してキャッチされるという事実に基づいています。

ArgumentOutOfRangeただし、特定のメソッドを呼び出しているときに内部的に例外をスロー (およびキャッチ) するライブラリがあり ます。例外がスローされる (そしてライブラリによってキャッチされる) のはおそらく 1% の確率ですが、私はこのメソッドを頻繁に呼び出しています。編集者は、これは設計によるものだと言っています (実際、編集者が選択した設計は理にかなっています)。

問題は、例外がスローされるたびに Visual Studio を中断させたくないということです。

  • ArgumentOutOfRangeコードにいくつかの例外があり、それらを中断したい場合があるため、例外の中断をやめたくありません。
  • 「コードのみ」のデバッグを有効にしたくありません。これは、コードの外部で例外がスローされることを懸念しているからです (特にパフォーマンス上の理由から)。

これを達成する方法はありますか?属性 ( などDebuggerStepThrough) を調べていますが、適切なものがまだ見つかりません。

これを行う方法に関するヒントはありますか?

4

3 に答える 3

3

「自分のコードのみ」のデバッグを有効にしたくない

ええ、すぐにやめてください。これは、不要なデバッガーのブレークを取得しないために必要な機能です。他人のくだらないコードを知りたくない場合は、そのチェックボックスをオンに戻してください。

プログラマーがフロー制御に例外を使用する場合、これは常に常軌を逸しています。非常に一般的な犯罪です。それを混乱させてデバッグセッションを非常に退屈なクリックの悪夢に変えるには、そのうちの2つが必要です. 最初の例外で中断するデバッガー機能が必要な場合、他の誰かがそれを必要とする場合、基本的に失われます。

[DebuggerNonUserCode] または [DebuggerHidden] または [DebuggerStepThrough] 属性を魔法のように使用して、その問題を解決できることを誰もが望んでいます。そうではありません。他のプログラマーは、自分のコードがそれらの属性に値するほど重要ではないとは考えていませんでした。それは、try/catch-em-all コードを使用するコードには常にバグが隠されているからではありません。ポケモンコード。

そのため、Microsoft は、プログラマーがくだらないライブラリ コードに対処するのを支援する別の方法を見つけなければなりませんでした。彼らがやった。そのチェックボックスにチェックを入れてください、バム、解決しました。とにかく、厄介なグラムを作成者に送信する以外に、そのくだらないコードについてできることは何もありません。私たちやマイクロソフトがあなたの仕事を遅らせないようにしてください。人々が使いたがる製品を作るためには、皆で協力しなければなりません。

于 2016-12-02T23:31:17.987 に答える
2

Visual Studioでは不可能だと思いますが、WinDbgでは確かに可能です。たとえば、http://blogs.msdn.com/b/alejacma/archive/2009/08/24/managed-debugging-with-windbg-breaking-on-an-exception-part-1.aspxを参照してください。

補足として、Visual Studio 2010 以降では、WinDbg 拡張 DLL を直接読み込んで使用して、追加の機能 (おそらく必要なものを含む) を提供できるようですが、まだ試していません。たとえばhttp://wwwを参照してください。 .dotnetcurry.com/ShowArticle.aspx?ID=648

于 2011-03-08T10:46:18.120 に答える
1

できることは、Visual Studio (バージョン 2012 以降) に同梱されているデバッグ エンジンであるConcordを使用することです。優れたマネージ API (および vsix テクノロジを使用して展開可能) を介して非常に拡張可能ですが、完全に文書化されているわけではありません。

Concord には、 IDkmDebugMonitorExceptionNotification インターフェイスを使用してフックできるデバッグ モニターの概念があります。

すばらしいことに、このインターフェイスは、スローされたすべての例外を監視できます。また、検出された例外イベントを「抑制する」こともできます。これはまさに必要なものです。

私が提案するのは、Hello Worldサンプルから始めることです: . ダウンロードして、期待どおりに動作することを確認してください。

今、次のHelloWorld.vsdconfigxmlように変更するだけです:

<!--TODO: If you copy the sample, ensure to regenerate the GUID in this file -->

<!-- 1. change component level to something higher than 40500 -->
<ManagedComponent
  ComponentId="51736b11-9fb4-4b6d-8aca-a10a2b7ae768"
  ComponentLevel="40501"
  AssemblyName="HelloWorld">

  <!-- 2. change class full name to HelloWorld.ExceptionHandler, for example -->
  <Class Name="HelloWorld.ExceptionHandler">
    <Implements>
      <InterfaceGroup>
        <NoFilter/>
        <!-- 3. change supported interface -->
        <Interface Name="IDkmDebugMonitorExceptionNotification"/>
      </InterfaceGroup>
    </Implements>
  </Class>

</ManagedComponent>

次に、ExceptionHandler.csクラスを作成して、そこに次のようなものを配置します。

public class ExceptionHandler : IDkmDebugMonitorExceptionNotification
{
    private bool _unhandledDetected;

    // we're being called!
    public void OnDebugMonitorException(DkmExceptionInformation exception, DkmWorkList workList, DkmEventDescriptorS eventDescriptor)
    {
        if (_unhandledDetected)
        {
            // this will cause the program to terminate
            eventDescriptor.Suppress();
            return;
        }

        if (exception.ProcessingStage.HasFlag(DkmExceptionProcessingStage.Unhandled))
        {
            _unhandledDetected = true;
        }
        else if (exception.ProcessingStage.HasFlag(DkmExceptionProcessingStage.Thrown))
        {
            if (SuppressException(exception))
            {
                eventDescriptor.Suppress();
            }
        }
    }

    // should we suppress a thrown (1st chance) exception?
    private bool SuppressException(DkmExceptionInformation exception)
    {
        // implement any custom logic in here, for example use the exception's name
        if (exception.Name == typeof(ArgumentOutOfRangeException).FullName)
        {
            // for example, use the module (assembly) name
            var clrAddress = (DkmClrInstructionAddress)exception.InstructionAddress;
            var clrModule = clrAddress.ModuleInstance;
            if (clrModule.Name == "TheUglyOne.dll")
                return true; // we don't want this one!
        }
        return false;
    }
}

プロジェクトを実行すると、監視されているすべての例外が表示されるはずです (「自分のコードのみ」および/または例外トリガーの設定に関係なく)。見たい。私は確認していませんが、Dkm クラスは大量の .NET メタデータ情報を提供するため、カスタム属性を使用してロジックを構築できると思います。

注: ご覧のとおり、プログラムが正常に終了することを確認するためのトリックがあります。

于 2016-12-07T22:43:41.213 に答える