【问题标题】:How can I catch an application crash/ungraceful exit?如何捕获应用程序崩溃/不正常退出?
【发布时间】:2020-01-17 15:49:04
【问题描述】:

我有一个 VB.NET WinForms 应用程序从存储在网络共享上的可执行文件运行。在那个应用程序中,我在ApplicationEvents (Private Sub MyApplication_UnhandledException(sender As Object, e As UnhandledExceptionEventArgs) Handles Me.UnhandledException) 中定义了UnhandledException 处理程序。在我的处理程序中,我有一个方法可以在提示用户确认退出应用程序之前将异常详细信息记录到文本文件中。

但是,此应用程序“随机”崩溃并完全退出,而没有创建任何日志或显示消息框。这种行为发生在应用程序的不同可执行点,我正在拼命寻找原因。我猜测问题可能是由于网络连接暂时中断或与 PostgreSQL 数据库通信的其他问题,但我无法确认来源,因为没有堆栈跟踪或消息在应用程序从用户屏幕上消失之前提供的详细信息。

这应该是“简单的”,但我不知所措,因为我尝试了几件事,包括将大量代码块包装在 Try...Catch 块中,并向我的错误处理程序添加额外的日志记录功能。我尝试重新排列我的UnhandledException 处理程序中的代码以避免新对象实例化的任何问题(对于我的ErrorHandler 对象)。如果网络不可用,我在错误处理中添加了一个检查以在本地记录错误。如果关闭不是由用户直接发起的,我什至在主窗体的FormClosing 事件中添加了一个简单的消息框,以尝试至少让应用程序在关闭之前执行某事完全。

到目前为止,无论我尝试过什么,应用程序仍然会在看似随机的时间强制退出。用户将按下一个按钮来执行通常正常工作的许多方法中的任何一种。如果用户在被踢出后重新启动应用程序并再次执行完全相同的操作,则它可以正常工作。我需要完成的是某种形式的“白痴证明”错误处理,以便捕获并记录导致应用程序退出的任何内容。我确定目前我还没有想到一些事情,所以如果需要进一步澄清,请告诉我。


代码

应用程序的Startup 事件处理程序:

Private Sub MyApplication_Startup(sender As Object, e As StartupEventArgs) Handles Me.Startup
    Try
        Common.ApplicationStartup(ApplicationSettings.CurrentUser)
    Catch ex As Exception
        Dim StartupException As New ErrorHandler(ex)

        StartupException.LogException()
        MessageBox.Show("You do not have permission to access this resource." & vbCrLf & vbCrLf &
                    "The application will now exit.")
        System.Environment.Exit(1)
    End Try

    ' *********************************************************************
    ' ** Notify the user if the application is running in test mode.     **
    ' *********************************************************************
    If ApplicationSettings.TestMode Then
        MessageBox.Show("This application is currently running in Test Mode, and will use " &
                        "local paths for data and configuration information." & vbCrLf & vbCrLf &
                        "If you are trying to use this application with live data and see " &
                        "this message, please contact the IT HelpDesk for assistance.", "TEST MODE",
                        MessageBoxButtons.OK, MessageBoxIcon.Exclamation)

        If ApplicationSettings.CurrentUser.Department = Users.Employee.Department.IS Then
            If MessageBox.Show("Do you want to continue in Test Mode?", "TEST MODE", MessageBoxButtons.YesNo,
                               MessageBoxIcon.Question, MessageBoxDefaultButton.Button1) = DialogResult.No Then
                ApplicationSettings.TestMode = False
            End If
        End If
    End If

    ' *********************************************************************
    ' ** Initialize any application-specific settings here.              **
    ' *********************************************************************
    Try
        'If ApplicationSettings.TestMode AndAlso ApplicationSettings.CurrentUser.Department = Users.Employee.Department.IS Then
        '    MessageBox.Show("If you have any additional parameters/settings to configure for this application, " &
        '                    "please do so before commenting out this message.",
        '                    "DEVELOPMENT WARNING", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
        'End If
    Catch ex As Exception
        Dim ExHandling As New Common.ErrorHandler(ex)

        ExHandling.LogException()

        MessageBox.Show("There was a problem with initializing the application's configuration." & vbCrLf & vbCrLf &
                    "The application will now exit.")
        System.Environment.Exit(2)
    End Try
End Sub

