Kommunikation zwischen 2 Scripten

  • Wie tausche ich Variablen / Strings zwischen 2 Scripten aus

    Da die Frage immer wieder mal gestellt wird, hab ich mal 2 Beispiele geschrieben

    Beispiel 1
    Hier wird vom Hauptscript ein zweites Script (EXE) gestartet und dann via StdIn / StdOut Daten ausgetauscht.

    Vorteile:
    Benötigt kein GUI.
    Zielscript kann quasi nicht verwechselt werden (siehe Nachteile Beispiel 2)

    Nachteile:
    Empfänger muß ständig auf neue Daten prüfen.
    Script2.exe MUSS von Script1 aus via Run gestartet werden.

    Script_1.au3:

    Spoiler anzeigen
    [autoit]

    #include <Constants.au3>
    #include <GUIConstantsEx.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Global $hPid = 0, $sStdOut = ""

    [/autoit] [autoit][/autoit] [autoit]

    $hGui = GUICreate("Script 1", 200, 225, @DesktopWidth / 2 - 250, @DesktopHeight / 2 - 112)
    $hEdit = GUICtrlCreateEdit("Script 1 Test Text", 10, 10, 180, 150)
    $hButtonStart = GUICtrlCreateButton("Start Script 2", 10, 170, 85, 20)
    $hButtonStop = GUICtrlCreateButton("Stop Script 2", 105, 170, 85, 20)
    $hButtonSend = GUICtrlCreateButton("Send Edit to Script 2", 10, 195, 180, 20)
    GUISetState()

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    $msg = GUIGetMsg()
    Switch $msg
    Case $GUI_EVENT_CLOSE
    If $hPid Then ProcessClose($hPid)
    Exit
    Case $hButtonStart
    $hPid = Run(@ScriptDir & "\Script_2.exe", @ScriptDir, @SW_SHOW, BitOR($STDIN_CHILD, $STDOUT_CHILD))
    Case $hButtonStop
    ProcessClose($hPid)
    $hPid = 0
    Case $hButtonSend
    StdinWrite($hPid, GUICtrlRead($hEdit))
    EndSwitch
    If $hPid Then
    $sStdOut = StdoutRead($hPid)
    If @error Then $hPid = 0
    If $sStdOut Then GUICtrlSetData($hEdit, $sStdOut)
    EndIf
    WEnd

    [/autoit]

    Script_2.au3:

    Spoiler anzeigen
    [autoit]

    #include <GUIConstantsEx.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Global $sStdIn = ""

    [/autoit] [autoit][/autoit] [autoit]

    $hGui = GUICreate("Script 2", 200, 225, @DesktopWidth / 2 + 50, @DesktopHeight / 2 - 112)
    $hEdit = GUICtrlCreateEdit("Script 2 Test Text", 10, 10, 180, 175)
    $hButtonSend = GUICtrlCreateButton("Send Edit to Script 1", 10, 195, 180, 20)
    GUISetState()

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    $msg = GUIGetMsg()
    Switch $msg
    Case $GUI_EVENT_CLOSE
    Exit
    Case $hButtonSend
    ConsoleWrite(GUICtrlRead($hEdit))
    EndSwitch
    $sStdIn = ConsoleRead()
    If $sStdIn Then GUICtrlSetData($hEdit, $sStdIn)
    WEnd

    [/autoit]


    Beispiel 2
    Datenaustausch via SendMessage

    Vorteile:
    Der Empfänger muß nicht ständig auf neue Daten überprüfen.
    Die Scripte können unabhängig voneinader gestartet werden.

    Nachteile:
    Setzt ein GUI voraus.
    Das Zielscript wird über WinTitle definiert, d.h. wenn mehrere Fenster mit dem gleichen Title existieren, dann kann es zu Verwechsulngen kommen. (Also eindeutige Fentertitel wählen)

    Script_1.au3:

    Spoiler anzeigen
    [autoit]

    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $hGui = GUICreate("Script 1", 200, 225, @DesktopWidth / 2 - 250, @DesktopHeight / 2 - 112)
    $hEdit = GUICtrlCreateEdit("Script 1 Test Text", 10, 10, 180, 175)
    $hButtonSend = GUICtrlCreateButton("Send Edit to Script 2", 10, 195, 180, 20)
    GUISetState()

    [/autoit] [autoit][/autoit] [autoit]

    GUIRegisterMsg($WM_COPYDATA, '_MY_WM_COPYDATA')

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    $msg = GUIGetMsg()
    Switch $msg
    Case $GUI_EVENT_CLOSE
    Exit
    Case $hButtonSend
    _SendCopyDataString($hGui, WinGetHandle("Script 2"), GUICtrlRead($hEdit))
    EndSwitch
    WEnd

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _SendCopyDataString($My_Hwnd, $Scite_hwnd, $sCmd) ; by Prog@ndy
    Local $CmdStruct = DllStructCreate('Char[' & StringLen($sCmd) + 1 & ']')
    DllStructSetData($CmdStruct, 1, $sCmd)
    Local $COPYDATA = DllStructCreate('Ptr;DWord;Ptr')
    DllStructSetData($COPYDATA, 1, 1)
    DllStructSetData($COPYDATA, 2, StringLen($sCmd) + 1)
    DllStructSetData($COPYDATA, 3, DllStructGetPtr($CmdStruct))
    DllCall('User32.dll', 'None', 'SendMessage', 'HWnd', $Scite_hwnd, 'Int', $WM_COPYDATA, 'HWnd', $My_Hwnd, 'Ptr', DllStructGetPtr($COPYDATA))
    EndFunc ;==>_SendCopyDataString

    [/autoit] [autoit][/autoit] [autoit]

    Func _MY_WM_COPYDATA($hWnd, $msg, $wParam, $lParam) ; by Prog@ndy
    Local $Temp = ""
    Local $COPYDATA = DllStructCreate('Ptr;DWord;Ptr', $lParam)
    Local $COPYDATA_StringLen = DllStructGetData($COPYDATA, 2)
    Local $CmdStruct = DllStructCreate('Char[' & $COPYDATA_StringLen & ']', DllStructGetData($COPYDATA, 3))
    $COPYDATA_String = StringLeft(DllStructGetData($CmdStruct, 1), $COPYDATA_StringLen)
    GUICtrlSetData($hEdit, $COPYDATA_String)
    EndFunc ;==>_MY_WM_COPYDATA

    [/autoit]

    Script_2.au3:

    Spoiler anzeigen
    [autoit]

    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $hGui = GUICreate("Script 2", 200, 225, @DesktopWidth / 2 + 50, @DesktopHeight / 2 - 112)
    $hEdit = GUICtrlCreateEdit("Script 2 Test Text", 10, 10, 180, 175)
    $hButtonSend = GUICtrlCreateButton("Send Edit to Script 1", 10, 195, 180, 20)
    GUISetState()

    [/autoit] [autoit][/autoit] [autoit]

    GUIRegisterMsg($WM_COPYDATA, '_MY_WM_COPYDATA')

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    $msg = GUIGetMsg()
    Switch $msg
    Case $GUI_EVENT_CLOSE
    Exit
    Case $hButtonSend
    _SendCopyDataString($hGui, WinGetHandle("Script 1"), GUICtrlRead($hEdit))
    EndSwitch
    WEnd

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _SendCopyDataString($My_Hwnd, $Scite_hwnd, $sCmd) ; by Prog@ndy
    Local $CmdStruct = DllStructCreate('Char[' & StringLen($sCmd) + 1 & ']')
    DllStructSetData($CmdStruct, 1, $sCmd)
    Local $COPYDATA = DllStructCreate('Ptr;DWord;Ptr')
    DllStructSetData($COPYDATA, 1, 1)
    DllStructSetData($COPYDATA, 2, StringLen($sCmd) + 1)
    DllStructSetData($COPYDATA, 3, DllStructGetPtr($CmdStruct))
    DllCall('User32.dll', 'None', 'SendMessage', 'HWnd', $Scite_hwnd, 'Int', $WM_COPYDATA, 'HWnd', $My_Hwnd, 'Ptr', DllStructGetPtr($COPYDATA))
    EndFunc ;==>_SendCopyDataString

    [/autoit] [autoit][/autoit] [autoit]

    Func _MY_WM_COPYDATA($hWnd, $msg, $wParam, $lParam) ; by Prog@ndy
    Local $Temp = ""
    Local $COPYDATA = DllStructCreate('Ptr;DWord;Ptr', $lParam)
    Local $COPYDATA_StringLen = DllStructGetData($COPYDATA, 2)
    Local $CmdStruct = DllStructCreate('Char[' & $COPYDATA_StringLen & ']', DllStructGetData($COPYDATA, 3))
    $COPYDATA_String = StringLeft(DllStructGetData($CmdStruct, 1), $COPYDATA_StringLen)
    GUICtrlSetData($hEdit, $COPYDATA_String)
    EndFunc ;==>_MY_WM_COPYDATA

    [/autoit]


    Eigentlich werden bei beiden Beispielen nur Strings übertragen.
    Um nun tatsächlich Variablen zu senden, könnte man mit DllStructCreate ein Struct erstellen und den Pointer mit oben genannten Methoden verschicken...
    Bei Bedarf kann ich auch hierfür ein Beispielscript schreiben!

    Viel Erfolg
    E

  • Es ginge auch noch über den Arbeitsspeicher, eins schreibt was rein, das andere liest wieder

    mfg

    Edit1: Juhu 500. Beitrag xD

    Computers are like Airconditioning. They don´t work with open Windows.

  • Super Tut

    Eigentlich werden bei beiden Beispielen nur Strings übertragen.
    Um nun tatsächlich Variablen zu senden, könnte man mit DllStructCreate ein Struct erstellen und den Pointer mit oben genannten Methoden verschicken...
    Bei Bedarf kann ich auch hierfür ein Beispielscript schreiben!

    Bei mir ist Bedarf vorhanden :rolleyes:

    Spoiler anzeigen

    Grundkenntnisse in: C++, JavaScript
    Sehr gute Kenntnisse: PHP, JAVA, C und näturlich AutoIt


    Klaviatur, Anhang UDF, GDI+ Mühle

    Zitat

    "Wenn einen um 20h der Pizzadienst anruft und fragt, ob man's nur vergessen hat und ob man das gleiche
    möchte wie immer -- dann sollte man sein Bestellverhalten evtl überdenken"

  • Es ginge auch noch über den Arbeitsspeicher, eins schreibt was rein, das andere liest wieder

    mfg

    Edit1: Juhu 500. Beitrag xD


    Sorry, dass ich den Thread wieder ausgrabe, doch mich würde dazu ein (einfaches) Beispiel wundernehmen.
    Ist jemand in der Lage übers RAM Daten zwischen zwei unabhängig voneinander gestarteten Programmen auszutauschen?

    Lg, Veronesi

  • Ich denke selbiges ist etwas schwerer, da wir hier "nur" eine Interpretersprache haben wo man keine festen Variablen hat ...

    Es gibt sehr viele Leute, die glauben. Aber aus Aberglauben.
    - Blaise Pascal

  • Hallo nochmals ich :)

    Ich habe mir den Scriptteil von Prog@ndy nochmals angeschaut.
    Warum kann man das nicht einfacher lösen, so wie ich das gemacht habe?
    Klar meine Lösung funktioniert nicht :) Aber wieso?

    Danke für Eure Input

    Spoiler anzeigen
    [autoit]

    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>
    Global $WM_APP = 0x8000

    [/autoit] [autoit][/autoit] [autoit]

    $hGui = GUICreate("Script 1", 200, 225, @DesktopWidth / 2 - 250, @DesktopHeight / 2 - 112)
    $hEdit = GUICtrlCreateEdit("Script 1 Test Text", 10, 10, 180, 175)
    $hButtonSend = GUICtrlCreateButton("Send Edit to Script 2", 10, 195, 180, 20)
    GUISetState()

    [/autoit] [autoit][/autoit] [autoit]

    GUIRegisterMsg($WM_APP, '_MY_WM_APP')

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    $msg = GUIGetMsg()
    Switch $msg
    Case $GUI_EVENT_CLOSE
    Exit
    Case $hButtonSend
    _SendCopyDataString($hGui, WinGetHandle("Script 2"), GUICtrlRead($hEdit))
    EndSwitch
    WEnd

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _SendCopyDataString($My_Hwnd, $Scite_hwnd, $sCmd) ; by Prog@ndy
    ;~ Local $CmdStruct = DllStructCreate('Char[' & StringLen($sCmd) + 1 & ']')
    ;~ DllStructSetData($CmdStruct, 1, $sCmd)
    ;~ Local $COPYDATA = DllStructCreate('Ptr;DWord;Ptr')
    ;~ DllStructSetData($COPYDATA, 1, 1)
    ;~ DllStructSetData($COPYDATA, 2, StringLen($sCmd) + 1)
    ;~ DllStructSetData($COPYDATA, 3, DllStructGetPtr($CmdStruct))
    ;~ DllCall('User32.dll', 'None', 'SendMessage', 'HWnd', $Scite_hwnd, 'Int', $WM_COPYDATA, 'HWnd', $My_Hwnd, 'Ptr', DllStructGetPtr($COPYDATA))

    [/autoit] [autoit][/autoit] [autoit]

    Local $Struct = DllStructCreate("CHAR[" & StringLen($sCmd) + 1 & "]")
    DllStructSetData($Struct, 1, $sCmd)
    DllCall("User32.dll", "None", "SendMessage", "HWnd", $Scite_hwnd, "INT", $WM_APP, "INT", StringLen($sCmd), "Ptr", DllStructGetPtr($Struct))
    EndFunc ;==>_SendCopyDataString

    [/autoit] [autoit][/autoit] [autoit]

    Func _MY_WM_APP($hWnd, $msg, $wParam, $lParam) ; by Prog@ndy
    ;~ Local $Temp = ""
    ;~ Local $COPYDATA = DllStructCreate('Ptr;DWord;Ptr', $lParam)
    ;~ Local $COPYDATA_StringLen = DllStructGetData($COPYDATA, 2)
    ;~ Local $CmdStruct = DllStructCreate('Char[' & $COPYDATA_StringLen & ']', DllStructGetData($COPYDATA, 3))
    ;~ $COPYDATA_String = StringLeft(DllStructGetData($CmdStruct, 1), $COPYDATA_StringLen)
    ;~ GUICtrlSetData($hEdit, $COPYDATA_String)

    [/autoit] [autoit][/autoit] [autoit]

    Local $Struct = DllStructCreate("CHAR[" & $wParam & "]", $lParam)
    $COPYDATA_String = DllStructGetData($Struct, 1)
    GUICtrlSetData($hEdit, $COPYDATA_String)
    EndFunc ;==>_MY_WM_COPYDATA

    [/autoit]
  • Ja, das könnte ich verwenden. Aber der Ehrgeiz lässt mir keine ruhe.
    Jetzt wo ich die DllStructCreate und DllStructGetData / SetData einigermassen verstanden habe ;)

    Wo liegt der Fehler?
    Ich habe ja extra eine eigene Message (WM_APP) verwendet!