Code-Beispiel
Nutzung des Windows - Message - Systems zur Datenübertragung
Lizenz: | Erster Autor: | Letzte Bearbeitung: |
WTFPL | grindstone | 18.11.2014 |
Neben Pipes und Filemapping besteht auch die Möglichkeit, das Message - System von Windows zu benutzen, um Daten zwischen verschiedenen Prozessen auszutauschen. Der Vorteil ist, daß sich das Betriebssystem weitgehend um die Verteilung und Synchronisation der Daten kümmert, so daß man sich über Threadsicherheit keine Gedanken machen muß.
Für einen Datenaustausch muß neben dem Einbinden der Sende-/Empfangsroutinen lediglich senderseitig die ThreadID des Empfängerthreads bekannt sein.
Zunächst einmal die Sende-/Empfangsroutinen:
msg_se.bi:
#Include Once "windows.bi"
Sub stringSenden(threadId As Integer, text As String)
Dim As Integer tp = 0 'pointer auf test
Do While tp < Len(text) - 7 'verbleibender text ist >= 8 zeichen
PostThreadMessage(threadId, WM_USER+1, _
Cvi(Chr(text[tp],text[tp + 1],text[tp + 2],text[tp + 3])), _
Cvi(Chr(text[tp + 4],text[tp + 5],text[tp + 6],text[tp + 7]))) '8 zeichen senden
tp += 8 'pointer setzen
Loop
Do While tp < Len(text) - 3 'verbleibender text ist >= 4 zeichen
PostThreadMessage(threadId, WM_USER+2, _
Cvi(Chr(text[tp],text[tp + 1],text[tp + 2],text[tp + 3])), Cvi(Chr(0,0,0,4))) '4 zeichen senden
tp += 4 'pointer setzen
Loop
'restliche zeichen und endekennzeichen senden
PostThreadMessage(threadId, WM_USER+2, Cvi(Right(Chr(0,0,0,0) + Mid(text,tp + 1),4)),Cvi(Chr(0,0,1,Len(text) - tp)))
End Sub
Function stringEmpfangen(timeout As UInteger) As String
Dim As Double zeit = Timer + timeout / 1000
Dim As String text = "", g
Dim As MSG nachricht
Do 'endlosschleife
Do While PeekMessage(@nachricht,NULL,0,0,PM_NOREMOVE) = 0 'keine nachricht
If Timer > zeit Then 'timeout
Return text
EndIf
Sleep 1
Loop
GetMessage(@nachricht,NULL,0,0) 'nachricht holen
With nachricht
Select Case .message
Case WM_USER+1 'text übertragen (8 zeichen)
text += Mki(.wparam) + Mki(.lparam)
Case WM_USER+2 'text übertragen (0 bis 4 zeichen)
g = Mki(.lparam) 'niederwertigstes byte enthält die anzahl der zeichen
text += Right(Mki(.wparam),g[3]) 'angegebene anzahl von zeichen an den text anhängen
Select Case g[2] 'vorletztes byte enthält ein steuerzeichen
Case 1 'textübertragung beendet
Return text
End Select
End Select
End With
Loop
End Function
Und zwei Programme als Anwendungsbeispiel:
Der Elternprozess msg_parent:
#Include "windows.bi"
#Include "msg_se.bi"
Dim As HWND hWndChild, hWndDiesesFenster
Dim As Integer threadId
Dim As String message, antwort
hWndDiesesFenster = GetConsoleWindow() 'fensterhandle ermitteln
SetWindowText(hWndDiesesFenster,"Sender") 'fenstertitel setzen zur identifizierung
Shell "start " + ExePath + "\msg_child.exe" 'kindprogramm starten
Do
hWndChild = FindWindow(0,"Empfaenger")
Sleep 1
Loop Until hWndChild 'warten, bis kindprozess läuft
threadId = GetWindowThreadProcessId(hWndChild,0) 'thread - ID des kindprozesses ermitteln
SetForegroundWindow(hWndDiesesFenster) 'elternprogramm in den Vordergrund holen
Do
Input "Nachricht ";message
stringSenden(threadID,message) 'nachricht an kindprozess schicken
If message = "quit" Then 'programm beenden
End
EndIf
antwort = stringEmpfangen(INFINITE) 'antwort von kindprozess holen (timeout 1 sekunde)
Print antwort 'antwort ausgeben
Print
Loop
Der Kindprozess msg_child:
#Include "windows.bi"
#Include "msg_se.bi"
Dim As HWND hWndParent, hWndDiesesFenster
Dim As String text
Dim As Integer threadId
hWndDiesesFenster = GetConsoleWindow() 'fensterhandle ermitteln
SetWindowText(hWndDiesesFenster,"Empfaenger") 'fenstertitel setzen zur identifizierung
ShowWindow(hWndDiesesFenster,SW_HIDE) 'fenster unsichtbar machen
hWndParent = FindWindow(0,"Sender") 'fensterhandle des elternprozesses ermitteln
threadId = GetWindowThreadProcessId(hWndParent,0) 'thread - ID des elternprozesses ermitteln
Do
text = stringEmpfangen(-1) 'gesendeten text holen
If text <> "" Then
If text = "quit" Then 'programm beenden
End
EndIf
stringSenden(threadId,"ECHO " + text) 'text als echo zurückschicken
text = ""
EndIf
Loop
Vor dem Start von msg_parent muß msg_child kompiliert und im selben Verzeichnis wie msg_parent abgelegt werden.
Die Eingaben von msg_parent werden über die Message-queue an msg_child und von dort mit dem Präfix "ECHO " versehen wieder zurückgeschickt.
Wenn ein in der Message-queue befindlicher Text sicher erkannt werden soll, sollte der Timeout-Wert von stringEmpfangen nicht kleiner sein als 100. Ein Timeout-Wert von -1 oder "INFINITE" bedeutet "kein Timeout".
Zusätzliche Informationen und Funktionen | |||||||
---|---|---|---|---|---|---|---|
|
|