ApplicationStartup 方法:

Public Sub ApplicationStartup(ByRef CurrentUser As Users.Employee)
    ' *********************************************************************
    ' ** Default the TestMode variable to False.  If the check for       **
    ' ** whether or not the application is running from the IDE fails,   **
    ' ** the application should assume that it's running live.           **
    ' *********************************************************************
    ApplicationSettings.TestMode = False

    ' *********************************************************************
    ' ** Perform a check of whether or not the application is running    **
    ' ** from the IDE or the Debug folder.                               **
    ' *********************************************************************
    SetTestMode()

    ' *********************************************************************
    ' ** Retrieve any parameters sent to the executable from the command **
    ' ** line and determine if the application is running from the task  **
    ' ** scheduler.                                                      **
    ' *********************************************************************
    ApplicationSettings.ScheduledTask = False
    ApplicationSettings.RuntimeParameters = System.Environment.GetCommandLineArgs().ToList

    If Not ApplicationSettings.RuntimeParameters Is Nothing AndAlso ApplicationSettings.RuntimeParameters.Count > 0 Then
        For Each Parameter As String In ApplicationSettings.RuntimeParameters
            If Parameter.ToUpper.Contains("SCHEDTASK") Then
                ApplicationSettings.ScheduledTask = True
                Exit For
            End If
        Next
    End If

    ' *********************************************************************
    ' ** Set up the CurrentUser object by querying Active Directory and  **
    ' ** the PostgreSQL database for details.                            **
    ' *********************************************************************
    Try
        If CurrentUser.ADUserName Is Nothing OrElse String.IsNullOrEmpty(CurrentUser.ADUserName) Then
            CurrentUser = New Users.Employee(Environment.UserName)
        End If
    Catch UserEx As Exception
        Dim ExHandler As New ErrorHandler(UserEx)

        ExHandler.LogException()
        Throw UserEx
    End Try

    If CurrentUser Is Nothing Then
        Throw New Exception("Username " & Environment.UserName & " was not found in Active Directory.")
    ElseIf CurrentUser.Enabled = False Then
        Throw New Exception("Username " & Environment.UserName & " is not a currently active employee.")
    End If

    ' *********************************************************************
    ' ** Default the DBCommandTimeout variable to 30.                    **
    ' *********************************************************************
    ApplicationSettings.DBCommandTimeout = 30
End Sub

Private Sub SetTestMode()
    ' *********************************************************************
    ' ** Use the Debug.Assert to call the InTestMode function, which     **
    ' ** will set the TestMode variable to True.  Debug.Assert will only **
    ' ** execute if the program is running from a debugging version of   **
    ' ** the code (in Design-Time, or from the Debug folder).  When the  **
    ' ** code is running from a compiled executable, the Debug.Assert    **
    ' ** statement will be ignored.                                      **
    ' *********************************************************************
    Debug.Assert(InTestMode)
End Sub

Private Function InTestMode() As Boolean
    ' *********************************************************************
    ' ** Set the global TestMode variable to True.  This function is     **
    ' ** only called in debug mode using the Debug.Assert method in the  **
    ' ** SetTestMode Sub.  It will not be called if the application is   **
    ' ** running from a compiled executable.                             **
    ' *********************************************************************
    Common.ApplicationSettings.TestMode = True
    Return True
End Function

UnhandledException 事件处理程序:

Private Sub MyApplication_UnhandledException(sender As Object, e As UnhandledExceptionEventArgs) Handles Me.UnhandledException
    Dim Response As DialogResult = DialogResult.Yes

    Response = MessageBox.Show("An unknown error occurred in the application." & vbCrLf & vbCrLf &
                               "Do you want to exit the application?", "UNHANDLED EXCEPTION",
                               MessageBoxButtons.YesNo, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1)

    Dim UnhandledError As New ErrorHandler(e.Exception)

    UnhandledError.LogException()

    If Response = DialogResult.Yes Then
        e.ExitApplication = True
    Else
        e.ExitApplication = False
    End If
End Sub

主窗体的FormClosing事件:

Private Sub frmMain_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
    If Not e.CloseReason = CloseReason.UserClosing Then
        MessageBox.Show("The application has encountered some sort of problem and is closing.")
    End If
End Sub

如果您想/需要查看更多代码,请告诉我。正如我所说,错误发生在应用程序执行中看似随机的点,并且在一次尝试或另一次尝试之间不一致。


