Bạn không cần phải đi spelunking cho quá trình chỉ để có được một xử lý cho quá trình con mà bạn đẻ trứng.Hàm VB6 Shell() trả về mã số quy trình bạn có thể sử dụng để gọi OpenProcess
bằng. CreateProcess
cung cấp cho bạn xử lý trực tiếp.
Ok, đây là một ví dụ siêu tước của một chương trình trong VB6 để sinh sản và theo dõi chương trình. Ví dụ được mã hóa để bắt đầu và liên tục khởi động lại 3 bản sao của lệnh shell (chương trình con mẫu nhỏ). Nó cũng được viết để giết bất kỳ trẻ em đang chạy khi nó được chấm dứt, và có lựa chọn thay thế tốt hơn để sử dụng trong nhiều trường hợp. Xem A Safer Alternative to TerminateProcess().
Bản trình diễn này cũng báo cáo lại mã thoát của mỗi quá trình thoát. Bạn có thể nhập exit 1234
hoặc somesuch để xem điều này hoạt động.
Để tạo bản trình diễn, hãy mở Dự án VB6 mới bằng Biểu mẫu. Thêm một Hộp văn bản nhiều dòng Text1
và Bộ hẹn giờ Timer1
(được sử dụng để thăm dò ý kiến trẻ em để hoàn thành). Dán mã này vào Biểu mẫu:
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
Hy vọng điều này sẽ giúp trả lời câu hỏi.
Kỹ thuật này chắc chắn có ứng dụng của nó và tôi muốn đề nghị nó như là một khả năng bản thân mình đối với các loại ceratin mới. Tuy nhiên nó không giúp ích nhiều nếu các chương trình con không được viết bởi bạn, và thậm chí sau đó nó có thể yêu cầu khá nhiều viết lại. Nó cũng đòi hỏi quá trình đăng ký COM có thể là một nhược điểm trong nhiều kịch bản. – Bob77