C# 处理windows应用程序的结束进程

C# 处理windows应用程序的结束进程,c#,.net,event-handling,C#,.net,Event Handling,是否可以在同一windows应用程序本身中捕获windows应用程序的任务管理器结束进程?我正在使用一个C#2.0 win应用程序,我想在结束进程发生时进行一些数据库处理(将数据库中的标志从“Y”更改为“N”)。您可以做的是获取进程ID并监视进程,您可以使用HasExited属性检查进程是否结束。下面是一个快速的VB代码(对不起,我现在没有VS。这是我在另一个论坛上写的) 上面的代码启动Internetexplorer,按钮检查进程是否结束。您可以使用类似的进程来获取所有正在运行的进程,并使用p

是否可以在同一windows应用程序本身中捕获windows应用程序的任务管理器结束进程?我正在使用一个C#2.0 win应用程序,我想在结束进程发生时进行一些数据库处理(将数据库中的标志从“Y”更改为“N”)。

您可以做的是获取进程ID并监视进程,您可以使用HasExited属性检查进程是否结束。下面是一个快速的VB代码(对不起,我现在没有VS。这是我在另一个论坛上写的)


上面的代码启动Internetexplorer,按钮检查进程是否结束。您可以使用类似的进程来获取所有正在运行的进程,并使用processID。

我认为从应用程序内部不可能做到这一点。结束任务的目的是立即停止进程。这不允许执行任何清理代码


Shoban指出了实现目标的另一种方法。另一个应用程序或服务需要查找主进程。当另一个进程找不到主进程时,您可以在该点执行数据库处理。

否,无法钩住操作系统结束进程的决定。注意,这不是由任务管理器完成的,结束进程是内核的责任

在这里,您需要做两件事:

  • 将事件处理程序连接到通知应用程序退出的正常用户界面消息。使用这些事件来持久化数据、释放资源,或者以其他方式干净地退出
  • 酌情处理异常以捕获错误,并在可能的情况下清理和保存数据 这里是雷蒙德博客的三个链接,解释了为什么你不能按自己的要求去做


    此外,我还提出了一个类似的StackOverflow问题。

    稍微不同的方法如何:

    让您的应用程序在运行时每隔一段时间更新一个日期时间字段(例如LastPollDate),并设置一个单独的字段(例如“AppTerminatedNormal”),将其设置为N,如果收到表单关闭事件,则将其更改为Y

    如果通过任务管理器终止应用程序,则日期将不再更新,并且您的AppTerminatedNormal仍将为否


    通过这种方式,您可以运行一个查询,查找LastPollDate大于10分钟且AppTerminated通常为N的所有行,您将拥有所有异常终止的会话。

    您都会在这篇文章中吐痰,但接下来

    您试图以错误的级别解决问题(即,当内核终止应用程序时,在应用程序中运行代码)。真正的问题在于确保数据库正确反映其客户端应用程序的存在(或不存在)

    要解决这个问题,请避免让应用程序在用户交互之间处于“不一致状态”。换句话说,不要启动无法快速提交的事务,不要将数据写入文件,使文件处于半写或不可读状态,不要将应用程序外部的资源保持在用户交互之外的不一致状态。换句话说,如果你的应用程序没有忙于响应事件处理程序,它应该准备好立即关闭

    如果你按照上面的练习,你会发现很少有场景需要在终止之前“快速清理”。在用户单击“确定”或“保存”等的交互之外,编写良好的应用程序应该能够在即时终止后生存,而不会对其数据存储造成任何持久的损坏或损坏

    如果你必须在退出时在数据库中设置一个标志(这听起来是一种典型的用于检测用户登录的模式),那么考虑以下选项之一:

  • 定期(可能每30秒一次)在数据库中插入/更新类似时间戳的字段,以指示应用程序最近联机的时间。其他应用程序可以检查这些时间戳,以确定另一个应用程序最近联机的时间。。。如果该值在最近30秒内,则另一个应用程序仍为opnline

  • 正如Woodhenge正确建议的那样,创建一个单独的进程(理想情况下是一个服务)来监控主应用程序的状态。Windows服务可以配置为在服务出现故障时自动重新启动。然后,该监视过程将向数据库发出时间戳


  • 请注意,上述两个建议都解决了实际问题(检测应用程序是否正在访问数据库),而不会使数据库处于“不一致状态”(当应用程序实际已死亡时,上述标志为“Y”,标志应为“N”)。

    如果您的目标是Windows Vista(或更高版本)您可能对RegisterApplicationRecoveryCallback API感兴趣

    它允许您在应用程序中指定一个回调例程,该例程将在进程即将崩溃时调用。注意:它仅适用于崩溃,如果进程被故意终止,则不会自动调用它

    您可以从C#对这个API进行p/invoke(我已经这样做了),但是请记住,当您调用回调时,您的应用程序已经处于非常糟糕的状态,并且您可以对内存状态进行很少的假设。如果您有任何内存中的数据要在这个例程中使用,我会将它放在一个非常通用的静态范围中,这样您就有可能在回调例程运行时不会“整理”它


    还有一些其他有趣的API,与此相关,允许您在出现故障后自动重新启动应用程序等。

    嘿,Shoban,我可以使用您的代码捕获外部应用程序结束进程(iexplorem记事本等)。但是我应该怎么做才能在同一个应用程序(上面代码中包含Form1的那个应用程序)上捕获最终任务呢?他说,“在同一个windows应用程序中”。我不能这样做
    Public Class Form1
        Dim p As ProcessStartInfo
        Dim process As Process
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            p = New ProcessStartInfo("iexplore.exe")
            process = process.Start(p)
        End Sub
    
        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
            MsgBox(process.Id)
            If process.HasExited Then
                MsgBox("yes")
            Else
                MsgBox("no")
            End If
        End Sub
    End Class