2020 年 7 月 1 日更新


我有一段时间没有回到这个话题,因为我将可执行文件(和支持库)的副本移动到用户的本地驱动器,并让她从那里运行应用程序。当她使用该副本时,她并没有像上面描述的那样从程序中“启动”(她在这里和那里有一些错误,但这些都按预期由我的异常处理例程处理)。

几个月后,我有理由将用户切换回使用网络共享中的可执行文件副本。我刚刚收到用户的报告,她再次遇到被随机踢出应用程序而没有任何警告或错误的问题,而且我没有收到任何异常“报告”。对我来说幸运的是,她在记录事件方面做得很好。

奇怪的是,有时这些崩溃发生在她没有做任何“特别”的事情时。有几次,当她简单地单击其中一个工具条菜单以显示子菜单的下拉列表时,就会发生这种情况。我已经检查过,这些父工具条菜单没有任何事件处理代码,所以它不像正在执行任何查询或其他指令。它应该只是显示子菜单。

FWIW,几周前,我们的办公室和存储这些可执行文件的服务器之间存在严重的连接问题(托管虚拟机通过站点到站点 VPN 访问)。尽管我在其他任何地方都没有看到任何数据包丢失,但我在 VPN 上丢失了大约 10% 的数据包。我从来没有发现是什么导致了数据包丢失,但它似乎已经解决了,我只能假设这里和那里之间的一个 ISP 有一个他们修理/更换的故障设备。当我通过 VPN 对服务器运行 PING 测试时,我没有看到任何明显的数据包丢失(可能是数千个数据包中的 1 个数据包)和 15-35 毫秒的响应时间。

在这一点上,我只是猜测(显然),但我认为 VPN 连接上可能发生某种“超时”,导致与代码库的连接丢失。这是一个完整的 pS.W.A.G. ((伪)Scientific Wild-@$$ Guess),但我正在尝试提出一个可行的解决方案来解决这个问题。


我的想法

一个想法是这样的:我所有的内部应用程序都在这个服务器上运行,并且每个支持库都存储在可执行文件夹中。是的,这意味着我在服务器上的不同文件夹中存储了许多库的多个副本。我一直想要减少这种重复,但我真的没有/花时间找出最好的方法来做到这一点。此时,我正在考虑为每个工作站安装某种“安装程序”包,以将必要的库放入每个用户的 GAC(全局程序集缓存),而不是通过 VPN 访问它们。

唯一的问题(我能想到的)是有几个遗留系统使用相同库的不同版本。例如,我目前的开发是使用 Npgsql v4.1.3.1,但是有一些应用程序仍在使用 v2.x,我真的没有时间去检查每个应用程序来查找哪些应用程序正在/没有使用当前版本实现版本升级。这只是会出现此类问题的众多库之一,因此我想我需要尝试将所有正在使用的版本安装到每个 GAC。

另一个想法: 将所有可执行文件带回本地服务器(而不是通过 VPN)并更改所有快捷方式以指向该版本,而不是需要 VPN 的版本。显然,这样做的好处是减少了对互联网连接和第三方系统等事物的依赖,并减少了延迟。

this 选项的问题在于,我的老板完全“不支持”它。当我过去提出类似建议时,他们的回应是“我们正在为托管服务器付费,他们应该支持它......”好吧,我们都知道类似这很可能超出了对第三方服务器主机的任何合理支持请求的范围。

我真的倾向于 GAC 选项 - 至少作为第一步 - 但在我开始走这条路之前,我需要做一些研究。还有其他人对我可以处理这个问题的方法有其他建议吗?我的想法真的快用完了,我必须找到一个真正可行且可持续的解决方案。

更多信息


我已经实现了来自@djv 的以下建议,将应用程序的启动包装在启动新线程的“启动”形式中,但仍然无法捕获导致崩溃的任何原因。该应用程序仍然只是周期性地死掉,到目前为止我完全没有找到任何日志记录。

