Autoit-Datei während Laufzeit einbinden

  • Hallo, wie der Titel schon sagt möchte ich dass man in einer GUI eine AutoIt (au3) - Datei auswählen kann und diese wird dann "eingebunden" und eine darin existierende Funktion ausgeführt.
    Ist soetwas überhaupt möglich und falls ja wie?

    Ich würde mich über jegliche Hilfe freuen :)

  • Ganz pauschal muss ich dir da leider sagen: Nein! Natürlich gibt es Ausnahmen, zum Beispiel wenn auf dem PC Autoit installiert ist, oder wenn die Funktion nur aus 'einzelnen' Funktionen besteht, die nicht zusammen abreiten und sich daher mit Execute() ausführen lassen. Alternativ lässt sich so etwas natürlich auch über eine _RunPE() Funktion lösen, die ich hier jetzt aber nicht posten werde, da damit viel Unsinn gemacht werden kann... ;) *hust* Google *husthust*
    Worum gehts denn speziell? Wenn du uns sagst was du eigentlich machen möchtest, lässt sich dir viel viel besser helfen... ;)

    LG
    Christoph :)

  • Christoph54 danke für den komplett sinnlosen und destruktiven Post..

    Prinzipiell geht das natürlich. Es ist auch unabhängig davon ob AutoIt 'installiert' ist oder nicht.. Warum sollte es auch.

    Ein eigens dafür bestimmtes Script zu schreiben das besagte Zeilen aus der au3 aufnimmt und dann compiliert wird sollte eine schnell machbare Lösung darstellen..

    Und runPE ist wie der Name schon sagt eine Methode zum loaden von PEs und nicht von Code. Argon will aber aus einem au3 bestimmte Teile ausführen.

    Evtl. ist es auch mit einer erweiterten Execute-Funktion realisierbar je nachdem was genau du einbinden willst

    Einmal editiert, zuletzt von Toffmo (5. September 2012 um 23:32)

  • Zitat

    Christoph54 danke für den komplett sinnlosen und destruktiven Post..


    Das geht doch auch freundlicher. :whistling:
    Die Funktion in deinem Link hat auch eine Menge einschränkungen, genau wie das Original. Sie bietet längst nicht die volle Funktionalität des AutoIt Interpreters und wird bestimmt auch nicht immer auf dem neuesten Stand sein.
    Außerdem hat er Recht, ohne AutoIt auf dem PC wo das gemacht werden soll geht das nicht, egal in welcher Form. Ob du jetzt einen Interpreter selbst schreibst (was wohl meist weniger Sinnvoll ist), oder den AutoIt Interpreter in die kompilierte Datei mit einbindest und später wieder entpackst... Das man sich bei diesem Forum registrieren soll um da eine Datei runterzuladen von der ich keine Ahnung hab was drin sein könnte find ich auch nicht so prickelnd, daher werde ich das auch gar nicht erst ausprobieren.

    @argon Du kannst, soweit ich weiß, nicht zur Laufzeit Funktionen in AutoIt Scripte einbinden. Aber du kannst den Code der ausgeführt werden soll in eine Datei schreiben und die per Kommandozeilenparameter an die AutoItv3.exe übergeben um sie sofort auszuführen. Wenn du allerdings Werte zwischen diesen separaten Prozessen übertragen willst, dann musst du dir ein Verfahren zur Interprozess Kommunikation aussuchen (z.B. TCP, Named Pipes, AutoIt Fenstertitel, Standard Input/Output Streams etc..).
    In den meisten Fällen lässt sich das aber besser lösen, deshalb schließe ich mich mal Christoph an und frage: "Worum gehts denn speziell?" ;).

  • So sollte das ungefähr aussehen

    [autoit]

    ; Skript 1

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

    ; einbinden skript 2 (dieser Part fehlt mir)
    Call("NeueFunktion","Hallo Welt")

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

    ; Skript 2
    Func NeueFunktion($str)
    MsgBox(0,"",$str)
    EndFunc

    [/autoit]


    Dabei soll das ganze ohne #include funktionieren ich will, dass der User selbst festlegen kann in einer GUI welche Datei er einbindet.
    Hoffe ihr könnt damit was anfangen :pinch:

  • Was genau soll das denn ermöglichen? Der User soll also sein eigenes Script schreiben können, dass dann in dein Script hineingeschrieben wird?
    Was soll der User dadurch alles festlegen können? Es wäre gut wenn du mal den Zweck beschreiben könntest. Weil jetzt weiß ich immer noch genauso viel wie ich auch aus deinem ersten Post erahnen konnte ;).
    Du könntest es ja mit einer Art Launcher versuchen. In dem Launcher wäre dann nur die GUI in der ein Script ausgewählt werden kann, und eine Funktion die dein Hauptscript und die Ergänzung des Users kombiniert, in eine Datei schreibt und ausführt. Allerdings kann man das nicht wirklich als "zur Laufzeit" bezeichnen...

  • Es soll ermöglichen dass der User in AutoIt geschriebene "Plugins" einbinden kann.
    Naja dann werde ich mir wohl etwas anderes einfallen lassen müssen.

  • Nö, Plugins sollten möglich sein. Das ist nicht ganz simpel, aber wenn du den AutoIt Interpreter in deine exe packst und eine kleine API aufbaust, die es ermöglicht bestimmte Werte im Hauptscript durch die, von mir angesprochene, Interprozess Kommunikation zumanipulieren, dann sollte das möglich sein. Es geht schon, aber je nachdem was für ein Funktionsumfang dir da vorschwebt beeinflusst das auch die Komplexität des Vorhabens.
    Was müssen diese Plugins denn tun können?

  • Ich hab mal ein Beispiel gebastelt. Das ist zwar längst noch nicht fertig/optimiert und nicht auf deine Bedürfnisse angepasst, aber es funktioniert immerhin.

    Hauptscript mit GUI (Auswahl der Plugins hab ich noch nicht eingebaut):

    Main.au3
    [autoit]

    #include <GUIConstants.au3>

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

    Opt("GUIOnEventMode", 1)

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

    Global Const $sPath_PlugIn = @ScriptDir & "\Plugins" ;Der Pfad zum Ordner der alle Plugins (in Form von .au3 Dateien) enthält
    Global Const $sPath_AutoItExe = @AutoItExe ;Der Pfad zum AutoIt Interpreter

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

    Global $aPlugIn[1] = [0]
    Global $hSearch = FileFindFirstFile($sPath_PlugIn & "\*.au3") ;Nach .au3 Dateien im Plugin Verzeichnis suchen

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

    While True
    $sFile = FileFindNextFile($hSearch)
    If @error Then ExitLoop
    If Not @extended Then
    $aPlugIn[0] += 1
    ReDim $aPlugIn[$aPlugIn[0] + 1]

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

    $aPlugIn[$aPlugIn[0]] = Run($sPath_AutoItExe & ' "' & $sPath_PlugIn & '\' & $sFile & '"', @ScriptDir, @SW_HIDE, 3)
    EndIf
    WEnd

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

    $hWnd = GUICreate("Plugin Test", 400, 400)
    $cButton_Test = GUICtrlCreateButton("Test", 10, 10, 60, 25)
    $cButton_AutoIt = GUICtrlCreateButton("AutoIt", 10, 40, 60, 25)
    $cEdit = GUICtrlCreateEdit("", 80, 10, 200, 200)
    $cInput = GUICtrlCreateInput("", 10, 85, 60, 20)
    GUISetState()

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

    GUICtrlSetOnEvent($cButton_Test, "_Test")
    GUICtrlSetOnEvent($cButton_AutoIt, "_AutoIt")
    GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")

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

    For $i = 1 To $aPlugIn[0]
    StdinWrite($aPlugIn[$i], "START")
    Next

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

    While Sleep(20)
    For $i = 1 To $aPlugIn[0]
    If $aPlugIn[0] = 0 Then ContinueLoop

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

    $sData = StdoutRead($aPlugIn[$i])
    If @extended Then
    If $sData = "QUIT" Then
    StdioClose($aPlugIn[$i])
    $aPlugIn[$i] = 0
    ContinueLoop
    EndIf

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

    $aSplit = StringRegExp($sData, "(?s)([^=]+)=(.*)", 1)
    If UBound($aSplit) < 1 Then ExitLoop

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

    Switch $aSplit[0]
    Case "Set Button_Test Text"
    GUICtrlSetData($cButton_Test, $aSplit[1])
    Case "Set Button_AutoIt Text"
    GUICtrlSetData($cButton_AutoIt, $aSplit[1])
    Case "Set Button_AutoIt BKColor"
    GUICtrlSetBkColor($cButton_AutoIt, $aSplit[1])
    Case "Set Edit Text"
    GUICtrlSetData($cEdit, $aSplit[1])
    Case "Set Input Text"
    GUICtrlSetData($cInput, $aSplit[1])
    EndSwitch
    StdinWrite($aPlugIn[$i], "OK")
    EndIf
    Next
    WEnd

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

    Func _Test()
    MsgBox(64, "Event", "Test Button clicked")
    EndFunc ;==>_Test

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

    Func _AutoIt()
    MsgBox(64, "Event", "AutoIt Button clicked")
    EndFunc ;==>_AutoIt

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

    Func _Exit()
    For $i = 1 To $aPlugIn[0]
    StdinWrite($aPlugIn[$i], "STOP")
    StdioClose($aPlugIn[$i])
    Next
    Exit
    EndFunc ;==>_Exit

    [/autoit]


    Beispiel Plugin:

    Test Plugin 1.au3
    [autoit]

    ;Auf Bereitschaft warten...
    While Sleep(20)
    $sData = ConsoleRead()
    If @extended Then
    If $sData = "START" Then ExitLoop
    EndIf
    WEnd

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

    AdlibRegister("_CheckStatus", 100) ;Überprüft alle 100ms ob der Parent Prozess noch aktiv ist

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

    Sleep(2000) ;Wartezeit, damit man verfolgen kann was passiert
    _SetValue("Set Edit Text", "This is a test.")
    Sleep(1000) ;Wartezeit, damit man verfolgen kann was passiert
    _SetValue("Set Input Text", "Indeed")
    _Exit() ;Plugin beenden

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

    Func _SetValue($sControl, $vValue)
    ConsoleWrite($sControl & "=" & $vValue)
    While Sleep(20)
    $sData = ConsoleRead()
    If @extended Then
    If $sData = "OK" Then Return ;Bestätigung des Parent Prozesses
    EndIf
    WEnd
    EndFunc

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

    Func _CheckStatus()
    $sData = ConsoleRead()
    If @extended Then
    If $sData = "STOP" Then Exit ;Parent Prozess ist inaktiv
    EndIf
    EndFunc

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

    Func _Exit()
    ConsoleWrite("QUIT")
    Exit
    EndFunc

    [/autoit]


    Beispiel Plugin:

    Test Plugin 2.au3
    [autoit]

    ;Auf Bereitschaft warten...
    While Sleep(20)
    $sData = ConsoleRead()
    If @extended Then
    If $sData = "START" Then ExitLoop
    EndIf
    WEnd

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

    AdlibRegister("_CheckStatus", 100) ;Überprüft alle 100ms ob der Parent Prozess noch aktiv ist

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

    _SetValue("Set Button_AutoIt BKColor", 0xFF0000)
    _SetValue("Set Button_AutoIt Text", "Works")
    _SetValue("Set Button_Test Text", "Plugin")
    _Exit()

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

    Func _SetValue($sControl, $vValue)
    ConsoleWrite($sControl & "=" & $vValue)
    While Sleep(20)
    $sData = ConsoleRead()
    If @extended Then
    If $sData = "OK" Then Return ;Bestätigung des Parent Prozesses
    EndIf
    WEnd
    EndFunc

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

    Func _CheckStatus()
    $sData = ConsoleRead()
    If @extended Then
    If $sData = "STOP" Then Exit ;Parent Prozess ist inaktiv
    EndIf
    EndFunc

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

    Func _Exit()
    ConsoleWrite("QUIT")
    Exit
    EndFunc

    [/autoit]


    Die Plugins müssen in einen Ordner namens "Plugins" im Scriptverzeichnis (lässt sich auch ändern). Danach wird das Hauptscript gestartet, dass die Plugin Scripte als Child Prozesse ausführt und mit diesen über die Standard Streams kommuniziert. Alle Plugins können sich selbst beenden oder werden automatisch beendet sobald der Parent Prozess nicht mehr aktiv ist. Der Pfad zum AutoIt Interpreter wird momentan per Makro ausgelesen (d.h. das funktioniert nur wenn du AutoIt installiert hast und das Script nicht kompiliert ist). Später für den Einsatz bei Leuten die kein AutoIt haben musst du dein Hauptprogramm eben kompilieren und per FileInstall den AutoIt Interpreter in ein beliebiges Verzeichnis entpacken. Den Pfad musst du dann entsprechend anpassen, damit er wieder zur AutoIt.exe führt.
    Mir fällt dabei gerade auf, dass für so etwas simples auch eine kleine Ini Kofingurationsdatei reichen würde, aber ich gehe mal davon aus, dass du noch weitaus mehr vorhast. ;)
    Im Anhang ist noch ein Template Plugin wo das absolute Minimum für ein leeres Plugin drin ist.
    Ich hoffe das ist in etwa das was du wolltest.

  • Hab zuhause funktioniernde selbsterweiterung rumliegen.
    Ich poste das nacher mal. Sollte es gegen irgendwas verstoßen post löschen.
    Ich habs mal verwendet um ne art polymophie zu erreichen.

    -

  • Zitat

    @Name Wenn du die Plugins auf diese Weise ausführst, funktioniert dein System, egal ob kompiliert oder nicht und egal ob AutoIt installiert ist (wenn das Skript kompiliert ist) oder nicht.


    Ach so :huh:. Ich wusste nicht, dass der Interpreter in der exe auch auf diese Kommandozeile reagiert. Weißt du zufällig, ob UPX diese Funktion beeinflusst?