Try/Catch on Application.Run работает в отладчике, но не работает при запуске самого приложения
Я сделал проект в 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
Есть ли лучшее решение для этого?
1 ответ
Try
System.Windows.Forms.Application.Run(New Form1)
Catch ex As Exception
WriteErrorLogs(ex)
End Try
Да, это предложение Catch никогда не будет перехватывать исключение, когда вы запускаете его без подключенного отладчика. Исключения, которые возникают в потоке пользовательского интерфейса, перенаправляются и вместо этого вызывают событие Application.ThreadException. Который по умолчанию отображает диалоговое окно, вы должны были заметить, что когда вы запустили его из каталога bin\Debug.
Он работает по-другому, когда у вас подключен отладчик, этот диалог действительно мешает, когда вам нужно отлаживать необработанные исключения. Таким образом, событие ThreadException намеренно отключено, и отладчик показывает, где произошел сбой вашего кода. Что не произойдет с кодом, который вы написали, теперь, когда предложение Catch перехватывает исключение.
Предложение Catch также не будет работать, когда ваша программа потерпела крах из-за необработанного исключения, возникшего в рабочем потоке, она может видеть только исключения в потоке пользовательского интерфейса.
Вам потребуется более основательный подход, вы можете получить его из события 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 гарантирует, что диалоговое окно никогда не отображается и все исключения регистрируются.