我还在ApplicationEvents 中包含了一个非常简单的NetworkAvailabilityChanged 事件处理程序,以尝试捕捉那里发生的事情。

        Private Sub MyApplication_NetworkAvailabilityChanged(sender As Object, e As NetworkAvailableEventArgs) Handles Me.NetworkAvailabilityChanged
            If Not My.Computer.Network.IsAvailable Then
                MessageBox.Show("Network connection has been lost.", "NETWORK CONNECTION TESTING", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            End If
        End Sub

不幸的是,即使 也没有给我任何额外的见解,因为用户从未见过 MessageBox

已经在用户的 Windows 事件日志中发现了一个错误,该错误似乎与最近的事件相对应,但我不确定它的确切含义:

EVENT ID 1000
---
Faulting application name: <EXECUTABLE_NAME>.exe, version: 1.0.0.0, time stamp: 0x9d491d36
Faulting module name: clr.dll, version: 4.8.4180.0, time stamp: 0x5e7d1ed7
Exception code: 0xc0000006
Fault offset: 0x000cc756
Faulting process id: 0xe570
Faulting application start time: 0x01d64fc245d7d922
Faulting application path: \\<SERVER_NAME>\<SHARE_PATH>\<EXECUTABLE_NAME>.exe
Faulting module path: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Report Id: 7016e3cc-7406-4854-95be-dbe3231447e7
Faulting package full name: 
Faulting package-relative application ID: 

这似乎表明 CLR 中的某些东西正在崩溃,但这似乎并没有给我提供比以前更多的信息。

针对特定问题的进一步诊断/研究


在事件日志中进一步挖掘之后,我发现了上述事件发生前后的几个错误:

EVENT ID 1005
---
Windows cannot access the file  for one of the following reasons: there is a problem with the network connection, the disk that the file is stored on, or the storage drivers installed on this computer; or the disk is missing. Windows closed the program <EXECUTABLE_NAME> because of this error.

Program: <EXECUTABLE_NAME>
File: 

The error value is listed in the Additional Data section.
User Action
1. Open the file again. This situation might be a temporary problem that corrects itself when the program runs again.
2. If the file still cannot be accessed and
    - It is on the network, your network administrator should verify that there is not a problem with the network and that the server can be contacted.
    - It is on a removable disk, for example, a floppy disk or CD-ROM, verify that the disk is fully inserted into the computer.
3. Check and repair the file system by running CHKDSK. To run CHKDSK, click Start, click Run, type CMD, and then click OK. At the command prompt, type CHKDSK /F, and then press ENTER.
4. If the problem persists, restore the file from a backup copy.
5. Determine whether other files on the same disk can be opened. If not, the disk might be damaged. If it is a hard disk, contact your administrator or computer hardware vendor for further assistance.

Additional Data
Error value: C00000C4
Disk type: 0

还有这个:

EVENT ID 1026
---
Application: <EXECUTABLE_NAME>.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.Runtime.InteropServices.SEHException
   at <ROOT_NAMESPACE>.frmPayments.get_instance()
   at <ROOT_NAMESPACE>.frmMain.tsmiProcessPayments_Click(System.Object, System.EventArgs)
   at System.Windows.Forms.ToolStripItem.RaiseEvent(System.Object, System.EventArgs)
   at System.Windows.Forms.ToolStripMenuItem.OnClick(System.EventArgs)
   at System.Windows.Forms.ToolStripItem.HandleClick(System.EventArgs)
   at System.Windows.Forms.ToolStripItem.HandleMouseUp(System.Windows.Forms.MouseEventArgs)
   at System.Windows.Forms.ToolStripItem.FireEventInteractive(System.EventArgs, System.Windows.Forms.ToolStripItemEventType)
   at System.Windows.Forms.ToolStripItem.FireEvent(System.EventArgs, System.Windows.Forms.ToolStripItemEventType)
   at System.Windows.Forms.ToolStrip.OnMouseUp(System.Windows.Forms.MouseEventArgs)
   at System.Windows.Forms.ToolStripDropDown.OnMouseUp(System.Windows.Forms.MouseEventArgs)
   at System.Windows.Forms.Control.WmMouseUp(System.Windows.Forms.Message ByRef, System.Windows.Forms.MouseButtons, Int32)
   at System.Windows.Forms.Control.WndProc(System.Windows.Forms.Message ByRef)
   at System.Windows.Forms.ScrollableControl.WndProc(System.Windows.Forms.Message ByRef)
   at System.Windows.Forms.ToolStrip.WndProc(System.Windows.Forms.Message ByRef)
   at System.Windows.Forms.ToolStripDropDown.WndProc(System.Windows.Forms.Message ByRef)
   at System.Windows.Forms.Control+ControlNativeWindow.OnMessage(System.Windows.Forms.Message ByRef)
   at System.Windows.Forms.Control+ControlNativeWindow.WndProc(System.Windows.Forms.Message ByRef)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr, Int32, IntPtr, IntPtr)
   at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG ByRef)
   at System.Windows.Forms.Application+ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr, Int32, Int32)
   at System.Windows.Forms.Application+ThreadContext.RunMessageLoopInner(Int32, System.Windows.Forms.ApplicationContext)
   at System.Windows.Forms.Application+ThreadContext.RunMessageLoop(Int32, System.Windows.Forms.ApplicationContext)
   at System.Windows.Forms.Application.Run(System.Windows.Forms.Form)
   at <ROOT_NAMESPACE>.StartupForm.Main()
   at System.Threading.ThreadHelper.ThreadStart_Context(System.Object)
   at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
   at System.Threading.ThreadHelper.ThreadStart()

