【问题标题】:Printing an Exception in Debugger在调试器中打印异常
【发布时间】:2023-03-26 02:25:01
【问题描述】:

我的问题在于 catch 语句。尝试执行,但异常似乎从未被捕获并且不会打印到调试器。结果表明从未处理过异常并且抛出了 FindElementException,尽管这正是我想要捕获的。

private void verify(HtmlControl obj, int timeout)
{
    try
    {
        for (int i = 0; i < timeout; i++)
        {
            obj.Wait.ForExists();
            //break;
        }
    }
    catch (Exceptions.FindElementException ex)
    {
        Debug.WriteLine("Could Not Verify Object" + obj + "Exists.  Exception: " + ex);
    }
}

【问题讨论】:

    标签: c# debugging exception printing


    【解决方案1】:

    非常感谢大家对该主题的帮助和意见,但今天早上我能够通过 MSDN 博客找到有关该主题的文档。供将来参考,这是 x64 版本的 Windows 的常见问题,不幸的是,没有人可以做很多事情来解决这个问题。以下是微软博客中的文字,已删除图片和数字(http://blogs.msdn.com/b/debugger/archive/2010/05/12/visual-studio-debugger-fails-to-catch-unhandled-exception-for-a-windows-form-or-wpf-application.aspx):

    为什么调试器不能在 x64 版本的 Windows 上捕获/中断我未处理的异常?

    在 x64 版本的 Windows 上发生这种情况的原因是设计 由 Windows 操作系统决定; x64 版本的 Windows 不允许用户模式异常在内核转换后传播 在调用堆栈上。当一个异常被抛出时会发生什么 应用程序,它在调用堆栈上向后移动,直到它 到达异常处理程序或应用程序的“Main()”方法。如果 异常到达应用程序的“Main()”方法而不被 处理后,调试器识别出异常未处理并且 中断发生异常的应用程序。如下所示, Form_Load 方法会导致内核转换,因此当出现异常时 抛出一个 Form_Load 方法到达内核框架上 callstack,操作系统捕获异常。由于 异常在到达“Main()”方法之前被捕获,从 调试器的观点 异常被捕获——调试器无法 确定异常被操作系统捕获, 不是用户代码。

    如何判断这是否是我的问题?

    这个问题可能会以不同的方式表现出来,具体取决于 异常类型。 Windows 窗体和 WPF 应用程序都有 底层框架中将捕获的异常处理代码 某些类型的异常(例如 NullReferenceException),所以在某些 在这种情况下,您的应用程序将因未处理的异常而崩溃,在 其他情况下,表单将加载并出现,但是 Form_Load 方法(以及所有后续调用)将无法正确运行 完成。但是,“输出”窗口中会显示一条消息 “第一次出现‘’类型的机会异常发生在 ”。

    解决方法

    不幸的是,在这种情况下,调试器无能为力,因为 操作系统捕获异常(上面解释过)。这 Visual Studio 中的解决方法是启用“第一次机会”例外 Form_Load 方法中抛出的异常类型。至 对此:

    导航到“调试”菜单,然后选择“例外”检查 “公共语言运行时异常”行的“抛出”框。 (笔记: 您可以使用“+”号展开例外,并且只检查 所需异常的“抛出”框”

    再次感谢大家的宝贵时间和意见!

    问候,

    迈克尔

    【讨论】:

      【解决方案2】:

      我建议在 Visual Studio 中打开所有异常的中断,以便您可以在异常发生时对其进行检查。您可以通过转到Debug (menu) &gt; Exceptions... 并选中所有复选框来执行此操作。也许 FindElementException 的命名空间与您期望的不同?我怀疑你没有捕捉到你想要的异常类型。

      【讨论】:

      • 我也尝试在 catch 中使用一般的“Exception ex”,但效果相同。我有点困惑,为什么它一开始就没有到达 catch 块。
      • 如果Exception ex 没有捕捉到它,那么它不会被抛出。
      【解决方案3】:

      尝试在其中放置一个通用的 catch,并在该 catch 中放置一个断点。这样,当它捕获时,您可以检查该错误消息并找出它所抛出的异常究竟是什么。一旦你发现了这一点,你就可以改变你的代码来期待那个异常,而不是你拥有的那个。

      第 1 步)将您的代码更改为:

      private void verify(HtmlControl obj, int timeout)
      {
          try
          {
              for (int i = 0; i < timeout; i++)
              {
                  obj.Wait.ForExists();
                  //break;
              }
          }
          catch (Exceptions.FindElementException ex)
          {
              Debug.WriteLine("Could Not Verify Object" + obj + "Exists.  Exception: " + ex);
          }
          catch {} // PUT THE BREAKPOINT HERE
      }
      

      步骤 2) 运行并找出抛出的异常。如果您不知道该怎么做,请发表评论,我会解释(假设您使用的是 VisualStudio 或其他使用断点的编译器)

      第 3 步)将您的代码更新为:

      private void verify(HtmlControl obj, int timeout)
      {
          try
          {
              for (int i = 0; i < timeout; i++)
              {
                  obj.Wait.ForExists();
                  //break;
              }
          }
          catch (INSERTNEWEXCEPTIONTYPEHERE ex)
          {
              Debug.WriteLine("Could Not Verify Object" + obj + "Exists.  Exception: " + ex);
          }
      }
      

      【讨论】:

      • 我只是尝试按照说明执行代码,但是通过调试器运行代码最有趣的部分是在尝试之后它似乎没有到达 catch 块。每次运行时,异常都会在代码的早期抛出并在断点之前终止。
      • 我只是想测试这个方法以验证它是否适用于该方法的两次迭代,我知道它适用于存在的对象,但不存在的对象不会被捕获为一个例外。
      • 这很奇怪.. 如果错误在 try-catch 块中,程序不应该终止。您确定它甚至可以到达 try-catch 块吗?尝试将其他代码位放入 try-catch 块中。或者更好的是,如果您的调试器具有“介入”代码的能力,请在您知道 SURE 工作的最后一行放置一个断点,然后从那里“介入”
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-12-30
      • 2010-12-01
      • 1970-01-01
      • 2011-04-08
      • 1970-01-01
      • 2017-12-21
      相关资源
      最近更新 更多