2011-06-17 19 views
5

Potrzebuję napisać małą aplikację w VB6, aby uruchomić instancje innej aplikacji VB6 i śledzić uruchomione procesy, ale nie mam pojęcia, jak uzyskać informacje o procesach w VB6. Widzę niektóre z potrzebnych z narzędziem tasklist, ale tak naprawdę nie wiem jak tworzyć procesy (określając proces lub nazwę aplikacji, jeśli to możliwe) i pobierając informacje o procesach z systemu operacyjnego.Monitor procesu/dyspozytora w VB6

Ta aplikacja jest uruchamiana na komputerze z systemem Windows XP.

Czy ktoś wie o samouczku z okazji rozpoczęcia lub przydatnej stronie internetowej do tego typu rzeczy?

Odpowiedz

6

Istnieje wiele funkcji Windows API, których można użyć do wykonania tej czynności. Zacznę od analizy EnumProcesses (VB6 example and declaration here), która może być wykorzystana do zebrania informacji o wszystkich uruchomionych procesach. Możesz także użyć OpenProcess , aby rozpocząć odpytywanie systemu Windows o konkretny proces (another VB6 example).

Istnieje również fairly nice example on MSDN.

I oczywiście, istnieje CreateProcess (AllApi link) lub ShellExecute (AllApi) dla procesów tarła - dawna daje większą kontrolę nad procesem tworzenia, podczas gdy druga jest znacznie prostsze połączenia.

There was another question posted about this a while back with some example code.

Innym możliwym rozwiązaniem będzie użycie WMI (some useful snippets to adapt).

Wreszcie, oto kilka samouczków, które pokazują, jak to zrobić (polecam próbuje go samodzielnie choć pierwszy :):

Oto kilka powiązanych pytań, chociaż prawdopodobnie już je widziałeś, gdy przeszukałeś tę stronę przed opublikowaniem:

3

Skoro mówisz, że inna aplikacja jest również VB6 ** **, byłoby łatwiej inną aplikację do exe ActiveX. Następnie możesz uzyskać odniesienia do obiektów w drugiej aplikacji bezpośrednio z pierwszej aplikacji. COM rozwiązuje to wszystko za Ciebie.

+0

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

2

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.

+0

, więc CreateProcess tworzy proces potomny, a następnie nie jest wolnostojący? Miałem nadzieję, że procesy będą działać, jeśli monitor/dyspozytor zawali się w bałaganie. –

+0

Połączenia rodziny procesorów w systemie Windows są zwykle dość słabe. Procesy potomne będą nadal działać, nawet jeśli rodzic zakończy działanie. – Bob77

+0

Er, powyższy komentarz mówi o ogólnym użyciu CreateProcess() lub Shell() VB. Dodany przeze mnie przykład kodu zabija swoje dzieci jawnie przy wyjściu. – Bob77

0

coś prostszego będzie używać gniazd.

Uruchom serwer aplikacji, a na kliencie implementuje komunikację z serwerem. Dzięki temu zapewnisz komunikację wewnętrzną.

dobrze mówię. bo nie będzie czego spróbować zrobić

Niestety to tylko stosuje się, jeżeli klienci są wykonywane w domu i masz możliwość dodanych zmian