在Application.Run上尝试/捕获在调试器中工作,但在运行实际应用程序时不起作用

pvz*_*kch 4 .net vb.net error-handling

我在VB.NET中创建了一个项目.如果我创建的应用程序将产生不需要的错误,它将创建一个包含错误的文本文件.我在Visual Studio上运行时能够执行此操作,但在运行单独的应用程序时,它不起作用,在bin/Debug上找到可执行文件.

这就是我所做的:

Sub Main(ByVal ParamArray args() As String)
  Try
System.Windows.Forms.Application.Run(New Form1)
  Catch ex As Exception
WriteErrorLogs(ex)
  End Try
End Sub

Sub WriteErrorLogs(Byval ex As Exception)
' create a textfile the write x.Message, x.Source, x.ToString
  Dim dnow As String = Now.ToString
  Dim filename As String = "Error " & removeInvalidChars(dnow)
  Dim saveto As String = New IO.FileInfo("Errors/" & filename).FullName & ".txt"
  Dim title As String = ex.Message
  Dim stacktrce As String = ex.StackTrace

  If Not IO.Directory.Exists(New IO.DirectoryInfo("Errors").FullName) Then IO.Directory.CreateDirectory("Errors")
  Dim fw As New IO.StreamWriter(saveto, False, System.Text.Encoding.UTF8)
  fw.WriteLine(title)
  fw.WriteLine()
  fw.WriteLine(stacktrce)
  fw.Close()
End Sub

Private Function removeInvalidChars(ByRef s As String)
  Dim invalidChars() As Char = "\/:*?""<>|".ToCharArray
  For Each i As Char In invalidChars
    s = s.Replace(i, ".")
  Next
  Return s
End Function
Run Code Online (Sandbox Code Playgroud)

有更好的解决方案吗?

Han*_*ant 8

  Try
      System.Windows.Forms.Application.Run(New Form1)
  Catch ex As Exception
      WriteErrorLogs(ex)
  End Try
Run Code Online (Sandbox Code Playgroud)

是的,当你在没有连接调试器的情况下运行它时,Catch子句永远不会捕获异常.重新路由在UI线程上引发的异常,并触发Application.ThreadException事件.默认显示一个对话框,您应该注意到从bin\Debug目录运行它时.

如果连接了调试器,它的工作方式会有所不同,当您需要调试未处理的异常时,该对话框确实会受到妨碍.因此,故意禁用ThreadException事件,调试器会显示代码崩溃的位置.对于您编写的代码,这不会发生,现在Catch子句确实捕获了异常.

当程序因工作线程引发的未处理异常而崩溃时,Catch子句也不起作用,它只能看到UI线程上的异常.

您将需要一个更加可靠的方法,您可以从AppDomain.UnhandledException事件中获取一个.这是针对任何未处理的异常引发的,无论它引发了什么线程.让代码看起来像这样:

Module Module1
    Public Sub Main(ByVal args() As String)
        Application.EnableVisualStyles()
        Application.SetCompatibleTextRenderingDefault(False)
        If Not System.Diagnostics.Debugger.IsAttached Then
            Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException)
            AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf LogUnhandledExceptions
        End If
        Application.Run(New Form1())
    End Sub

    Private Sub LogUnhandledExceptions(ByVal sender As Object, ByVal e As UnhandledExceptionEventArgs)
        Dim ex = DirectCast(e.ExceptionObject, Exception)
        '' Log or display ex.ToString()
        ''...
        Environment.Exit(System.Runtime.InteropServices.Marshal.GetHRForException(ex))
    End Sub
End Module
Run Code Online (Sandbox Code Playgroud)

使用Debugger.IsAttached可确保您可以使用调试器诊断未处理的异常.使用Application.SetUnhandledExceptionMode可确保永远不会显示该对话框并记录所有异常.