Kommunikation Skripte untereinander

  • Hallo Zusammen,
    in meinem aktuellen Projekt benötige ich eine Kommunikation von mehreren Skripten untereinander. Jetzt gibt es dafür verschiedene Ansätze

    - TCP Kommunikation
    - Windows Variablen
    - Dateien lesen/schreiben
    - usw...

    Alle Ansätze gefallen mir nur bedingt. Aus meiner Roboter-Welt kenn ich Globale Variablen, die ich von jedem Programm aus lesen/schreiben kann. Gibt es sowas bzw. was ähnliches vielleicht für AutoIt?


    Ich bedanke mich für eure Bemühungen!


    Gruß
    Homer J. S.

    ...wenn die Donuts auch nur halb so gut schmecken wie sie aussehen, dann sehen sie doppelt so gut aus wie sie schmecken...

  • Hy,
    Sowas wie übergreifende Globale Variablen gibt es leider nicht... Ich denke der beste Weg ist die TCP Kommunikation untereinander, ist auch nicht so kompliziert wie es anfangs erscheint! Und das mit dem Datei lesen/schreiben würde ich gleich verwerfen, gibt nur probleme wenn z.B. die Datei bereits erstellt aber noch nicht fertig geschrieben ist...

    Grüsse!


  • Sowas überhaupt vorzuschlagen :thumbdown:

    Ganz ruhig Chéfé :D war bestimmt nicht böse gemeint.
    Es kommt immer auf den Anwendungszweck an, je nachdem ist ein Registry-Eintrag vieleicht sogar sinnvoller als tcp Kommunikation (falls die "Variable" dauerhaft bestehen soll und von mehreren programmen benötigt wird).
    Zumüllen würde ich das aber nicht nennen...ausserdem lass ich doch nicht alle 2 Wochen den Registry-Cleaner durchlaufen nur damit ich sie selber mit allerhand mist "beschmutzen" kann.

    Bild1: Ich beim debuggen

  • Zitat

    Und das mit dem Datei lesen/schreiben würde ich gleich verwerfen, gibt nur probleme wenn z.B. die Datei bereits erstellt aber noch nicht fertig geschrieben ist...

    Kann ich nicht bestätigen. Habe in Produktivumgebung ca. 10-15 Clients, welche in "Datenbank"-Textdateien schreiben und lesen.
    Probleme gibts dabei keine, sämtliche Aktionen laufen im Millisekundenbereich ab. Und sollte doch einmal eine Datei gesperrt sein, na dann gibts nen Fehler welcher abgefangen wird und ne Sekunde später ist die Datei wieder "frei".
    Die "Probleme" in diesem Zusammenhang entstehen immer dann, wenn derjenige, der die Programme schreibt, nicht weiß was er gerade tut...wie bei anderen Programmen auch.
    Dateien Öffnen, irgendwelche Berechnungen durchführen, und dann Dateien schließen ist, wenn die Berechnungen lange dauern, völliger mumpitz.
    Fileread() liest die Datei in Millisekunden ein, dann kann man gemütlich Berechnungen durchführen und DANN die Datei wieder schreiben.
    Wie gesagt, eine sehr einfache Lösung, wenn man weiss, was man macht....

  • Schnitzel:
    Ich versteh deine Reaktion nicht. Was ist denn so verwerflich daran die registery für globale variablen zu missbrauchen? Es gibt ne eigene sektion extra für softwaren. Da drin kannste alles nach herzenslust ändern, löschen, überschreiben und haste net gesehen. Das nimmt keinen einfluss auf das eigentliche betriebssystem. Nur wenn du an der falschen stelle rumhantierst wir's unter umständen kritisch :p

  • Hallo Zusammen,
    erstmal sorry, berufsbedingt, für die späte Antwort und danke für eure Hilfe.


    Andy:

    Zitat

    Die "Probleme" in diesem Zusammenhang entstehen immer dann, wenn derjenige, der die Programme schreibt, nicht weiß was er gerade tut...wie bei anderen Programmen auch.

    ...da stimme ich dir absolut zu. Vielen wäre schon geholfen, wenn sie ein gut überlegtes Error/Debug-Handling integrieren würden.


    Schnitzel: Die UDF's kannte ich noch nicht und werde diese mal genauer betrachten, wenn es meine Zeit wieder zulässt.

    Techmix: TCP-Kommunikation habe ich schon einige gemacht, aber die hat den entscheiden Nachteil, das beide Skripte "parallel" kommunizieren müssen (Handshake).

    @Make-Grafik: Mit der Registery den Gedanken hatte ich auch schon, aber das hat den entscheiden Nachteil, das bei jedem beschreiben der Registery dies auch auf der HDD geschieht, was auch der Nachteil an einem Filehandling ist.


    Ich erkläre am besten mal was ich grob vor habe:

    1 - Ich habe "Skript 1" was Daten von einer Hardwareschnittstelle (z.B. Ethernet) holt, wobei die angeschlossene Peripherie diese Daten ohne Anforderung sendet.

    2 - Ich habe "Skript 2" welches mehrere Aufgaben hat, unteranderem Daten von "Skript 1" zu holen und zu verarbeiten.

    3 - Angenommen die Peripherie sendet mir ein Byte "10101010", dann soll "Skript 1" diesen Wert in eine Globale Variable schreiben und wieder auf Daten von der Peripherie warten, da diese ja ohne Anforderung gesendet werden. Wenn "Skript 2" die Daten benötigt, dann müßte dieses nur die Globale Variable auslesen um den Wert "10101010" zu erhalten. Falls in der Zwischenzeit die Peripherie neue Daten sendet, dann sind die alten Daten hinfällig.

    Da dies später auf einem Rechner mit Speicherkarte läuft, will ich unnötiges beschreiben der HDD vermeiden. Ein Verfall der Daten bei Neustart oder Reset ist für meine Anwendung nicht bedeutsam.

    Ich habe auch noch die Möglichkeit mit Umgebungsvariablen gefunden (EnvSet/EnvGet), was mir den erfolgsversprechenden Ansatz bietet. Wenn ich das richtig verstanden habe, liegen diese nur im RAM-Speicher. Was es hier halt zu beachten gibt, das alles vom "Master-Skript" gestartet wird, was auf diese Variablen zugreifen soll. Was haltet ihr von dieser Lösung?


    Gruß
    Homer J. S.

    ...wenn die Donuts auch nur halb so gut schmecken wie sie aussehen, dann sehen sie doppelt so gut aus wie sie schmecken...

  • Wenn dein Programm 1 eine GUI verwendet, könntest du mit Programm 2 die Daten aus einem Control auslesen.

    Weiterhin besteht die Möglichkeit eine DllStruct in Programm 1 zu erstellen und mit Daten zu füllen. Den Pointer auf diese Struct an Programm 2 übertragen (einmalig ggf doch auf Platte schreiben) .
    Somit kann Programm 2 auf dem Speicherbereich von Programm 1 zugreifen.

  • Nun ja, dürfte aber nicht so einfach werden. Das 2te Skript kann nämlich nicht via DllStruct darauf zugreifen. Da müsste dann mit den Funktionen _WinApi_ReadProcessMemory() und _WinApi_WriteProcessMemory hantiert werden.

    €dit: @Homer:
    Wenn du mit Umgebungsvariablen arbeiten willst, musst du die Skripte die darauf zugreifen sollen mit Run starten. Dann kannst du auch gleich die Std-Streams (hoffentlich heißen die so xd) verwenden.

    Einmal editiert, zuletzt von Yjuq (8. Oktober 2014 um 13:35)

  • Zitat

    Nun ja, dürfte aber nicht so einfach werden.

    yupp, unendlich kompliziert^^

    Script1 kompilieren und starten

    Spoiler anzeigen
    [autoit]


    $gui=guicreate("Script1")
    $label=GUICtrlCreateLabel("",20,20,200,30)
    guisetstate()

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

    $struct = dllstructcreate("dword;char[20]")
    $ptr=dllstructgetptr($struct)
    filedelete("ptr.txt")
    filewrite("ptr.txt",$ptr)

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

    $x=0

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

    while $x<1000*sleep(1000)
    $x=$x+1
    GUICtrlSetData($label,$x&" AutoIt_"&$x)
    dllstructsetdata($struct,1,$x)
    dllstructsetdata($struct,2," AutoIt_"&$x)
    wend

    [/autoit]

    Dann Script2 starten

    Spoiler anzeigen
    [autoit]

    #include <WinAPI.au3>
    $gui = GUICreate("Script2")
    $label = GUICtrlCreateLabel("", 50, 80, 200, 30)
    GUISetState()

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

    $struct = DllStructCreate("dword;char[20]")
    $ptr = DllStructGetPtr($struct)

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

    $ptr1 = FileRead("ptr.txt")

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

    $pid = WinGetProcess("Script1")
    $ph = _WinAPI_OpenProcess(0x0010, False, $PID)

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

    $bytes=0
    $x = 0

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

    While $x < 1000 * Sleep(1000)
    $x = $x + 1
    $a = _WinAPI_ReadProcessMemory($ph, $ptr1, $ptr, 24, $bytes)
    $int = DllStructGetData($struct, 1)
    $txt = DllStructGetData($struct, 2)
    GUICtrlSetData($label, $int & " " & $txt)
    WEnd

    [/autoit]


    Entgegen sonstiger Gewohnheiten habe ich keinerlei Kommentare eingefügt. Wer dafür Kommentare braucht, sollte von dieser Art Scripte die Finger lassen!

  • Hallo Zusammen,

    @ Make-Grafik:

    Zitat

    Wenn du mit Umgebungsvariablen arbeiten willst, musst du die Skripte die darauf zugreifen sollen mit Run starten. Dann kannst du auch gleich die Std-Streams (hoffentlich heißen die so xd) verwenden.

    ...das meinte ich mit...

    Zitat

    Was es hier halt zu beachten gibt, das alles vom "Master-Skript" gestartet wird

    Aber was ist Std-Streams?


    @ Andy:
    Ich habe mit "DllStruct" noch nicht gearbeitet, daher muß ich ich mir dies erstmal zu Gemüt führten. Allerdings beschleicht mich das Gefühl, das du mit Umgebungsvariablen keine guten Erfahrungen gemacht hast?! Vom Befehlssatz ist das mit den Umgebungsvariablen deutlich kürzer und einfacher gehalten, wie mit "DllStruct".


    @Alle:
    Werden jetzt die Umgebungsvariablen (EnvSet/EnvGet) im Arbeitspeicher gelagert oder auf der HDD? Zudem würde mich die maximale Anzahl der von mir angelegten Umgebungsvariablen interessieren?!


    Vielen Dank für eure Untetstützung!


    Gruß
    Homer J. S.

    ...wenn die Donuts auch nur halb so gut schmecken wie sie aussehen, dann sehen sie doppelt so gut aus wie sie schmecken...

  • Gute Frage, es gibt ja von Windows vordefinierte Umgebungsvariablen. Deren Inhalt lässt sich auch ändern. Daraus schließe ich mal, dass sie auf der Festplatte gespeichert sind. Ob AutoIt das ebenfalls tut weiß ich nicht, aber da gehe ich mal von aus. Vllt. Kann dir jemand anderes mehr dazu sagen.

    Zu dem Std-Streams:
    Es gibt 3 Standard-Datenströme, den stdin stream, stdout stream und stderr stream. Über diesen 3 Datenströmen ist es möglich Daten zu übergeben. Für weitere Erklärungen siehe Wikipedia. Die Streams kann man für Interprozesskommunikation schön missbrauchen. ^^

    Hab dazu auch mal hier nen Thread aufgemacht, da müsste sich auch ein Beispielcode dazu befinden. Bin aber gerade suchfaul, aber ich schreib dir vllt. später ein Beispiel.

    [autoit]

    If Not $CmdLine[0] Then ; Prüft ob schon eine Instanz des Skriptes offen ist
    $iPID = Run(@AutoItExe & ' ' & @ScriptFullPath & ' make', '', @SW_HIDE, 0x1) ; Startet eine neue Instanz des Skriptes mit aktivierten Stdin-Stream
    StdinWrite($iPID, 'Message ;)') ; Sendet die Nachricht in den Stdin-Stream des anderen Prozesses
    StdioClose($iPID) ; Schließt alle Std-Streams
    Else
    MsgBox(0x40000, '', ConsoleRead()) ; Liest den Stdin-Stream aus
    EndIf

    [/autoit]

    Einmal editiert, zuletzt von Yjuq (9. Oktober 2014 um 14:10)

  • Zitat

    Werden jetzt die Umgebungsvariablen (EnvSet/EnvGet) im Arbeitspeicher gelagert oder auf der HDD?

    Die Umgebungsvariablen werden in der Registry gespeichert. Also auf HDD.
    Und ob man nun die Registry direkt beschreibt oder "Umgebungsvariablen" benutzt, ist unerheblich, auf die HDD wird definitiv geschrieben.

    Die Methode, direkt aus dem Speicherbereich eines Prozesses zu schreiben, berührt die HDD nicht.
    Weiterhin bleiben auch keine "Dateileichen" übrig, wenn die Prozesse beendet werden.

  • Also, du hast nun einen Eimer voll an Möglichkeiten von uns bekommen. Ich glaube auch nicht dass es mehr Möglichkeiten gibt. Was mir noch einfällt wäre "File Mapping" Wenn ich auf MSDN das richtig verstandn habe, dann werden die Daten erst von einer Datei ins RAM geholt, dort wird der Speicher gemeinsam genutzt. Ist z.B. sinnvoll wenn man von einer CD die Daten nur einmal im RAM haben will, und alle Progamme mit den Daten arbeiten können. Dann gibts noch "Shared Memory", da wird der Speicher ebenfalls gemeinsam genutzt, Andy hatte ja schon ein Beispielskript dazu geschrieben. Naja, ansonsten bleibt noch das gedönse über die Standard-Datenströme, TCP und Named Pipe.

    Eine Sache gibt's aber noch, ist aber ziemlich kompliziert. Es ist möglich globale Variablen in eine DLL zu verpacken. Da musst du aber erst einen eigenen Datenbereich in der DLL benennen und kannst nur vordefinierte Variablen nutzen. Außerdem sprengt es sowieso den Zweck von DLL's und ist eher eine (ich nenn es jetzt mal so) "abstrakte" Idee. Jedoch möglich.

    Nun ja, genug Möglichkeiten hast du ja jetzt, ich glaube auch das wir solangsam alles an Möglichkeiten abgeklappert haben. Such dir was aus und werde zufrieden. ^^

  • Hi,
    habe mir das mit der DLL durch den Kopf gehen lassen.
    Vorteil wäre, beliebig viele Programme auf ein und denselben Speicherbereich zugreifen lassen zu können.
    Dazu müsste man imho nur einen Speicherbereich reservieren, die Struktur, also die Definition von Variablen, Konstanten usw. könnte man, ohne die Dll zu verändern, vom jeweiligen Programm aus definieren!
    Sozusagen eine universell verwendbare Dll zum beliebigen Datenaustausch.
    Bald ist ja Wochenende 8)

  • Ach Andy, soll das heißen dass du das mit der DLL in Angriff nehmen willst? Wäre auf jedenfall durchaus interessant das mal umzusetzen. Jedoch wüsste ich nicht wie genau das nun funktionieren soll. Hatte dazu bisher nur mal ein C++ code dazu gesehen. Scheint mir durchaus kompliziert zu sein. Und ob das sinnvoller ist als den benötigten Speicher direkt im Skript zu reservieren (_WinApi_MemGlobalAlloc) sei mal dahingestellt. Aber bestimmt klärst du mich noch auf. ^^