1

编辑:

致所有回答者和评论者:请专注于提供我要求的解决方案,而不是提供重构它的方法。为简洁起见,下面提供的代码是一个非常精简的示例。我已经在下面说明了这种类型的代码存在于整个应用程序的 20 或 30 个位置,如果存在更简单的解决方案,我将选择不移动/合并/重构任何代码。

原始问题:

首先,简要介绍一下:我们有一个由离岸团队开发的应用程序。此应用程序的目的是对各种数据库表进行夜间维护。它是一个 WinForms 应用程序,但它更像是一个控制台应用程序,因为它所做的只是 1) 在 Form1_Load 中执行单个方法,然后 2) 调用 End 以关闭程序。

问题是错误电子邮件通知不起作用,所以我负责修复它的任务。考虑这段代码:

Try
    'This inner Try/Catch is actually code in another method
    Try
        'Run some code here
    Catch ex As Exception
        'Errors are logged silently to text file here
    End Try
Catch ex As Exception
    'Code to email exception details is here
End Try

问题是在内部的 Try/Catch 中抛出并处理了异常。因此,在外部 Try/Catch 中不会处理任何异常,因此没有发送电子邮件通知。

有人可能会说只添加Throw ex内部 Catch,但请记住,代码中大约有 20 或 30 个地方是这样处理异常的。我正在做的决定是让它现在工作,而不是进行那种开发工作。因此,我寻求一种方法来获取应用程序抛出的最后一个异常。这样,我可以将 finally 块添加到外部 Try/Catch 并执行以下操作:

Finally
    If Not Application.GetLastException() is Nothing Then
       SendErrorEmail(Application.GetLastException())
    End If
End Try
4

2 回答 2

5

因此,如果我理解正确,您的应用程序会捕获所有异常并将它们静默记录到文件中。

您希望更改行为,以便在程序结束时获得最后抛出的异常(如果有),并发送包含该异常详细信息的电子邮件。但是最后抛出的异常没有存储在任何地方。

并且您希望在不修改处理异常的代码的情况下更改此行为。

那是做不到的。您如何期望在不改变程序行为的情况下改变程序的行为?你问的是不可能的。(而且,不,甚至尤达也无法将这个特殊的 X 翼从沼泽中拉出来。)

没有自动保存上次抛出的异常的运行时属性。

您必须对捕获异常的代码进行一些修改。您说代码采用这种通用格式:

Try
    'This inner Try/Catch is actually code in another method
    Try
        'Run some code here
    Catch ex As Exception
        'Errors are logged silently to text file here
    End Try
Catch ex As Exception
    'Code to email exception details is here
End Try

我认为问题出在内部Catch块中。在我看来,如果有通用代码将错误记录到文本文件中,那么该代码应该在单独的方法中。如果是,则修改该方法以将最后一个异常保存在您的方法可以访问的属性中GetLastException。如果没有处理异常日志记录的通用方法,那么您必须在每个地方进行更改。

评论者是正确的:一般的“捕获所有异常”几乎总是一个坏主意。特别是当“处理”包括记录和继续时。当您捕获一些随机异常时,您不知道程序的状态是什么。很可能是数据损坏,程序状态不稳定。“记录并继续”只会让问题变得更糟,并可能导致各种有趣的副作用,如数据损坏、无限循环、死锁等。

您最好的做法是重构代码。实际上,最好的做法是将其发回给离岸开发商并告诉他们做正确的事。但这可能问得太多了。

于 2013-06-24T13:53:04.553 回答
3

我参加这个聚会已经很晚了,但你可以尝试这种相当丑陋的做事方式。

首先通过添加 LastException 属性和 GetLastException 函数来扩展 Application 类,详见此处

其次,在每个内部 Catch 块中添加一行并设置 LastExcepotion 属性:

Application.LastException = ex

好了,无需重构所有离岸代码。

于 2014-01-28T13:25:25.810 回答