Exit code 3221225477 bei TrayCreateMenu()

  • Hallo Comunity,
    nach ein paar Tagen, die ich mit AutoIt verbracht habe (und meinen ersten Programmen und Problemen, die ich alle selbsständig lösen konnte), habe ich nun ein Problem, bei dem mir weder die Online-Hilfe, noch der Debugger weiterhelfen konnte.

    Mein Programm möchte ich möglichst klein halten und habe mich daher gegen eine GUI entschieden. Die entsprechenden Konfigurationen möchte ich über das Tray-Symbol ändern und zwar während der Laufzeit.

    Leider funktioniert das nur manchmal, wobei es egal ist, ob man Das Programm direkt ausführt oder zuerst kompiliert.

    Wenn man das Programm startet, funktioniert es entweder immer oder es stürzt beim Auswählen des Menüpunkts ab. Den Sourcecode hab ich kopiert und auf den fehlererzeugenden Code reduziert:

    Es scheint so, als ob TrayItemSetOnEvent() die entsprechende Funktion nicht immer finden kann.

    Ich hoffe, Ihr könnt mir sagen, was ich falsch mache. Vielen Dank schon mal im Vorraus.

  • Du erzeugst dein Tray innerhalb einer Funktion und erstellst ein Menu in eine Variable mit lokalem Scope.

    Die Referenz geht nach dem Beenden der Funktion verloren und deswegen crasht dein Skript.

    Du solltest NIEMALS in Funktionen globale Variablen deklarieren, höchstens setzen.

    Wenn du deinen Code in den globalen Scope verschiebst (also einfach über die While-Schleife) funktioniert es problemlos.

  • Ich dachte mir, innerhalb der Funktion bleibt mein globaler Scope übersichtlicher. Mit dem setzen der Globalen Variable hast Du natürlich recht. Wenn global, muss sie auch immer und überall lesbar sein und nicht erst, wenn die Funktion aufgerufen wird.

    Den Code hab ich jetzt nach oben verschoben und getestet. Funktioniert problemlos. Beim dritten Versuch aber der Rückschlag. Das Script läuft nach wie vor ab und zu in den Exit code 3221225477.

    Hier mein aktueller Versuch:

    Edit 1: Habe das Array um eine Dimension gekürzt und die For-Schleife entfernt - Fehler tritt immer noch (wie auch vorher schon) ab und zu auf.

    Edit 2: Habe das Array jetzt komplett rausgeschmissen und definiere überhaupt keine Variablen mehr. Obwohl ich noch mehr gekürzt hab, taucht der Fehler immer noch auf (ca. 50% der runs).

    Hoffentlich nehmt Ihr es mir nicht übel, dass ich den Beitrag jetzt schon zum zweiten mal editiert hab.

    2 Mal editiert, zuletzt von Domi78 (9. Mai 2019 um 17:59)

  • Okay, ich hab nochmal rumprobiert und den Fehler entdeckt.

    Hier hab ich sogar den EventMode deaktiviert:

    Das Problem besteht immer noch. Also lag es nicht wie vermutet am "TrayOnEventMode" oder am TrayItemSetOnEvent() sondern es liegt am TrayCreateMenu().

    Ich bin jetzt nochmal alle Versionen die ich probiert hab und bei denen der Fehler aufgetreten ist durchgegangen. Wenn ich TrayCreateMenu() nicht verwende, sondern mit TrayCreateItem("") eine Trennzeile erzeuge, funktioniert alles perfekt.

    Das Problem ist eigendlich noch nicht gelöst, aber so kann ich zumindest weiter machen. Der Rest ist ja rein optisch.

  • Domi78 9. Mai 2019 um 20:24

    Hat das Label [ offen ] hinzugefügt.
  • Domi78 9. Mai 2019 um 20:24

    Hat den Titel des Themas von „Exit code 3221225477 bei TrayItemSetOnEvent()“ zu „Exit code 3221225477 bei TrayCreateMenu()“ geändert.
  • Das Problem besteht immer noch. Also lag es nicht wie vermutet am "TrayOnEventMode" oder am TrayItemSetOnEvent() sondern es liegt am TrayCreateMenu().

    Nicht ganz.

    Code
    TrayCreateMenu("Untermenü")
    TrayCreateItem("Text 3")
    TrayItemSetOnEvent(-1, "CallTray")

    Das crasht bei mir nicht.

    Code
    TrayCreateMenu("Untermenü")
    TrayCreateItem("Text 3", -1, -1, 1)
    TrayItemSetOnEvent(-1, "CallTray")

    Das hingegen schon.

    Der Fehler ist ziemlich inkonsistent aber reproduzierbar, wenn du die Zeit und Lust hast kannst du ihm ja gerne im BugTracker auf der engl. Seite melden.

    Ich nehme mal stark an intern werden die -1 als vorheriges GUI-Element statt "kein Menu" fehlinterpretiert und deswegen crasht das ganze.

  • Okay, das hat sich bei mir jetzt auch so gezeigt. Wenn ich die Optionen anklickbar mache, funktioniert alles normal.

    Man muss sich also entscheiden, ob man Radiobuttons möchte oder Untermenüs. Wenn man beides kombiniert, rennt man in einen Programmfehler rein.

    Das heißt, das vom Coding her (den Fauxpas mit der globalen Variable vergessen wir mal ganz schnell) also alles ganz okay war, wenn ich das richtig verstehe.

    Okay, dann bedank ich mich noch recht freundlich bei Dir, Amaterasu ;)

    Wenn das Programm fertig ist und läuft, schau ich mir mal den BugTracker an. Momentan will ich erstmal noch ein bischen geübter werden.

  • Sorry, daß ich mich hier noch reinhänge, aber das Problem es hat mich einfach gereizt.

    Im folgenden Script funktioniert es schon bei etlichen Durchgängen ohne Fehler bei mir, ist sicher nicht perfekt

    aber es läuft soweit ohne Absturz.

    Ich habe folgende Zeilen mit dem Fettgedruckten ergänzt und es läuft ohne Fehler

    $aTrayArray[1][3] = TrayCreateItem($aTrayArray[0][3], $iTraySettings, -1, 1)

    $aTrayArray[1][4] = TrayCreateItem($aTrayArray[0][4], $iTraySettings, -1, 1)

    $aTrayArray[1][5] = TrayCreateItem($aTrayArray[0][5], $iTraySettings, -1, 1)

    $aTrayArray[1][6] = TrayCreateItem($aTrayArray[0][6], -1, -1, 0)

    Was ich noch nicht ganz verstehe ist, wenn bei der letzten Zeile statt der 0 eine 1 eingefügt wird gibts auch Fehler.

    Ein Frage an alpines , wenn ich die Globale Variable in der Funktion so deklariere wie ich es in der

    auskommentierten Zeile stehen habe, sollte es aber doch auch machbar sein ohne Probleme oder nicht?

    Bei meiner Variante wird die Globale Variable nur dann deklariert wenn sie noch nicht exisitert,

    die Deklarierung wird also maximal einmal durchgeführt.

    Ich habe nicht viel aber doch ein paar Scripte, wo mir das als beste Löung erschien.

    Hoffe ich zur Lösung des Problems beitragen

    MfG Tuxedo

    Einmal editiert, zuletzt von Tuxedo (10. Mai 2019 um 08:31)

  • Guten Morgen,

    Danke Tuxedo für Deinen Versuch. Ich habe Dein Script kopiert, die Kommentarzeilen und die MsgBoxen entfernt und getestet. Es ist gleich beim ersten mal in den Fehler gelaufen.

    wenn bei der letzten Zeile statt der 0 eine 1 eingefügt wird gibts auch Fehler.

    Das deutet darauf hin, dass die Radiobuttons (die ja durch das "-1, -1, 1" aktiviert werden) Probleme damit haben, wenn unter ihnen ein Untermenü definiert ist. Das Einfügen einer Trennzeile löst das Problem.

    Hier der Code, der bei mir funktioniert (20 Tests ohne Absturz):

    wenn ich die Globale Variable in der Funktion so deklariere wie ich es in der auskommentierten Zeile stehen habe...

    Dann definierst Du $iTraySettings und erzeugst gleichzeitig das Untermenü als Eintrag ganz oben. Du könntest $iTraySettings aber zuerst global nur definieren (leer lassen) und später dann nur füllen, aber $iTraySettings wird ja nur benötigt, um das Untermenü anzulegen. Daher muss das keine globale Variable sein (im Gegensatz zum Array, welches die ID speichert und später beim klicken abgefragt werden muss).

  • Ein Frage an alpines , wenn ich die Globale Variable in der Funktion so deklariere wie ich es in der

    auskommentierten Zeile stehen habe, sollte es aber doch auch machbar sein ohne Probleme oder nicht?

    Bei meiner Variante wird die Globale Variable nur dann deklariert wenn sie noch nicht exisitert,

    die Deklarierung wird also maximal einmal durchgeführt.

    Es geht nicht darum zu prüfen, ob eine globale Variable bereits deklariert wurde. Die globale Variable $g_sString2 ist erst global verfügbar, nachdem Du eine Funktion aufrufst. Kommentiere in dem Skript mal _DeclareVars() ein und aus :

    Gruß Musashi

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

  • OMG... Ich geh in die Ecke und schäme mich... :Face:

    Aus der Hilfe:

    Zitat

    Radio menuitems are automatically grouped together and these groups are separated by a separator line or a normal item which is not a radio item.

    Ich danke euch allen trotzdem für eure Unterstützung.

  • Danke Euch beiden für die Antworten.

    Domi78 hast Recht, ich hatte das Script mindestens 10 mal gestartet und jedesmal etliche >Punkte aus dem Traymenu

    und zwar extra querbeet allesw durcheinander und jetzt nochmal versucht und es Crasht. Der Fehler ist richtig eigensinnig,

    der kommt und geht wie per Zufall gesteuert.

    Dank an Musashi für die Erhellung, jetzt habe ich kapiert worum es dabei geht.

    Das war mein Gedankenfehler, denn ich nutze diese Variablen ja nur in meiner Funktion und nicht ausserhalb.

    Das wäre eigentlich sinnfrei, aber Globale Variablen behalten ihre Werte auch nach Funktionsende, aber hast Recht dafür kann ich ja dann Local Static verwenden. Aber diese Local Static kannte ich damals noch nicht.

    Aber stimmt schon wenn ich die Variable tatsächlich auch ausserhalb der Funktion verwenden will, müsste ich sicherstellen, daß die entsprechende Funktion vorher mindestens einmal durchlaufen wird.

    Man lernt nie aus.

  • Ein Frage an alpines , wenn ich die Globale Variable in der Funktion so deklariere wie ich es in der

    auskommentierten Zeile stehen habe, sollte es aber doch auch machbar sein ohne Probleme oder nicht?

    Bei meiner Variante wird die Globale Variable nur dann deklariert wenn sie noch nicht exisitert,

    die Deklarierung wird also maximal einmal durchgeführt.

    Ich habe nicht viel aber doch ein paar Scripte, wo mir das als beste Löung erschien.

    Musashi hatte bereits einen wichtigen Punkt angesprochen.

    Es geht nicht darum zu prüfen, ob eine globale Variable bereits deklariert wurde. Die globale Variable $g_sString2 ist erst global verfügbar, nachdem Du eine Funktion aufrufst.

    Das wäre die erste Sache. D.h. du erzwingst in deinem Skriptverlauf Implikationen damit alles fehlerfrei abläuft. In diesem Fall musst du erst die Funktion zur Deklaration der Variablen aufrufen damit du diese nutzen kannst.

    Das kann und wird dir viele viele Warnungen schmeißen, da Au3Check nicht sicher sein kann, ob du diese Implikationen auch einhältst.

    Darum erzeugen wir unsere globale Variablen vorher im Skript und setzen sie nachher wenn wir sie benötigen. Wenn möglich sogar direkt, damit wir uns später ein paar Zeilen sparen.

    Schneidere deine Variablen immer auf den engsten Scope wie nur irgendwie möglich, damit du, bspw. in einer Funktion, nur kurz hochscrollen musst um zu sehen ob du auf eine lokale oder globale zugreifst.

    Nichtsdestotrotz:

    Du kannst mit Globalen Variablen in Funktionen trotzdem programmieren, das erlaubt dir ja der Interpreter, allerdings wirst du bei der Fehlersuche mehr Zeit aufwenden, vor allem bei Fehlern die nicht direkt ersichtlich sind.

  • Domi78 10. Mai 2019 um 09:26

    Hat das Label [ offen ] entfernt.
  • Hi, nochmal kurz als Abschluss für dieses Thema und zur Vervollständigung (und für jeden, der das Problem auch mal haben sollte):

    Wenn Ihr unbedingt keine Trennzeile haben möchtet, aber trotzdem ein Untermenü direkt darüber oder darunter haben möchtet, ist das auch möglich. Dazu muss nur diese Option gesetzt werden:

    Code
    AutoItSetOption("TrayMenuMode", 8)

    Achtet dann aber darauf, dass die Radiobuttons nicht mehr automatisch umgeschaltet werden. Ihr müsst das dann selbst in euer Skript für jeden Radiobutton einzeln einprogrammieren.

    Der Grund ist der, da bei der Erstellung eines Radiobuttons die Zeile darüber und darunter überprüft wird, ob es auch ein Radiobutton ist. Nur so können automatisch Gruppen erstellt werden, zwischen denen der ausgewählte Radiobutton hoch und runter springen kann. Als Abgrenzung der Gruppen dienen Trennlinien (oder normale Einträge), jedoch keine Untermenüs, da diese sonst den Fehler verursachen. Nutzt man die oben angegebene Einstellung, werden keine automatischen Gruppen erstellt und man muss den Klick entsprechend selbst auswerten.

    So lange man aber nicht gerade besonders komplexe Radiobuttons haben möchte, empfehle ich eher die Verwendung der Trennlinie...