Nie trzeba iść spelunking procesów tak aby uzyskać uchwyt do procesów potomnych, które odradzania.Funkcja VB6 Shell() zwraca Identyfikator procesu, którego można użyć do wywołania OpenProcess
za pomocą. CreateProcess
daje uchwyt bezpośrednio.
OK, oto superpasowany przykład programu w VB6 do odradzania i monitorowania programów. Przykład jest kodowany w celu uruchomienia i wielokrotnego restartowania 3 kopii powłoki poleceń (trywialny przykładowy program potomny). Jest również napisany, aby zabić wszystkie działające dzieci, gdy zostanie zakończony, i istnieją lepsze alternatywy do użycia w większości przypadków. Zobacz A Safer Alternative to TerminateProcess().
To demo również zgłasza kod wyjścia każdego procesu, który został zamknięty. Możesz wpisać exit 1234
lub kliknąć, aby zobaczyć to w akcji.
Aby utworzyć prezentację, otwórz nowy projekt VB6 za pomocą formularza. Dodaj wieloliniowy TextBox Text1
i Timer Timer1
(który służy do odpytywania dzieci do ukończenia). Wklej ten kod do formularza:
Option Explicit
Private Const SYNCHRONIZE = &H100000
Private Const PROCESS_QUERY_INFORMATION = &H400&
Private Const PROCESS_TERMINATE = &H1&
Private Const WAIT_OBJECT_0 = 0
Private Const INVALID_HANDLE = -1
Private Const DEAD_HANDLE = -2
Private Declare Function CloseHandle Lib "kernel32" (_
ByVal hObject As Long) As Long
Private Declare Function GetExitCodeProcess Lib "kernel32" (_
ByVal hProcess As Long, _
ByRef lpExitCode As Long) As Long
Private Declare Function OpenProcess Lib "kernel32" (_
ByVal dwDesiredAccess As Long, _
ByVal bInheritHandle As Long, _
ByVal dwProcessId As Long) As Long
Private Declare Function TerminateProcess Lib "kernel32" (_
ByVal hProcess As Long, _
ByVal uExitCode As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" (_
ByVal hHandle As Long, _
ByVal dwMilliseconds As Long) As Long
Private Tasks() As String
Private Handles() As Long
Private Sub Form_Load()
Dim I As Integer
'We'll run 3 copies of the command shell as an example.
ReDim Tasks(2)
ReDim Handles(2)
For I = 0 To 2
Tasks(I) = Environ$("COMSPEC") & " /k ""@ECHO I am #" & CStr(I) & """"
Handles(I) = INVALID_HANDLE
Next
Timer1.Interval = 100
Timer1.Enabled = True
End Sub
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
Dim I As Integer
Timer1.Enabled = False
DoEvents
For I = 0 To UBound(Tasks)
If Handles(I) <> INVALID_HANDLE And Handles(I) <> DEAD_HANDLE Then
TerminateProcess Handles(I), 666
CloseHandle Handles(I)
Handles(I) = DEAD_HANDLE
End If
Next
End Sub
Private Sub Timer1_Timer()
Dim I As Integer
Dim ExitCode As Long
Dim Pid As Long
Timer1.Enabled = False
For I = 0 To UBound(Tasks)
If Handles(I) <> INVALID_HANDLE Then
If WaitForSingleObject(Handles(I), 0) = WAIT_OBJECT_0 Then
If GetExitCodeProcess(Handles(I), ExitCode) <> 0 Then
Text1.SelText = "Task " & CStr(I) & " terminated, " _
& "exit code: " & CStr(ExitCode) _
& ", restarting task." _
& vbNewLine
Else
Text1.SelText = "Task " & CStr(I) & " terminated, " _
& "failed to retrieve exit code, error " _
& CStr(Err.LastDllError) _
& ", restarting task." _
& vbNewLine
End If
CloseHandle Handles(I)
Handles(I) = INVALID_HANDLE
End If
End If
If Handles(I) = INVALID_HANDLE Then
Pid = Shell(Tasks(I), vbNormalFocus)
If Pid <> 0 Then
Handles(I) = OpenProcess(SYNCHRONIZE _
Or PROCESS_QUERY_INFORMATION _
Or PROCESS_TERMINATE, 0, Pid)
If Handles(I) <> 0 Then
Text1.SelText = "Task " & CStr(I) & " started." _
& vbNewLine
Else
Text1.SelText = "Task " & CStr(I) _
& ", failed to open child process." _
& vbNewLine
Handles(I) = DEAD_HANDLE
End If
Else
Text1.SelText = "Task " & CStr(I) _
& ", failed to Shell child process." _
& vbNewLine
Handles(I) = DEAD_HANDLE
End If
End If
Next
Timer1.Enabled = True
End Sub
Mamy nadzieję, że pomoże to w rozwiązaniu tego problemu.
Technika ta z pewnością ma swoje aplikacje i sugeruję go jako jedną z możliwości sobie dla nowych rodzajów pracy. Jednak niewiele pomoże, jeśli programy dla dzieci nie zostały napisane przez ciebie, a nawet wtedy może wymagać sporo przepisywania. Wymaga to również rejestracji procesowej COM, co może być wadą wielu scenariuszy. – Bob77