5

我在 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

有没有更好的解决方案?

4

1 回答 1

9
  Try
      System.Windows.Forms.Application.Run(New Form1)
  Catch ex As Exception
      WriteErrorLogs(ex)
  End Try

是的,当您在没有附加调试器的情况下运行它时,该 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

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

于 2013-02-13T17:07:12.910 回答