对错误代码和异常信息做进一步的研究,看起来问题实际上是由于通过 VPN 从网络共享加载的可执行文件。

我找到的一些资料:

最后一个让我对 PE 文件选项以及如何为 VB.NET 应用程序设置它们进行了一些研究,但我没有找到足够的东西来感觉追求这种思路会带来足够的好处。

我想这意味着我需要做一些事情来将所有内容通过 VPN 带回执行。也许我会为应用程序进行某种实际的本地安装(现在我需要弄清楚如何实际做到这一点,但这远远超出了这个问题的范围)。我对此并不特别高兴,但至少我知道从这里往哪个方向发展。

回到最初的问题


但是,这个仍然并没有回答我最初关于如何捕获和处理这些应用程序杀手异常的问题。如果应用程序崩溃至少给了我一些关于当时发生的事情的迹象,我会“很好”。我认为ApplicationEvents 中的UnhandledException 处理程序甚至可以捕获这些,但对SEHException 的进一步研究至少可以帮助我了解为什么它没有 - 请参阅SEHException not caught by Try/Catch。我知道尝试定义规则来处理或忽略可能在UnhandledException 事件处理程序中出现的每一种异常类型将是一场噩梦,但它会更好,对故障排除更有帮助至少看到东西

【问题讨论】:

  • 了解更多有关您的应用程序的信息会很有帮助。 VB? C#?控制台应用程序?表格? WPF?
  • 另外,请考虑查看 Windows 事件日志以查看那里是否报告了错误。
  • 有几种方法可以做到这一点。你如何开始你的申请?你能显示一些代码吗?
  • @G_Hosa_Phat 你试过从本地机器而不是网络共享运行它吗?
  • @G_Hosa_Phat windows 是否提供应用程序崩溃的对话框?如果是这样,您可以在单击该对话框上的“确定”之前生成转储吗?如果是,那可以用来调查崩溃发生的原因。您还可以使用注册表设置为崩溃创建转储文件:stackoverflow.com/questions/30121822/…

标签: vb.net winforms error-handling crash


【解决方案1】:

这是一个想法。看起来它可能需要对您的应用程序的启动方式进行一些重写。但考虑添加另一个“启动表单”,使用 Application.Run à la C# void Main() { Application.Run(Form); }。您可以将其包装在 Try-Catch 中并处理其他未处理的异常。

添加一个名为 StartupForm 的表单,并将其作为应用程序的入口点

还有 StartupForm 代码

Imports System.Threading

Public Class StartupForm
    Protected Sub StartupForm_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
        Dim applicationThread = New Thread(AddressOf Main)
        applicationThread.SetApartmentState(ApartmentState.STA)
        applicationThread.Start()
        Dispose()
    End Sub
    Protected Shared Sub Main()
        Using myForm As New MainForm()
            AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf UnhandledExceptionHandler
            AddHandler Application.ThreadException, AddressOf UIThreadExceptionHandler
            Application.EnableVisualStyles()
            Try
                Application.Run(myForm)
            Catch ex As Exception
                UnhandledExceptionHandler(myForm, New UnhandledExceptionEventArgs(ex, True))
            End Try
        End Using
    End Sub
End Class

