Winwait wartet auf ein Fenster, das nie kommt

  • Hallo Profis,


    ich hab' mal wieder ein typisches Anfängerproblem, das ich einfach nicht gelöst bekomme:

    Bei der überwachung einer Installationsroutine warte ich auf das Fenster mit der Ende-Meldung, um dieses mit SEND zu bestätigen.

    Breche ich jedoch die Inst.-Routine regulär ab, so erscheint dieses Fenster nie und das Script wartet artig bis zum Skt. Nimmerleinstag im RAM.

    Starte ich dann die Inst.-Routine ein weiteres Mal über das gleiche Script, kommen sich beide Scripte in die Quere.

    Ein Timeout für WinWait ist hier nicht anwendbar, da die Zeiten zwischen wenigen Sekunden und bis zu 30 Minuten variieren.


    Ich habe mit folgendem Code versucht, das Problem über ProcessExists zu lösen, leider erfolglos:

    If ProcessExists ("setup.exe") Then

    winwait bla bla
    send {Enter}

    EndIf


    Bis jetzt bin ich ganz naiv davon ausgegangen, daß sobald die 'If' - Bedingung wegfällt, alles zwischen 'if' und 'EndIf' nicht mehr abgearbeitet wird und das Programm dann mit dem folgenden Code weitermacht.

    In diesem Fall ist es anscheinend so, daß wenn winwait erst einmal aktiv geworden ist, er wartet, bis das Fenster erscheint, auch wenn die 'If'-Bedingung längst nicht mehr erfüllt ist, weil "setup.exe" nicht mehr läuft. Bei einem 'Do' würde ich das ja erwarten, aber nichtbei 'If'.

    Vielleicht mache ich ja auch mal wieder eine klitzekleine Kleinigkeit falsch. Hat eine(r) von Euch vielleicht eine Idee?


    Mit freundlichen Grüßen

    BinCZ

    • Offizieller Beitrag

    Hi,

    prüfst du dies denn in der Schleife immer wieder?

    Was soll denn idealerweise dein Abbruchkriterium sein?

    Du kannst natürlich auch ganz einfach im Skript als erste Anweisung schreiben:

    If ProcessExists (...) Then ProcessClose

    Dann bist du wieder allein :)

    Ansonsten z.B. mit AdlibEnable immer prüfen, ob du noch aktiv bist.

    So long,

    Mega

    • Offizieller Beitrag

    Hallo

    Probier das mal aus:

    Spoiler anzeigen
    [autoit]

    ;Die Schleife wird entweder dadurch beendet, dass der Prozess setup.exe nicht (mehr) existiert, oder das Fenster BlaBla erscheint.
    While ProcessExists("setup.exe") ;Solange der Prozess Setup.exe existiert lass die Schleife laufen.
    If WinExists("BlaBla") Then ExitLoop ;Anstatt von WinWait: Sobald das Fenster mit dem Titel "BlaBla" exisitert beende die Schleife.
    WEnd
    ;Wenn der Prozess setup.exe exisitert (also die Whileschleife dadruch abgebrochen ist, dass das Fenster "BlaBla" existiert) dann...
    If ProcessExists("setup.exe") Then
    Send("blabla");... sende "blabla"
    EndIf

    [/autoit]

    Falls das nicht hilft, gebe uns doch mal bitte den bisherigen Sourcecode von dir :)

    Mfg Spider

  • Hallo, liebe Leute,


    vielen Dank für Eure Anregungen!


    Vielleicht habe ich mich auch ein wenig unklar ausgedrückt:

    Ich möchte einfach, daß wenn der vom Script gestartete Prozess "setup.exe" nicht mehr läuft, es nicht länger auf das mit "WinWait" spezifizierte Fenster wartet, sondern mit seinem weiteren Code fortfährt.

    Die Abbruchbedingung ist also ein nicht existenter Prozess "setup.exe".


    Hierzu der relevante Code-Ausschnitt:

    ------------------------------------

    If ProcessExists ("setup.exe";) Then

    WinWait("Installation", "Jetzt nicht neu star";)
    If Not WinActive("Installation", "Jetzt nicht neu star";) Then WinActivate("Installation", "Jetzt nicht neu star";)
    WinWaitActive("Installation", "Jetzt nicht neu star";)
    Send("{ENTER}";)

    EndIf


    Die Sache mit dem "If" klappt nicht, denn ist "WinWait" erst einmal aktiviert, wartet er auf das Fenster, auch wenn die "If"-Bedingung längst weggefallen ist. Auch mit "While" und "ExitLoop" klappt's nicht, da das Fenster ja nie erscheint (Hab' ich ausprobiert!).


    Am geeignetsten erscheint mir die von Xeno vorgeschlagene Lösung mit "AdLibEnable", die ich mir in der Hilfe schon 'mal näher angesehen hab'. Damit kann ich im Hintergrund "setup.exe" auf Existenz überwachen und muss nur noch eine Lösung finden, das Script mit dem nächsten oder einem definierten Code-Segment fortzusetzen, sobald "setup.exe" gecanceled wurde.

    Sowas simples wie'n "GoTo <Sprungmarke>" hab ich leider nich' finden können, aber wenn ich die ganze Mimik in ein "While" einbinde und über "AdLibEnable" ein "ExitLoop" erzeuge, müsste es eigentlich auch klappen . . . werd's mal probieren.

    Oder habt Ihr vielleicht eine einfache und elegante Lösung dafür?


    Bis dahin nochmals vielen Dank für Eure Unterstützung

    -------------------- BinCZ

    Einmal editiert, zuletzt von BinCZ (30. Oktober 2007 um 19:24)

  • Hallo, da bin ich wieder, mit überzeugenden Resultaten!


    Die Umsetzung von Xeno's Vorschlag mit AdLibEnable hat's wirklich gebracht!

    Func mit ProcessExists definiert, AdLibEnable eingebaut . . . . . jetzt kann passieren, was will, sobald meine "Setup.exe" abgebrochen wird, wird über AdLibEnable mit der Func ein "Exit" ausgeführt und schon ist im Gegensatz zu vorher die AutoIt.exe auch aus dem Prozessmonitor verschwunden. Dafür ist die "AdLibEnable"-Standardzeit von 250 ms allemal ausreichend.

    Somit läuft jetzt auch nach Abbruch meiner Setup-Routine bei ihrem Neustart alles ohne Probleme durch falsche "send"-Befehle.

    Ich habe spasseshalber nachträglich mal versucht, in der Hilfe irgendwie selbst auf "AdLibEnable" zu stoßen: Keiner der Suchbegriffe "zyklisch", "monitor", "überwachung" und was weiß ich, was ich nicht alles probiert hab', hat mich zu dieser nützliche Funktion geführt.

    Daher bedanke ich mich an dieser Stelle nochmals ausdrücklich für Eure Unterstützung.


    Aber ein "Problemchen", hätt' ich da trotzdem noch: Ich kann zwar jetzt das gesamte Script canceln, sobald meine "setup.exe" nicht mehr läuft, habe aber trotz Suche in der Hilfe und im Board nicht herausfinden können, wie ich das Script veranlasse, von einer definierten Marke an weiterzuarbeiten.

    Wenn Ihr dafür auch eine Lösung parat hättet, wäre ich sehr dankbar, Ihr teiltet sie mir mit.


    Mit freundlichen Grüßen

    ----------------------------- BinCZ

    • Offizieller Beitrag

    Hi,

    ich würde vorschlagen dir eine Ini anzulegen z.B. im selben Verzeichnis. Dann schreibst du nach jedem wichtigen Schritt eine Zahl in die Ini.

    1,2,3,4 usw.

    Wenn das Skript gestartet wird, dann checkst du If FileExists .. wenn ja dann lesen und dann dort weitermachen.

    Zum Schluss, checken alles fertig ? Wenn ja ini löschen.

    So long,

    Mega

  • Hallo Xeno,


    vielen Dank für Deinen Tipp mit der .ini. Mit dieser Lösung kann ich zwar das Script bei Neustart veranlassen, ab einem bestimten Punkt wieder aufzusetzen, mein eigentliches, an sich triviales Problem ist damit jedoch nicht gelöst:

    Wie definiere ich die Code-Zeile oder noch besser ein Label, an dem es wieder aufsetzen soll; und wie komme ich zu diesem Label? Wie schon erwähnt, sowas simples wie'n "GoTo Label" hab' ich leider trotz aller Anstrengungen nicht finden können

    Ich hab' da einfach keine Idee, Du vielleicht?


    Und dann ist mir beim "AdlibEnable" (Einfach Klasse, Dein Tipp!) noch 'ne Kleinigkeit aufgefallen, zu der ich auch nirgends einen Hinweis finden kann:

    Ich habe versucht, die "AdlibEnable" zugewiesene Funktion anderweitig aufzurufen, aber keine Chance. Sie wird einfach nicht abgearbeitet, auch nicht mit vorausgehendem "AdlibDisable". Sind "AdlibEnable" zugewiesene Funktionen generell nicht anderweitig aufrufbar?

    Weiterhin weiß ich nicht, ob "AdlibEnable" mehrfach definiert werden kann, mit jeweils einer anderen Funktion.

    Solltest Du mehr über die Interna von "AdlibEnable" wissen, als in der Hilfe steht, wäre ich dankbar, teiltest Du's mir mit.


    Mit freundlichen Grüßen

    ----------------------------- BinCZ

    • Offizieller Beitrag

    Hallo,

    das mit den Labels könntest Du so lösen:

    [autoit]

    $InstallSection = IniRead("install.ini", "Status", "Secton", "0")

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

    ; Installation von vorne beginnen
    If $InstallSection < 1 Then

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

    IniWrite("install.ini", "Status", "Secton", "1")
    Endif

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

    ; 2. Abschnitt beginnt hier
    If $InstallSection < 2 Then

    IniWrite("install.ini", "Status", "Secton", "2")
    EndIf

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

    ; 3. Abschnitt beginnt hier
    If $InstallSection < 3 Then

    IniWrite("install.ini", "Status", "Secton", "3")
    EndIf

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

    ; 4. Abschnitt beginnt hier
    If $InstallSection < 4 Then

    IniWrite("install.ini", "Status", "Secton", "4")
    EndIf

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

    ; Installation abgeschlossen, beim nächsten mal von vorne beginnen
    IniWrite("install.ini", "Status", "Secton", "0")

    [/autoit]


    Bei AdlibEnable gilt immer nur der letzte Aufruf, d.h. sobald AdlibEnable erneut aufrufen wird, wird die vorherige Funktion nicht mehr aufgerufen.

    Die Funktion die AdlibEnable zugewiesen ist kann auch ganz normal aufgerufen werden, sie wird von AdlibEnable nicht gesperrt.

  • Hallo Bernd,


    vielen Dank für Deinen Tipp. Ich habe mich bei meinem "Problemchen" mal wieder zu allgemein ausgedrückt. Daß ich mit der von Dir vorgeschschlagenen Methode den Script-Ablauf protokollieren und bei Neustart an dem Folgepunkt wieder aufsetzen kann, ist mir schon klar. Einen anderen Weg gibt es dafür gar nicht, es sei denn, ich schreibe mir Merker in die Registry.


    In meinem speziellen Beispielfall reicht es aus, über die in "AdlibEnable" spezifizierte Funktion das Script einfach über "Exit" zu canceln. Ich suche jedoch eine allgemeine Lösung, sodaß ich mit "AdlibEnable" auch einzelne Script-Teile einfach nur abbrechen, überspringen oder gar wiederholen kann, indem ich an einem definierbaren Punkt wieder aufsetze, ohne gleich das komplette Script zu canceln.

    Nach allem, was ich aus der Hilfe und von Euch bisher erfahren habe, scheint das nur möglich zu sein, indem ich das Script in Form von Funktionen (Prozeduren gibt es hier ja nicht) in einzelne Abschnitte aufteile, muss dafür aber anscheinend das Problem mit den Schleifen in Kauf nehmen. Gegebenfalls müssen diese Funktionen jeweils "AdlibEnable" neu definieren oder ich muss diverse "AdlibEnable" schon im Hauptprogramm ver-"If"-fen, bzw. ver-"case"-n. Das muß ich noch mal im einzelnen durchdenken. Sowas universelles wie'n "GoSub" oder "GoTO2 wär' hier das Mittel der Wahl, aber das oder etwas vergleichbares scheint es in AutoIt nicht zu geben; oder ich bin einfach zu duss'lich, es zu finden.


    Insbesondere bedanke ich mich für die erweiterten Informationen zum "AdlibEnable" selbst, diesbezüglich war einfach nirgends 'was zu finden. Der externe Aufruf der "AdlibEnable" zugewiesenen Funktion allerdings wollte bei mir partout nicht laufen, auch nicht mit vorausgehendem "AdlibDisable". Aber wenn Du sagst, daß die Funktion von "AdlibEnable" nicht "verexklusivisiert" wird, werde ich es, vorerst in einem Testscript, nochmal ausprobieren. Vielleicht habe ich ja in meinem etwas komlpexeren Gebilde eine Kleinigkeit übersehen.


    Bis dahin nochmals vielen Dank

    ------------------------------------ BinCZ

    5 Mal editiert, zuletzt von BinCZ (1. November 2007 um 16:21)

    • Offizieller Beitrag

    Hallo

    Hilft dir das vielleicht weiter?:

    [autoit]

    Global $Run = True
    AdlibEnable("_BreakRun",5000);Script Läuft 5 Sekunden - Script Pausiert 5 Sekunden - Script Läuft 5 Sekunden - usw usw usw

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

    While 1
    If $Run Then
    TrayTip("Script Läuft",Random(0,10000,1),3)
    Else
    TrayTip("Script Pausiert",'0',3)
    EndIf
    Sleep(50)
    WEnd

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

    Func _BreakRun()
    $Run = Not $Run ;Wenn $run voher False war dann wird es jetzt True. andersrum auch.
    EndFunc

    [/autoit]

    Mfg Spider

  • Hallo Spider,


    vielen Dank für Deine Anregung. Da hatt' ich auch schon dran gedacht, generell das gesamte Script in ein "While" einzubinden und über die in "AdlibEnable" spezifizierte Funktion die Konditionen zu setzen.

    Tritt hier jedoch wieder mein "spezieller" Fall des endlos wartenden "WinWait" auf, bin ich erst mal wieder gekniffen.


    Aber es scheint generell nur über den Weg zu funktionieren, innerhalb eines Komplett-"While" Programmteile kondidionell abbrechen, überspringen oder wiederholen können. Ich habe leider zu wenig Erfahrung, jetzt aus dem Stehgreif alle Eventualitäten zu abstrahieren und sagen zu können: "Das isses!"

    Wahrscheinlich muß ich dazu beim Start einzelner Segmente den "AdlibEnable" neu parametrieren, und wenn dies sauber abgelaufen ist, den vorhergehenden oder einen den aktuellen Konditionen entsprechenden "AdlibEnable"-Zustand wiederherstellen. Das muß ich erst mal im einzelnen ausfieseln.


    Das Ganze sprengt mittlerweilen den Rahmen des ursprünglichen Themas. Daher halte ich es für angebracht, dieses Thema erst mal für gelöst zu erklären und ggf. ein neues bezüglich meiner aktuellen Problematik zu eröffnen, sollte ich sie nicht über kurz oder lang ohne weitere Unterstützung in den Griff bekommen.


    Auf jeden Fall werde ich bei Jonathan mal die Implementierung so elementarer Befehle wie "GoSub" und "GoTo" anregen, denn damit gäbe es solche Probleme gar nicht.


    Bis dahin erst mal vielen Dank an alle für die bisher geleistet Unterstützung.

    ----------- BinCZ

    2 Mal editiert, zuletzt von BinCZ (1. November 2007 um 17:20)

    • Offizieller Beitrag

    Goto zu fordern ist einfach feige ;).
    Es ist so wie es in der FAQ gesagt wird: Goto macht Code unglaublich unleserlich. Es gibt immer eine Umsetzung mit Schleifen und If-Anweisungen - nicht immer leicht, das ist klar. Aber man muss sich einfach ein bisschen damit beschäftigen. Was sollte GoSub tun? Hoffentlich nicht nur eine Funktion aufrufen, das kann AutoIt mehr als gut...

    Also setz dich mal an While, For, Do, If...Then...Else, damit muss es umsetzbar sein...

    peethebee

  • Hallo peethebee,


    Hascha Recht, ob ich nun'n "GoSub" oder 'ne Func anspringe, dat is' Jacke wie Hose.

    Un'n "GoTo" macht Code tätsächlich unübersichtlich, vor allem, wenn sich dahinter weitere "GoTo's" verbergen. Da findet man bei etwas komplexeren Sachen am Ende sogar selbst nich' mehr durch.


    Ich werde mich also weiterhin in diesem speziellen Fall mit der "While"-Lösung näher beschäftigen.


    Gruß von der friesischen (O mei, a Preiß) Nordseeküste

    ------ BinCZ

    Einmal editiert, zuletzt von BinCZ (1. November 2007 um 17:54)