VB6: Starten, Auslesen & Beenden einer .exe

Hallo Experten,
ich bin neu im Forum und habe sofort eine umfangreiche Frage:

Ich möchte eine VB6-Anwendung schreiben, die das Programm
„wspice3.exe“ mit der Datei „test.cir“ startet.
(wspice3 ist ein Simulationsprogramm, das die Netzliste test.cir einer elektronischen Schaltung einliest und eine Analyse ausgibt. Meine VB6-Anwendung soll ein Editor für die *.cir werden)

wspice erzeugt in der standalone-Version eine unix-shell ähnliche Oberfläche. Diese will ich aber nicht sehen, sondern nur die plain-text Ausgaben am Prompt in meine VB6-Anwendung übernehmen. Bei grafischer Ausgabe (z.B. Frequenzkennlinie) wird über dieses Textfenster noch ein kleines Grafikfenster gelegt, das zusätzlich in der Taskleiste erscheint und separat geschlossen werden kann.

Soweit bin ich heute schon: Ich starte ich die Anwendung mit

taskId = shell („wspice3.exe test.cir“, vbMinimizedFocus)

Das Grafikfenster sehe ich. Das Textfenster ist natürlich nur Taskleiste.

Wenn ich das Grafikfenster schließe, kann ich den ganzen Task beenden, indem ich „ALT F4“ sende. Dazu erhält die TaskID zuvor den Fokus:

AppActivate taskId, True
SendKeys „%{F4}“, True

So, nun meine Fragen:

  1. Wie lese ich den Text aus dem Textfenster aus?
  2. Wie kann ich abfragen, ob die taskID noch in Arbeit oder schon fertig ist? (wenn die Simulation z.B. länger dauert)
  3. Wie kann ich abfragen, ob zur taskId überhaupt noch der Task existiert? (das gibt sonst eine Fehlermeldung beim AppActivate)

mfg
KPS

läuft der Prozess noch?
Hallo Klaus-Peter,
ziemlich schwierige Fragen hast Du auf Lager :smile:

  1. Wie kann ich abfragen, ob zur taskId überhaupt noch der
    Task existiert? (das gibt sonst eine Fehlermeldung beim
    AppActivate)

mit diesem Aufruf

 ' Prozess starten
 id = Shell("notepad.exe", vbMinimizedNoFocus)
 ' läuft er noch?
 ' findet das erste notpad (wenn 2 oder mehr laufen, ev. das falsche)
 If ProcessRunningID(id) Then MsgBox "ja"

dazu brauchst Du allerdings folgende Function :wink:

Private Function ProcessRunningID(ByVal id As String) As Boolean

Dim hSnapShot As Long, uProcess As PROCESSENTRY32, retval As Long

 hSnapShot = CreateToolhelpSnapshot(TH32CS\_SNAPPROCESS, 0&amp:wink:
 If hSnapShot = 0 Then Exit Function

 uProcess.dwSize = Len(uProcess)
 retval = ProcessFirst(hSnapShot, uProcess)
 
 Do While retval 0
 If uProcess.th32ProcessID = id Then
 ProcessRunningID = True
 Exit Function
 End If
 retval = ProcessNext(hSnapShot, uProcess)
 Loop

Call CloseHandle(hSnapShot)

End Function

und die wieder braucht folgende API-Deklarationen

Private Const TH32CS\_SNAPPROCESS As Long = 2&
Private Const MAX\_PATH As Integer = 260
 
Private Type PROCESSENTRY32
 dwSize As Long
 cntUsage As Long
 th32ProcessID As Long
 th32DefaultHeapID As Long
 th32ModuleID As Long
 cntThreads As Long
 th32ParentProcessID As Long
 pcPriClassBase As Long
 dwFlags As Long
 szExeFile As String \* MAX\_PATH
End Type

Private Declare Function CreateToolhelpSnapshot Lib "Kernel32" \_
 Alias "CreateToolhelp32Snapshot" (ByVal lFlags As Long, \_
 ByVal lProcessID As Long) As Long
Private Declare Function ProcessFirst Lib "Kernel32" Alias \_
 "Process32First" (ByVal hSnapShot As Long, uProcess As PROCESSENTRY32) As Long
Private Declare Function ProcessNext Lib "Kernel32" Alias \_
 "Process32Next" (ByVal hSnapShot As Long, uProcess As PROCESSENTRY32) As Long
Private Declare Sub CloseHandle Lib "Kernel32" (ByVal hPass As Long)

Textfenster auslesen
hier der nächste Teil am Beispiel von Notepad

 ' zuerst das Notepad Window-Handle
 hwnd = FindWindow("notepad", "Unbenannt - Editor")




 ' der Text steht im ersten Childwindow von obigem Notepad
 ' ob das bei dir auch so ist ???
 hwnd2 = FindWindowEx(hwnd, 0&, "edit", "")
 text$ = ReadText(hwnd2)


Private Function ReadText$(ByVal hwnd&amp:wink:
Dim i&, retval#, zahl&, puffer$

 retval = SendMessageByLong(hwnd, WM\_GETTEXTLENGTH, 0, 0)
 If retval \> 0 Then
 zahl = IIf(retval \> 1000, 1000, retval + 1)
 puffer = String$(zahl, 0)
 retval = SendMessageByString(hwnd, WM\_GETTEXT, zahl, puffer)
 Else
 puffer = ""
 End If

 i = InStr(puffer, Chr$(0))
 If i \> 0 Then
 puffer = Left$(puffer, i - 1)
 End If

 ReadText = puffer
End Function

benötigt folgende API-Deklarationen:

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" \_
 (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" \_
 (ByVal hWnd1 As Long, ByVal hwnd2 As Long, ByVal lpsz1 As String, \_
 ByVal lpsz2 As String) As Long
Private Declare Function SendMessageByLong& Lib "user32" Alias "SendMessageA" \_
 (ByVal hwnd&, ByVal wMsg&, ByVal wParam&, ByVal lParam&amp:wink:
Private Declare Function SendMessageByString& Lib "user32" Alias "SendMessageA" \_
 (ByVal hwnd&, ByVal wMsg&, ByVal wParam&, ByVal lParam$)

Private Const WM\_GETTEXTLENGTH = &HE
Private Const WM\_GETTEXT = &HD

Ziemlich viel - Teil 1: Prozess fertig?
Hallo,
damit hast Du ja ganz schön was vor;
ich habe das Szenario am Notepad durchprobiert und unten meine Ergebnisse für Deine Fragen gepostet.

Hat eine Menge mit API-Calls zu tun

Du brauchst außerdem die Fensterklasse Deiner Anwendung, die muß registriert sein, wenn Du die Software installiert hast müßte sie das auch sein.

Ad: Feststellen ob Task fertig
Das könnte nur gehen, wenn in deinem Textfenster eine eindeutige READY-Meldung (Fertig/All Tasks completed oderwasweisich) ausgegeben würde. Dann könntest Du timergesteuert nach diesem Text suchen. Sonst fällt mir da auch nichts ein.

Wenn ich Dich zusehr verwirrt habe mail an mich :smile: das ist doch ein ziemlich umfangreiches Thema