Как создать функцию, которая может ожидать завершения нескольких процессов? - PullRequest
1 голос
/ 30 апреля 2019

Я создаю службу Windows, которая запишет все время начала и время завершения для конкретного процесса, который я хотел отслеживать. Проблема в том, что когда я пытаюсь отслеживать процесс, ожидая выхода, я понятия не имею, как ждать завершения нескольких процессов. Ниже приведен мой код для написания времени начала процесса.

Try
    Using regkey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64).OpenSubKey("SOFTWARE\MonitoringApplication\Login", RegistryKeyPermissionCheck.Default)
        childrenID = regkey.GetValue("Login User").ToString
    End Using
    If childrenID.Equals("admin") Then
    Else
        Dim connection As New SqlConnection("Server=DESKTOP-FTJ3EOA\SQLEXPRESS;Initial Catalog=MonitorDB;User ID = admin; Password = admin")
        Dim command As New SqlCommand("SELECT  App.ApplicationName FROM App INNER JOIN ChildrenApplication ON App.ApplicationID = ChildrenApplication.ApplicationID WHERE ChildrenID = @a", connection)
        command.Parameters.Add("@a", SqlDbType.VarChar).Value = childrenID
        Dim adapter As New SqlDataAdapter(command)
        Dim table As New DataTable()
        adapter.Fill(table)

        Using sw As StreamWriter = New StreamWriter(AppDomain.CurrentDomain.BaseDirectory + "\MonitoringApplication.txt", True)

            For Each row As DataRow In table.Rows
                p = Process.GetProcessesByName(row.Item(0))
                Using myprocess = New Process
                    If p.Count > 0 Then
                        myprocess.StartInfo.FileName = row.Item(0)
                        myprocess.EnableRaisingEvents = True
                        sw.WriteLine(row.Item(0) + "running")

                    End If
                End Using
            Next row
        End Using

        Const SLEEP_AMOUNT As Integer = 100
        Do While Not eventHandled
            elapsedTime += SLEEP_AMOUNT
            If elapsedTime > 30000 Then
                Exit Do
            End If
            Thread.Sleep(SLEEP_AMOUNT)
        Loop
    End If
Catch ex As Exception
    Using sw As StreamWriter = New StreamWriter(AppDomain.CurrentDomain.BaseDirectory + "\MonitoringApplication.txt", True)
        sw.WriteLine(ex)
    End Using
End Try

Private Sub myProcess_Exited(ByVal sender As Object, ByVal e As System.EventArgs) Handles myProcess.Exited
    eventHandled = True
    Using sw As StreamWriter = New StreamWriter(AppDomain.CurrentDomain.BaseDirectory + "\MonitoringApplication.txt", True)
        sw.WriteLine("Exited")
    End Using
End Sub

Есть ли способы контролировать несколько процессов для выхода? Заранее спасибо.

1 Ответ

0 голосов
/ 30 апреля 2019

Теперь вы используете Process.GetProcessesByName () для получения массива запущенных процессов, если таковые имеются.
Вы можете использовать возвращенный массив процессов и подписаться на событие Exited каждого из них, чтобы регистрировать время выхода любого из процессов в массиве.

Настройка EnableRaisingEvent необходима для вызова события Exited, но вам также необходимо подписаться на событие, используя AddHandler вместе с адресом метода или лямбда-выражения:

AddHandler [Process].Exited, AddressOf [Handler]
' or 
AddHandler [Process].Exited, Sub() [Lambda]

Этот метод принимает имя процесса и путь к файлу, в котором хранится имя процесса и время его выхода при возникновении события Exited.

Если ваш текущий цикл:

For Each row As DataRow In table.Rows
    '(...)
Next

Вы можете вставить вызов этому методу:

For Each row As DataRow In table.Rows
    SubscribeProcExit(row.Item(0), Path.Combine(Application.StartupPath, "MonitoringApplication.txt"))
Next

Если файл журнала не завершается, он будет создан, и каждый раз при выходе из одного из процессов будет добавляться новая строка, в которую будут записываться Process.ProcessName и Process.ExitTime.
Обратите внимание, что row.Item(0) должно содержать понятное имя Процесса. Например, notepad.exe должен указываться как просто "notepad".

Private Sub SubscribeProcExit(processName As String, fileName As String)
    Dim processes As Process() = Process.GetProcessesByName(processName)
    If processes.Length = 0 Then Return
    For Each p As Process In processes
        p.EnableRaisingEvents = True
        AddHandler p.Exited,
            Sub()
                Using sw As StreamWriter = File.AppendText(fileName)
                    sw.WriteLine($"Process: {p?.ProcessName}, Exit Time: {p?.ExitTime}")
                    p?.Dispose()
                End Using
            End Sub
    Next
End Sub
...