1

我正在使用以下代码来了解如何在进程处于活动状态时等待进程结束。
在我的代码中,就在记事本打开时,我看到了 MessageBox。

如何等到记事本关闭,而不让我的表单无响应?

Public Class Form1
    Private Const WAIT_INFINITE = -1&
    Private Const SYNCHRONIZE = &H100000

    Private Declare Function OpenProcess Lib "kernel32" _
  (ByVal dwDesiredAccess As Long,
   ByVal bInheritHandle As Long,
   ByVal dwProcessId As Long) As Long

    Private Declare Function WaitForSingleObject Lib "kernel32" _
  (ByVal hHandle As Long,
   ByVal dwMilliseconds As Long) As Long

    Private Declare Function CloseHandle Lib "kernel32" _
  (ByVal hObject As Long) As Long

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim hProcess As Long
        Dim taskId As Long
        Dim cmdline As String

        cmdline = "notepad.exe"
        taskId = Shell(cmdline, vbNormalFocus)

        hProcess = OpenProcess(SYNCHRONIZE, True, taskId)
        Call WaitForSingleObject(hProcess, WAIT_INFINITE)
        CloseHandle(hProcess)

        MsgBox ("The shelled app has ended.")
    End Sub
End Class
4

2 回答 2

2

在 .Net Framework / .Net Core 中,您可以使用WaitForExit的异步事件驱动版本,订阅Exited事件,该事件在您启动的进程终止时引发。

注意:该事件在 ThreadPool 线程中引发。您可以将Process.SynchronizingObject设置为当前 Form 实例,以将事件编组到 UI 线程。

在 .Net Framework 中,将[Process].StartInfo.UseShellExecute设置为False,因为默认值为True.
在 .Net Core 中,默认值已经是False.

引发事件时,进程已经退出(HasExitedTrue),因此并非所有常用信息都可用。(ProcessStartInfoProcess.StartInfo对象)是可访问的,当然还有ExitTime和其他值(在引发事件时检查 Process 对象)。

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim p = New Process()
    p.StartInfo.FileName = "notepad.exe"
    p.StartInfo.UseShellExecute = False
    p.SynchronizingObject = Me
    p.EnableRaisingEvents = True
    AddHandler p.Exited,
        Sub()
            Dim processName = p.StartInfo.FileName
            Dim exitTime = p.ExitTime
            p?.Dispose()
            MessageBox.Show("Process exited")
            DoSomethingElseRelated(processName, exitTime)
        End Sub
    p.Start()
End Sub
于 2021-04-24T11:20:54.970 回答
1

最简单的 WaitForExitAsync 看起来像:

Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim p = Process.Start("notepad.exe")
    Await p.WaitForExitAsync()
    MsgBox ("The shelled app has ended.")
End Sub
于 2021-04-24T08:43:56.843 回答