Module ExceptionHandlers
    Public Sub UIThreadExceptionHandler(ByVal sender As Object, ByVal args As ThreadExceptionEventArgs)
        MessageBox.Show(args.Exception.Message, NameOf(UIThreadExceptionHandler))
    End Sub
    Public Sub UnhandledExceptionHandler(ByVal sender As Object, ByVal args As UnhandledExceptionEventArgs)
        MessageBox.Show(args.ExceptionObject.Message, NameOf(UnhandledExceptionHandler))
    End Sub
End Module

StartupForm 会在处理自己之前启动一个新线程。新线程使用您的 MainForm 启动一个 UI 线程(不管它叫什么 - 这是您当前的启动表单)。

要对其进行测试,您可以通过按下按钮引发异常

Public Class MainForm
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Throw New Exception("Unhandled, from button on Form")
    End Sub
End Class

并看到它在初始 Try-Catch 中处理

我们添加额外的处理程序以防 Try-Catch 无法捕获所有内容

AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf UnhandledExceptionHandler
AddHandler Application.ThreadException, AddressOf UIThreadExceptionHandler

但我发现托管的*异常都被捕获了。

*当然,我们不会从非托管来源捕获异常

【讨论】:

  • 我会看看实现这样的东西。是的,这需要一些工作,但如果我可以使用它来找到问题的实际根源,那么这项工作将非常值得。当然,我不知道它需要那么多...大部分启动代码都是在MyApplication_Startup 事件中执行的,所以它应该仍然有效...
  • 我实施了这个建议并让我的用户运行重新编译的版本。第一天做得很好,但今天早上应用程序又完全崩溃了,没有任何警告,也没有任何消息框或日志。应用程序窗口刚刚消失。她回去并能够毫无问题地执行完全相同的事情。我无法在事件查看器中找到任何东西,但也许我只是没有找对地方。我目前唯一猜测可能的原因是网络连接暂时中断,但我什至不确定。
  • 我想我的下一个故障排除步骤是将可执行文件放在她的本地机器上并让她从那里运行它,但我真的希望我能抓住 something - ANYthing - 像这样关闭之前的应用程序。
  • @G_Hosa_Phat 如果您有任何非托管代码正在运行,这将不会捕获源自它的异常。听起来这就是正在发生的事情,但目前还不清楚。您是否使用任何非托管库?
  • 我没有使用任何 COM 组件,但一些库可能实现了一些非托管代码(Office Interop 和 Crystal Reports 最有可能)。我将整个可执行文件夹复制到用户的本地计算机,最终在生成报告时能够在 UIThread 处理程序中弹出错误。该报告使用 Microsoft ReportViewer 而不是 Crystal(此应用程序是由不同人编写的遗留代码的混杂,我已经尝试“清理”一段时间了)。 “好”的是这次它没有关闭应用程序。
【解决方案2】:

我会在应用程序的应用程序主机(调试文件夹)中制作一个 txt 文件的日志文件,这样您就可以作为开发人员不时检查它或将这些日志文件远程发送给您,这是不时收集的数据要在客户端查看代码错误并使用堆栈 strace 大致了解崩溃的原因,您可以查看有错误的代码行并详细描述错误,也

使用流式编写器的教程 https://www.c-sharpcorner.com/article/csharp-streamwriter-example/ 所以对于每个容易出错的代码块,你都会这样做

    Try
    'Here your code is written for example dim a as integer=12
    Catch ex as exception
' Here stream writer takes your ex.Message & ex.Stack Trace  and adds it to the log file
'After that show message box saying
MessageBox.Show("Oops something crashed please try again ")
'That way you are handling both the user and developer
  End Try

'对于用户,您不希望应用程序为您作为开发人员而在他身上崩溃,您需要日志文件来跟踪错误并防止它们在您的程序的未来迭代中出现 '还在每个版本的程序集中确保您还确保您的日志文件具有发生错误时的 utc 日期时间,并包括执行此操作的用户(如果可用)

【讨论】:

  • 感谢您的建议,但我已经有了一个相当健壮的错误处理例程,它可以为异常创建一个日志文件(包括堆栈跟踪、消息详细信息和其他一些信息)我明确处理,甚至在应用程序的UnhandledException 处理程序中调用了该日志记录(如上面的代码清单所示)。然后,该处理程序将该日志数据保存到一个文本文件中,然后通过电子邮件将其发送给我。这种错误处理在大多数情况下都非常有效,但无论我尝试过什么,这些情况似乎都完全绕过了它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-18
相关资源
最近更新 更多