1. Dashboard
  2. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team
    4. Mitgliedersuche
  3. Forenregeln
  4. Forum
    1. Unerledigte Themen
  • Anmelden
  • Registrieren
  • Suche
Alles
  • Alles
  • Artikel
  • Seiten
  • Forum
  • Erweiterte Suche
  1. AutoIt.de - Das deutschsprachige Forum.
  2. Mitglieder
  3. AspirinJunkie

Beiträge von AspirinJunkie

  • _GDIPlus_ImageCalcDif

    • AspirinJunkie
    • 2. November 2025 um 19:33

    Grandios! "Script-Breaking" hinschreiben aber sich zum Inhalt komplett ausschweigen. "Internal optimisation" und fertig.

    Kein Mensch kann damit abschätzen in welchen Fällen es knallen wird. Sorry aber das ist wirklich wirklich unterirdisch unprofessionell.

    Edit: Ich rudere Mal ein Stück verbal zurück, da ich in dem Zusammenhang auch nichts von Script Breaking lese bislang.

  • PCIe 5 SSD

    • AspirinJunkie
    • 2. November 2025 um 08:31

    Ja das sind ja dann entsprechende Anwendungen.
    Diese habe ich persönlich nicht.
    Das habe ich vor einiger Zeit auch realisiert und daher hab ich da jetzt einen anderen Blick darauf.

    Aber dein Vergleich ging ja anscheinend allgemein SATA SSD --> M2. SSD.
    Ja das können tatsächlich heftige Unterschiede sein.
    Aber ob eine SSD 5.000 MBit/s schafft oder 15.000 Mbit/s wird (wenn man nicht, wie du, die entsprechenden Anwendungsfälle hat) man kaum bemerken (insb. beim angesprochenen USB3-Speicher-Kopieren ist man in beiden Fällen schon über dem Maximum).

    Zum Geraderücken: Das war nur für mein persönliches Anwendungsverhalten meine ganz eigenen Erkenntnisse zum Thema Performance.
    Wollte dir die SSD natürlich nicht madig reden (die ist offensichtlich ja wirklich gut). War nur ein allgemeiner Gedankengang zur Performancediskussion.

  • PCIe 5 SSD

    • AspirinJunkie
    • 1. November 2025 um 19:23

    Was habt ihr für Anwendungen wo derart hohe Datenraten relevant sind?
    Seit einigen Jahren habe ich für mich festgestellt, dass jegliche Hardware auf dem Markt die notwendige Performance für nahezu alle Dinge die ich mit dem PC mache mitbringt.
    Seither schaue ich nicht mehr auf die Performance sondern nur noch auf andere Dinge wie Ergonomie, Akkulaufzeit, Portabilität etc.
    Ich habe mir vor etwa einem Jahr für mein Surface eine neue SSD gegönnt wegen der Größe (256 GB --> 1 TB).
    Da das damalige absolute Topmodell für die Bauform M2 2230 (Corsair MP600 Mini R2) nur unwesentlich teurer war als der Rest dachte ich mir: OK gönnst du dir halt mal High-End.
    Die Benchmarks bestätigen das auch. Die neue liefert nun ~7.000 MBit/s. Deutlich mehr als die eingebaute SSD mit ~2000 Mbit/s.
    Nur wenn ich ehrlich bin: Ich merke davon schlicht nichts im Alltag im Vergleich zu vorher.
    Es ist im Grunde nur eine Zahl.
    Vielleicht habe ich sogar eher Nachteile, da ich ja den Performancesprung nicht bemerke aber dafür weniger Akkulaufzeit z.B. habe da das Ding mehr Strom zieht oder wärmer wird oder sowas.
    Ich weiß es nicht.

    Zitat von argumentum

    "Chris Titus Tech's Windows Utility"

    Zitat von Kanashius

    Ich kann dabei Atlas OS ( https://atlasos.net/ ) empfehlen.

    Oh so langsam schließt sich der Kreis wieder.
    Genau das war der Grund wie ich zu AutoIt gekommen bin.
    Ich war damals (>20 Jahre her) äußerst aktiv in der Welt von nLite.
    Und AutoIt war für diverse Automatisierungen im Zuge des Setups hilfreich.
    Ich war dort im Forum auch Moderator und habe so etwa 10x in der Woche XP installiert mit dem Ziel irgendwann ein möglichst perfekt entschlacktes, schlankes und kleines XP-Installations-Image zu erzeugen.

    Warum? Nun für uns war damals XP einfach ein riesenhaufen Bloatware-verseuchtes überladenes Monstrum, welches den Anwender wo es nur ging gängelte und versucht hat Zeug unterzuschieben was niemand braucht.
    Mal so als kleiner Wink an die Fraktion mit der Nostalgiebrille die heute über Win11 herziehen und glauben es war früher besser.

    Am Ende passe ich heute immer noch mein Windows meinen Bedürfnissen an.
    Aber nicht mal im Ansatz so exzessiv wie damals.
    Performance kostet ja heute nichts mehr im Vergleich zu damals - da kann man mit mehr drumherum leben.

    Aber nun als Tipp für Leute die sich ihre Win11-Installation individualisieren möchten: Windows bringt in Form der autounattended.xml im Grunde bereits alles mit.
    Die Datei erstellt man sich einmal, schmeißt sie mit in seine Windows-Installation und hat sein Windows dann so wie man es sich wünscht.
    Und anstatt sich durch die Doku zu wälzen gibt es eine super Seite wo man sich seine autounattend.xml zusammenklicken möchte wie man es braucht:
    Generate autounattend.xml files for Windows 10/11

  • MachMichVoll (MP3 zu Stick kopieren bis er voll ist)

    • AspirinJunkie
    • 31. Oktober 2025 um 14:52

    Ich finde es klasse!
    Es ist sowohl übersichtlich - auch ein fremder Betrachter weiß sehr schnell was das Skript wie macht und zum anderen hast du Fehlermanagement implementiert um auf verschiedene ungeplante Dinge zu reagieren.
    Und da das Skript offensichtlich genau das macht, was es soll, ist eigentlich schon 100% auf der Liste abgearbeitet.

    Um deine Übersichtlichkeit noch weiter zu erhöhen hätte ich ein paar Vorschläge.
    Wichtig ist aber, dass diese an der Funktionalität selbst nichts ändern - es geht eher um Code-Ästhetik.

    Aktuell liest du die die Datei mit der Funktion _FileReadToArray() ein.
    Standardmäßig gibt diese die Anzahl der Elemente im ersten Element ($Array[0]) zurück.
    Damit iteriert man über alle Elemente des Arrays mit der Form For $i = 1 To $Array[0] anstatt per For $i = 0 To Ubound($Array) - 1.
    Das kann hübscher sein, hat aber einen Haken: Du nimmst die Schleife um einzeln auf die ganzen Elemente des Arrays zuzugreifen.
    Dazu verwendest du (logischerweise) die Form $HSPSerieTitel[$Titelnummer].
    Es gibt aber noch eine andere Form der For-Schleife - nämlich die For-In-Schleife.
    Diese geht einfach über alle Elemente des Arrays und schmeißt diese in eine benannte Variable.
    Man spart sich damit die Index-Behandlung und das ganze wird deutlich übersichtlicher.
    In deinem Fall hier sollte aus meiner Sicht diese Variante die schönere sein (Beispiel folgt unten), denn anstatt immer in der Schleife zu schreiben $HSPSerieTitel[$Titelnummer], reicht dann ein $AktuellerTitel und $HSPSerieTitel kann ganz verschwinden.

    Dazu muss man aber die Anzahl aus dem ersten Element bekommen, sonst behandelt die For-In-Schleife diese ebenfalls als normales Element.
    Bei _FileReadToArray() kann man dazu das Flag $FRTA_NOCOUNT setzen oder man nimmt gleich das Pendant FileReadToArray (ohne Unterstrich).

    Bei _FileListToArray() bekommt man die Anzahl hingegen leider nicht so einfach weg, so dass du das mit deiner For-To-Schleife schon auf dem besten Weg bist (ich persönlich verwende stattdessen aus dem Grund direkt FileFindFirstFile/FileFindNextFile - aber das muss hier nicht sein).

    Nun zu deiner Frage mit FileOpen/FileClose.
    Man kann eine Datei "öffnen", dann wird ein sogenannter FilePointer auf die Datei (genauer auf eine bestimmte Stelle in der Datei) erstellt und gehalten.
    Das muss im Grunde immer gemacht werden wenn mit einer Datei gearbeitet wird.
    Manuell macht das in AutoIt aber eigentlich nur Sinn wenn du mehrere Operationen auf eine Datei ausführen möchtest (z.B. mehrere FileRead oder FileReadLine oder FileWrite usw.).
    Die meisten Funktionen in AutoIt machen nämlich selbst das FileOpen/FileClose wenn man nur den Dateinamen angibt.
    So auch _FileReadToArray(). Das heißt du brauchst hier gar nicht FileOpen/FileClose, da sich _FileListToArray schon darum kümmert.
    Und in deinem Fall war das leider auch sowieso wirkungslos, da man den Rückgabewert von FileOpen (das sogenannte FileHandle) dann in den File-Funktionen weiterverwendet anstatt dem Dateinamen.

    Das heißt konkret den Anfang deiner Region 2 könnte man folgendermaßen umschreiben:

    AutoIt
    #Region 02 - HSP
    
    ;große Schleife Serientitel aus Datei
    For $AktuellerTitel In FileReadToArray($ListeTXT)
    
    	;Ordner einer Serie erfassen
    	$ArrayEpisodenOrdner = _FileListToArray($HoerspielRoot & $AktuellerTitel, "*", $FLTA_FOLDERS)

    Aus meiner Sicht übersichtlicher, aber am Ende immer noch eine Geschmacksfrage.
    Der Effekt bleibt dennoch der gleiche - das Skript macht weiter was es soll.

    Zitat von Seppuku

    3) Beim If-Block If $KopieReturn = 0 Then hab ich in einer früheren Version If @error Then benutzt. Das hat aber nicht funktioniert und ich kapiere das überhaupt nicht.

    Das ist ganz von der jeweiligen Funktion abhängig. Eine Funktion hat 3 Ausgabemöglichkeiten (von ByRef-Parametern mal abgesehen): Den Return-Wert, den @error-Wert und den @extended-Wert.
    Ob und wie diese genutzt werden ist Sache der Funktion. Bei Funktionen die keinen wirklichen Rückgabewert benötigen (wie eben DirCopy) wird dort gerne ein Erfolgswert zurückgegeben.
    In dem Fall braucht man dann also kein @error mehr, da das schon durch den Return-Wert abgedeckt wird.
    Du musst also für jede Funktion schauen wie ihre Ausgaben funktionieren - daran kommst du nicht vorbei.
    Und ein Beispiel wo man unbedingt @error braucht ist im Grunde jede Funktion wo der Rückgabewert schon belegt ist. Z.B. eben _FileListToArray. Dort muss die Fehlerinformation auf anderem Wege erfolgen, da der Nutzer als Rückgabe ja ein Array erwartet und keinen Erfolgswert.

  • JSON UDF - beim erweitern eines JSON werden Escapezeichen geschrieben

    • AspirinJunkie
    • 12. Oktober 2025 um 21:52

    Ich hab's nicht ganz herausgelesen: Ist dein Problem gelöst oder ist noch eine Frage offen geblieben?


    Zitat von Yaerox

    Ich mache ein curl an die gleiche API aber einen anderen Controller. Der gibt ebenfalls JSON zurück. Den Output schreibe ich in eine Datei. Die Datei lese ich ein, mache ein

    Der Umweg über Dateien klingt etwas unnötig. Man kann die Ausgabe von curl auch direkt mit AutoIt weiterverarbeiten (mit StdOutRead).

    Und anstatt curl sollte in den allermeisten Fällen auch ein InetRead() reichen.

  • JSON UDF - beim erweitern eines JSON werden Escapezeichen geschrieben

    • AspirinJunkie
    • 9. Oktober 2025 um 21:24

    Hier fehlt ein bisschen was in deinem größeren Codebeispiel.
    Du hast erst einen JSON-String in der Variable $sString definiert.
    Danach machst du ein _JSON_addChangeDelete() auf die Datenstruktur $oJSON_Ad - keine Ahnung wo die auf einmal herkommt.

    Was ist das für eine Datenstruktur? Wo kommt die her?
    Egal - wir gehen mal davon aus, dass das eine gültige Datenstruktur ist und diese offensichtlich eine Map ist, welche den Key "images" besitzt oder diesen erhalten soll.

    Das Problem bei dir ist, dass du der Map $oJSON_Ad gar keine Datenstruktur hinzufügst sondern einfach nur den JSON-String. Es ist kein Array mit 3 Maps als Elementen - nein es ist einfach nur eine Zeichenkette.
    Und da diese Zeichenkette Zeichen enthält die in JSON eine Bedeutung haben müssen diese natürlich escaped werden.

    Kurz: Du musst aus dem JSON-String erstmal eine AutoIt-Datenstruktur machen - also ein _JSON_Parse. Sonst fügst du einfach nur einen langweiligen String hinzu und keine dadurch beschriebene Datenstruktur.

    Mal als Code zum besseren Verständnis:

    AutoIt
    #include "JSON.au3"
    
    ; eine Map, welche die Datenstruktur in $oJSON_Ad repräsentieren soll
    Global $oJSON_Ad[]
    $oJSON_Ad["Test"] = "Testwert" ; ein Beispielwert in der Map
    
    ; der Return-Wert der API als String (wichtig - es ist nur eine Zeichenkette - noch keine AutoIt-Datenstruktur!)
    $sAPIReturn = '{"ref":"https://blabla","hash":"3882db"}'
    
    ; erhaltenen JSON-String in eine AutoIt-Datenstruktur überführen
    $oMyStructure = _JSON_Parse($sAPIReturn)
    
    ; die erhaltene Datenstruktur als 3 Elemente eines Arrays wiederholen:
    Local $aArray[] = [$oMyStructure, $oMyStructure, $oMyStructure]
    
    ; zum Testen mal in einen JSON-String überführen und ausgeben lassen:
    ConsoleWrite(_JSON_GenerateCompact($aArray) & @CRLF & @CRLF)
    
    ; Das Array mit den 3 Elementen der Map $oJSON_Ad hinzufügen
    $oJSON_Ad["images"] = $aArray
    
    ; Das Endresultat ausgeben:
    ConsoleWrite(_JSON_Generate($oJSON_Ad) & @CRLF)
    Alles anzeigen


    Mal zum Grundverständnis der UDF:
    JSON ist einfach nur ein Format, welches verschachtelte Datenstrukturen in Textform abbildet.
    Ich kann z.B. in Python Dictionaries, Arrays, Strings, Zahlen etc. in irgendeiner verschachtelten Form in einer Variablen gespeichert haben und überführe dies in einen JSON-String.
    In irgendeiner anderen Programmiersprache schnappe ich mir dann den String und bilde diese Datenstruktur anhand des JSON-Strings dort nach.
    JSON ist also nur ein Textformat, welches die Datenstrukturen in Textform gießt zum einfachen Austausch - nicht mehr und nicht weniger.

    Das heißt im Grunde in der ganzen Prozessierung taucht JSON in dem ganzen Prozess nur zweimal auf: Einmal um einen externen _JSON-String in eine AutoIt-Datenstruktur zu überführen: Das macht _JSON_Parse() und einmal am Ende wenn man aus der AutoIt-Struktur einen _JSON_String erzeugen möchte der diese Struktur wiedergibt: Das macht _JSON_Generate() bzw. _JSON_GenerateCompact().

    Alles dazwischen ist im Grunde völlig unabhängig von JSON. Es sind reine AutoIt-Datenstrukturen und müssen auch so behandelt werden.
    Also Maps, Arrays, Strings, Zahlen usw. und üblicherweise auch ineinander verschachtelt.
    Da der Umgang mit derart verschachtelten Daten in AutoIt nicht immer ganz trivial ist, gibt es in der UDF Hilsfunktionen um mit diesen verschachtelten Daten besser zu arbeiten: _JSON_Get() und _JSON_addChangeDelete(). Die haben eigentlich gar nichts mit JSON zu tun sondern nur mit verschachtelten reinen AutoIt-Datenstrukturen. Aber da sie im Kontext von JSON sehr oft notwendig sind tragen sie dies mit im Namen.

    Also kurz: Wenn du einen JSON-String bekommst - egal wann, egal woher - das erste was du machst ist diesen mit _JSON_Parse() in eine AutoIT-Datenstruktur zu überführen.
    Alles was du dann mit den Daten machst ist rein auf Ebene von AutoIt und unabhängig von JSON.
    Je nachdem ob es sinnvoll ist kannst du hierbei die Funktionen _JSON_Get() und _JSON_addChangeDelete() zu Hilfe nehmen aber mit JSON hat das in dieser Phase nichts zu tun.
    Erst wenn du wieder einen JSON-String sehen willst (z.B. beim Ausgeben in eine Datei) dann überführst du die AutoIt-Datenstruktur in einen JSON-String per _JSON_Generate() bzw. _JSON_GenerateCompact().

  • xlsxNative - XLSX/XLSM-Dateien ohne Excel einlesen und erzeugen

    • AspirinJunkie
    • 9. Oktober 2025 um 11:03

    Es gab einige Anpassungen innerhalb der UDF:

    1. Schreiben von Excel-Funktionszellen

    _xlsx_WriteFromArray() kann nun auch Excel-Funktionen schreiben. Hierzu muss der Elementwert im Eingabearray ein String sein der mit einem = beginnt. Der String selbst wird dann als Excel-Funktion interpretiert.

    Beispiel: =IF(F2>E2,"yes","no")

    Hinweis: Damit Excel das korrekt interpretiert, ist ausschließlich die englische Notation zulässig.

    Sollte ein String der nicht als Funktion interpretiert werden soll geschrieben werden der aber mit einem = beginnt, dann muss dieses erste = durch Dopplung (==) escaped werden.

    2. Kleinstmögliche .xlsx-Ausgabedateien

    Die mit _xlsx_WriteFromArray() erzeugte .xlsx-Datei ist konsequent auf minimale Größe hin optimiert worden. Die hiermit erzeugten Dateien bewegen sich nah am möglichen Minimum des Dateiformates für die jeweiligen Daten.

    Beispielsdatensatz: [[1,2,3],[4,5,6]]

    ToolDateigröße
    Excel8.45 KB
    _xlsx_WriteFromArray()1.23 KB

    3. Formatierung von Datum und Zeit

    Wenn ein Elementwert im Eingabearray für _xlsx_WriteFromArray() ein Datum oder eine Zeit enthält, dann wird die Zelle in der .xlsx-Datei entsprechend als Datums-, Zeit- bzw. Datum/Zeit-Stil formatiert.

    Das Stringformat für diese Zellen muss hierbei folgendermaßen aufgebaut sein:

    WasFormat
    DatumYYYY-MM-DD
    ZeitHH:MM[:SS[.mmmmmm]]
    Datum + ZeitYYYY-MM-DD[T ]HH:MM[:SS[.mmmmmm]]

    Hinweis: Datum sowie Datum+Zeit bleiben als Stringwert erhalten. Eine reine Zeit hingegen wird als Zahl (Excel-Notation bei der 24h = 1.0) kodiert.

    Bugfixes und Stil

    • _xlsx_2Array() kann nun auch mit Dateien umgehen, deren sharedstrings.xml-Elemente mit einem Präfix versehen sind (= höhere Kompatibilität).
    • _xlsx_2Array() liest nun auch Dateien die Leerzeilen überspringen (= höhere Kompatibilität)
    • Au3Check wirft keine (teilweise falschen) Warnungen mehr bei Verwendung der UDF.
  • Datumsformat

    • AspirinJunkie
    • 25. September 2025 um 10:00
    Zitat von Peter S. Taler

    AM bedeutet Vormittag (die Zeit zwischen 00:00 und 12:00) ---> 12:00 AM = Mittags 12:00 --> Da stimmt der Code

    Das entspricht aber nicht den Standards.
    Für die US-Verwaltung z.B. gilt explizit >>folgende Vorgabe<< in deren offiziellen Style-Guide:

    Code
    9.54. References to meridian in statements of time are abbreviated as 
    follows:
    12 p.m. (12 noon)
    12 a.m. (12 midnight)

    Das handhaben auch alle mir bekannten Online-Converter und Programmierbibliotheken so (einfach mal probieren).

    Spannender ist die Behandlung von 00:00 AM/PM. Beide sollte es nicht geben, da im 12h-System nur die Werte 01-12 zugelassen sein sollten.
    Manche Konverter bringen daher hierbei einen Fehler, andere lassen zumindest 00:00 AM = 12:00 AM zu. Wirklich undefiniert ist hingegen 00:00 PM.
    Halb Eins Nachts ist demzufolge 12:30 AM - 00:30 AM wäre nämlich streng genommen auch nicht zulässig.
    Habe es auch mal gerade unter Python probiert und das eingebaute datetime.strptime schmeißt mir im Fall von 00:30:00 AM auch folgerichtig einen Fehler.

  • AutoIt 3.3.18.0 - bereits getestet?

    • AspirinJunkie
    • 15. September 2025 um 14:32

    Ich konnte die Messung über ProcessSetPriority noch stabilisieren.
    Die Ergebnisse nun zeigen dann doch ein klares Bild: Die 3.3.18.0 ist tatsächlich immer ein paar Prozentpunkte der 3.3.16.1 voraus:

    Markdown
    | Test                                      | 3.3.16.1 | 3.3.18.0 | Δ in % |
    | ----------------------------------------- | -------- | -------- | ------ |
    | GetCurrentProcessId (no params)           | 2,3 µs   | 2,3 µs   | 0,0%   |
    | GetTickCount (no params)                  | 2,3 µs   | 2,2 µs   | 1,9%   |
    | GetTickCount (no params)                  | 2,3 µs   | 2,2 µs   | 2,5%   |
    | GetLastError (no params)                  | 2,3 µs   | 2,2 µs   | 3,0%   |
    | GetLastError (no params)                  | 2,3 µs   | 2,2 µs   | 3,2%   |
    | lstrlenW (100 chars)                      | 3,5 µs   | 3,3 µs   | 3,2%   |
    | GetCurrentProcessId (no params)           | 2,4 µs   | 2,3 µs   | 3,4%   |
    | SetLastError (1 DWORD Parameter)          | 3,3 µs   | 3,2 µs   | 3,5%   |
    | lstrlenW (4 chars)                        | 3,4 µs   | 3,3 µs   | 4,0%   |
    | lstrlenW (10000 chars)                    | 7,0 µs   | 6,7 µs   | 4,8%   |
    | GetSystemTime (struct SYSTEMTIME)         | 5,9 µs   | 5,6 µs   | 5,4%   |
    | Sleep(0) (1 DWORD Parameter)              | 4,1 µs   | 3,8 µs   | 6,4%   |
    | RtlMoveMemory (1 KB)                      | 7,1 µs   | 6,6 µs   | 6,9%   |
    | RtlMoveMemory (1 MB)                      | 53,6 µs  | 49,9 µs  | 6,9%   |
    | GetSystemTimeAsFileTime (struct FILETIME) | 4,7 µs   | 4,3 µs   | 8,4%   | 
    Alles anzeigen
  • AutoIt 3.3.18.0 - bereits getestet?

    • AspirinJunkie
    • 15. September 2025 um 11:52

    Ja das wäre eine mögliche Interpretation.
    Hab das auch gleich mal so getestet - aber auch das sehe ich kein relevantes Muster:

    Code
             Test                             3.3.16.1   3.3.18.0  Δ in %
    ---------------------------------------------------------------------
    GetCurrentProcessId (no params)            2,4 µs	 2,4 µs	    1,6%
    GetTickCount (no params)                   2,3 µs	 2,3 µs	    1,6%
    GetLastError (no params)                   2,5 µs	 2,3 µs	    7,1%
    GetCurrentProcessId (no params)            2,4 µs	 2,4 µs	    3,0%
    GetTickCount (no params)                   2,4 µs	 2,3 µs	    6,4%
    GetLastError (no params)                   2,4 µs	 2,3 µs	    3,8%
    Sleep(0) (1 DWORD Parameter)               4,1 µs	 3,8 µs	    7,9%
    SetLastError (1 DWORD Parameter)           4,0 µs	 3,3 µs	   18,0%
    lstrlenW (4 chars)                         3,8 µs	 3,3 µs	   12,0%
    lstrlenW (100 chars)                       3,5 µs	 3,4 µs	    4,9%
    lstrlenW (10000 chars)                     6,9 µs	 6,7 µs	    3,1%
    GetSystemTime (struct SYSTEMTIME)          5,7 µs	 6,0 µs	   -4,6%
    GetSystemTimeAsFileTime (struct FILETIME)  4,3 µs	 4,5 µs	   -4,5%
    RtlMoveMemory (1 KB)                       6,8 µs	 6,9 µs	   -2,3%
    RtlMoveMemory (1 MB)                      51,7 µs	50,6 µs	    2,1%
    Alles anzeigen
  • AutoIt 3.3.18.0 - bereits getestet?

    • AspirinJunkie
    • 15. September 2025 um 08:03

    Mich hat vor allem der folgende Eintrag im Changelog interessiert:

    Zitat

    Added #3891: DllCall() performance optimisation.

    Was genau gemacht wurde steht da nicht und im verlinkten Ticket wird sich im Grunde auch ausgeschwiegen.
    Da steht nur "Internal optimisation to not allocate data at each DllCall".
    Das ist umso verwirrender, da im Ticket steht, dass dieses bereits in 3.3.16.1 umgesetzt wurde.

    Ich wollte daher mal herausfinden, was diese Änderung konkret ausmacht und habe mal verschiedene Szenarien für DllCall mit folgendem Skript getestet:

    AutoIt
    #include <Array.au3>
    #include <String.au3>
    
    Global Const $iRUNS = 1e5 ; number of iterations for each test
    Global $aResults[0][2] ; result array
    Global Const $hDLLKernel32 = DllOpen("kernel32.dll"), $hDLLUser32 = DllOpen("user32.dll")
    
    
    ConsoleWrite("===========================================" & @CRLF & _
                 "DllCall Performance Benchmark" & @CRLF & _
                 "AutoIt Version: " & @AutoItVersion & @CRLF & _
                 "Iterations: " & $iRUNS & @CRLF & _
                 "===========================================" & @CRLF & @CRLF)
    
    ; Warm-up (for waking the CPU)
    For $i = 1 To 1e6
        DllCall($hDLLKernel32, "DWORD", "GetTickCount")
    Next
    
    ; determine overhead for the loop itself
    Global $iOverhead = TimerInit()
    For $i = 1 To $iRUNS
    Next
    $iOverhead = TimerDiff($iOverhead)
    
    
    ; run the test
    ConsoleWrite("=== Test 1: functions without parameters ===" & @CRLF)
    _Test_NoParams()
    ConsoleWrite(@CRLF)
    
    ConsoleWrite("=== Test 2: functions with simple parameters ===" & @CRLF)
    _Test_SmallParams()
    ConsoleWrite(@CRLF)
    
    ConsoleWrite("=== Test 3: functions with string parameters ===" & @CRLF)
    _Test_StringParams()
    ConsoleWrite(@CRLF)
    
    ConsoleWrite("=== Test 4: functions with dll structs ===" & @CRLF)
    _Test_StructParams()
    ConsoleWrite(@CRLF)
    
    ConsoleWrite("=== Test 5: memory operations ===" & @CRLF)
    _Test_MemoryOps()
    ConsoleWrite(@CRLF)
    
    
    ; print results
    ConsoleWrite("===========================================" & @CRLF)
    ConsoleWrite("Results" & @CRLF)
    ConsoleWrite("===========================================" & @CRLF)
    
    For $i = 0 To UBound($aResults) - 1
        ConsoleWrite(StringFormat("%-50s % 10.3f µs\n", $aResults[$i][0], $aResults[$i][1] * 1000 / $iRUNS))
    Next
    
    ConsoleWrite(@CRLF)
    
    
    
    
    ; Test 1: functions without parameters
    Func _Test_NoParams()
    
    	; GetCurrentProcessId
        Local $hTimer = TimerInit()
        For $i = 1 To $iRUNS
            DllCall($hDLLKernel32, "DWORD", "GetCurrentProcessId")
        Next    
        Local $fTime = TimerDiff($hTimer)
        _PrintTestResult("GetCurrentProcessId (no params)", $fTime)
        
        ; GetTickCount
        $hTimer = TimerInit()
        For $i = 1 To $iRUNS
            DllCall($hDLLKernel32, "DWORD", "GetTickCount")
        Next    
        $fTime = TimerDiff($hTimer)
        _PrintTestResult("GetTickCount (no params)", $fTime)
        
        ; GetLastError
        $hTimer = TimerInit()
        For $i = 1 To $iRUNS
            DllCall($hDLLKernel32, "DWORD", "GetLastError")
        Next    
        $fTime = TimerDiff($hTimer)
        _PrintTestResult("GetLastError (no params)", $fTime)
    EndFunc
    
    ; Test 2: functions with simple parameters
    Func _Test_SmallParams()
        ; Sleep with 0 ms 
        Local $hTimer = TimerInit()
        For $i = 1 To $iRUNS
            DllCall($hDLLKernel32, "NONE", "Sleep", "DWORD", 0)
        Next    
        Local $fTime = TimerDiff($hTimer)
        _PrintTestResult("Sleep(0) (1 DWORD Parameter)", $fTime)
        
        ; SetLastError
        $hTimer = TimerInit()
        For $i = 1 To $iRUNS
            DllCall($hDLLKernel32, "NONE", "SetLastError", "DWORD", 0)
        Next    
        $fTime = TimerDiff($hTimer)
        _PrintTestResult("SetLastError (1 DWORD Parameter)", $fTime)
    EndFunc
    
    ; Test 3: functions with string parameters
    Func _Test_StringParams()
        ; short String
        Local $tCharStruct = DllStructCreate("WCHAR[5]")
    	Local $hPtr = DllStructGetPtr($tCharStruct)
    	DllStructSetData($tCharStruct, 1, "Test")
        Local $hTimer = TimerInit()    
        For $i = 1 To $iRUNS
            DllCall($hDLLKernel32, "int", "lstrlenW", "PTR", $hPtr)
        Next    
        Local $fTime = TimerDiff($hTimer)
        _PrintTestResult("lstrlenW (4 chars)", $fTime)
        
        ; medium string
    	$tCharStruct = DllStructCreate("WCHAR[101]")
    	$hPtr = DllStructGetPtr($tCharStruct)
    	DllStructSetData($tCharStruct, 1, _StringRepeat("A", 100))
        $hTimer = TimerInit()    
        For $i = 1 To $iRUNS
            DllCall($hDLLKernel32, "int", "lstrlenW", "PTR", $hPtr)
        Next    
        $fTime = TimerDiff($hTimer)
        _PrintTestResult("lstrlenW (100 chars)", $fTime)
        
        ; long string
    	$tCharStruct = DllStructCreate("WCHAR[10001]")
    	$hPtr = DllStructGetPtr($tCharStruct)
    	DllStructSetData($tCharStruct, 1, _StringRepeat("B", 10000))
        $hTimer = TimerInit()    
        For $i = 1 To $iRUNS
            DllCall($hDLLKernel32, "int", "lstrlenW", "PTR", $hPtr)
        Next    
        $fTime = TimerDiff($hTimer)
        _PrintTestResult("lstrlenW (10000 chars)", $fTime)
    EndFunc
    
    ; Test 4: functions with dll structs
    Func _Test_StructParams()
        ; struct definitions
        Local $tSystemTime = DllStructCreate("word Year;word Month;word DayOfWeek;word Day;" & _
                                             "word Hour;word Minute;word Second;word Milliseconds")
    	Local $tFileTime   = DllStructCreate("DWORD dwLowDateTime;DWORD dwHighDateTime")
        
    	; GetSystemTime										   
        Local $hTimer = TimerInit()    
        For $i = 1 To $iRUNS
            DllCall($hDLLKernel32, "NONE", "GetSystemTime", "struct*", $tSystemTime)
        Next    
        Local $fTime = TimerDiff($hTimer)
        _PrintTestResult("GetSystemTime (struct SYSTEMTIME)", $fTime)
        
        ; GetSystemTimeAsFileTime 
        $hTimer = TimerInit()    
        For $i = 1 To $iRUNS
            DllCall($hDLLKernel32, "NONE", "GetSystemTimeAsFileTime", "struct*", $tFileTime)
        Next    
        $fTime = TimerDiff($hTimer)
        _PrintTestResult("GetSystemTimeAsFileTime (struct FILETIME)", $fTime)
    EndFunc
    
    
    ; Test 5: memory operations
    Func _Test_MemoryOps()
        Local $iSize   = 1024 ; 1KB
        Local $tSource = DllStructCreate("byte[" & $iSize & "]")
        Local $tDest   = DllStructCreate("byte[" & $iSize & "]")
        ; fill source with data
        For $i = 1 To $iSize
            DllStructSetData($tSource, 1, Random(0, 255, 1), $i)
        Next
        
    
    	; RtlMoveMemory 1 KB block
        Local $hTimer = TimerInit()
        For $i = 1 To $iRUNS
            DllCall($hDLLKernel32, "NONE", "RtlMoveMemory", _
                    "struct*", $tDest, _
                    "struct*", $tSource, _
                    "ulong_ptr", $iSize)
        Next    
        Local $fTime = TimerDiff($hTimer)
        _PrintTestResult("RtlMoveMemory (1 KB)", $fTime)
        
    
        ; RtlMoveMemory 1 MB block
        $iSize   = 1048576 ; 1 MB
        $tSource = DllStructCreate("byte[" & $iSize & "]")
        $tDest   = DllStructCreate("byte[" & $iSize & "]")
    	For $i = 1 To $iSize
            DllStructSetData($tSource, 1, Random(0, 255, 1), $i)
        Next
        
        $hTimer = TimerInit()    
        For $i = 1 To $iRUNS / 10
            DllCall($hDLLKernel32, "NONE", "RtlMoveMemory", _
                    "struct*", $tDest, _
                    "struct*", $tSource, _
                    "ulong_ptr", $iSize)
        Next    
        $fTime = TimerDiff($hTimer)
        _PrintTestResult("RtlMoveMemory (1 MB)", $fTime * 10)
    EndFunc
    
    
    
    ; Hilfsfunktion: Ergebnis hinzufügen
    Func _PrintTestResult($sTest, $fTime)
        Local $iN = UBound($aResults)
    
    	; add current result
        ReDim $aResults[$iN + 1][2]
        $aResults[$iN][0] = $sTest
        $aResults[$iN][1] = $fTime - $iOverhead
            
        ConsoleWrite(StringFormat("%-50s: % 10.2f µs\n", $sTest, ($fTime - $iOverhead) * 1000 / $iRUNS))
    EndFunc
    Alles anzeigen

    Die Ergebnisse habe ich dann zwischen der Version 3.3.16.1 und 3.3.18.0 gegenübergestellt und erhielt folgendes Ergebnis:

    Code
             Test                             3.3.16.1   3.3.18.0  Δ in %
    ---------------------------------------------------------------------
    GetCurrentProcessId (no params)            2,0 µs     2,0 µs    0,2%
    GetTickCount (no params)                   1,9 µs     1,9 µs    1,1%
    GetLastError (no params)                   1,9 µs     1,9 µs    0,0%
    GetCurrentProcessId (no params)            2,0 µs     2,0 µs   -0,2%
    GetTickCount (no params)                   1,9 µs     1,9 µs   -0,7%
    GetLastError (no params)                   1,9 µs     1,9 µs   -2,0%
    Sleep(0) (1 DWORD Parameter)               3,4 µs     3,4 µs    2,3%
    SetLastError (1 DWORD Parameter)           2,8 µs     2,8 µs    1,9%
    lstrlenW (4 chars)                         3,0 µs     2,9 µs    3,2%
    lstrlenW (100 chars)                       3,0 µs     3,0 µs    2,5%
    lstrlenW (10000 chars)                     6,3 µs     6,5 µs   -3,6%
    GetSystemTime (struct SYSTEMTIME)          5,3 µs     5,3 µs   -0,3%
    GetSystemTimeAsFileTime (struct FILETIME)  3,9 µs     4,7 µs  -20,4%
    RtlMoveMemory (1 KB)                       7,0 µs     6,3 µs   10,1%
    RtlMoveMemory (1 MB)                      52,2 µs    48,1 µs    7,8%
    Alles anzeigen

    Einen wirklichen Performancesprung kann ich nicht erkennen. Die Unterschiede lassen sich nichtmal signifikant von der Messungenauigkeit trennen.
    Ich habe (da im Ticket ja steht, dass dieses bereits mit 3.3.16.1 umgesetzt wurde) auch mal die Version 3.3.14.0 dagegen gehalten.
    Aber auch da sieht das Ergebnis ziemlich gleich aus.

    Ich bin daher ziemlich ratlos was es mit der ominösen DllCall performance optimisation auf sich hat.

  • JSON-UDF

    • AspirinJunkie
    • 8. September 2025 um 13:41

    Die JSON-UDF weiß nichts darüber wie du die Daten semantisch interpretieren möchtest.
    JSON kennt nur Syntax.
    Und hier haben wir auch noch den Fall, dass JSON das Konzept von 2D-Arrays nicht kennt.
    Es kennt nur zwei Datenstrukturen als Verschachtelungsebene: Listen (quasi 1D-Arrays) und Objekte (Key-Value-Strukturen).
    Und da JSON nur die Syntax betrachtet, kann sie z.B. aus deinem verschachtelten Array-In-Array nicht ableiten, dass dort das erste Element die Headereinträge meint und danach die Zeilen einen Bezug zu diesem Header haben.
    Semantik ist nicht die Aufgabe von JSON - und damit auch nicht von der UDF.
    Daher wird es dort auch keine Funktion geben die aus einem 2D-Array eben keine verschachtelte Liste, wie man es aus dem Aufbau der Datenstruktur ableiten würde, sondern eine Liste von Objekten - denn das gibt die Syntax schlicht nicht her und eine andere Interpretation auf die Daten zu finden ist Sache des Users selbst.

    Hierfür muss man sich also was eigenes basteln. Oder wie im Falle der 2D-Tabellenstruktur Funktionen nutzen die die Arrays eben als solche Tabellen interpretiert. Ich hatte hierzu mal die TableData-UDF gebastelt. Die macht im Grunde genau das was deine _ArrayToJson() macht. Sie konvertiert ein 2D-Array so in ein 1D-Array mit Maps als Elementen, dass die erste Zeile als Key-Namen interpretiert wird und man dann das gleiche Ergebnis z.B. so erreichen würde:

    C
    #include "TableData.au3"
    #include "JSON.au3"
    
    _Main()
    
    Func _Main()
        Local $aTable[][3] = _
            [ _
                ['Feature',             'Technologie',    'Status'], _
                ['REST API - User',     'Node.js',        'Fertig'], _
                ['Datenbank-Migration', 'SQL',            'Geplant'], _
                ['Frontend Dashboard',  'React',          'Im Review'], _
                ['Unit Tests - Auth',   'Python',         'In Arbeit'], _
                ['CI/CD Pipeline',      'GitHub Actions', 'Fertig'], _
                ['Performance Tuning',  'Go',             'Offen'] _
            ]
    
    	; 2D-Array als Tabellenobjekt mit Header betrachten und in Array von Maps konvertieren
    	Local $aObjects = _td_toObjects(_td_fromArray($aTable, True))
    
    	_WriteFile('.\output\TableData-table.json', _JSON_Generate($aObjects))
    EndFunc
    
    
    Func _WriteFile($sFile, $sText)
        Local Const $iUtf8NoBom = 256
        Local Const $iOverwriteCreation = 2 + 8
        Local Const $iMode = $iUtf8NoBom + $iOverwriteCreation
    
        Local $hFile = FileOpen($sFile, $iMode)
        FileWrite($hFile, $sText)
        FileClose($hFile)
    EndFunc
    Alles anzeigen

    Das ist halt mal eine Funktion, welche die Daten semantisch genauso interpretiert wie du es auch getan hast.
    Das hat mit JSON aber erstmal nichts zu tun sondern nur wie die Daten eben aufgefasst werden.
    JSON macht dann nur die Konvertierung zwischen dem JSON-String und der internen Datenstruktur - es interpretiert nichts.

    Der einzige Punkt bei dem die UDF eine Funktionalität anbietet um Datenstrukturen in andere zu konvertieren ist bei der Konvertierung zwischen 1D und 2D-Arrays (bzw. Array-In-Arrays). Dies ist jedoch schlicht nur der Fall, da hierfür eine Notwendigkeit besteht denn JSON kann wie gesagt nichts mit mehrdimensionalen Arrays anfange.

    Bei der Liste hingegen habe ich kein Pendant.
    Die Interpretation, dass der erste Eintrag eines 1D-Array der einzige Key einer Map sein soll und alle anderen Elemente als 1D-Array als Value dieses Keys behandelt werden sollen ist schlicht halt sehr individuell und bedarf daher auch einer individuellen Behandlung.

    Kurz: Ja klar kann man Daten hin und her transformieren wie man möchte - die JSON-UDF ist dafür halt nur der falsche Ort.

  • Windows Graphics Capture API (WinRT) Fullscreen Capturing Test

    • AspirinJunkie
    • 27. August 2025 um 11:37

    Ja klappt super! :love:

    30s 1920x1080@30FPS ergibt .webp-Datei mit 1,3 MB Dateigröße!

  • Welche DLLs benutzt mein Programm.

    • AspirinJunkie
    • 25. August 2025 um 16:39
    Zitat von DOheim

    Ich hätte nicht gedacht, dass mein mickriges Testprogramm mit 18 DLLs arbeitet.

    Dein Programm selbst nicht. Aber eine AutoIt-Exe ist nichts weiter als der Quellcode deines Programmes plus dem kompletten AutoIt-Interpreter. Und der stellt alle Funktionen von AutoIt zur Verfügung - egal was davon in deinem Skript genutzt wird oder nicht.

    Und das führt halt zu der relativ großen Anzahl an Abhängigkeiten.

  • Welche DLLs benutzt mein Programm.

    • AspirinJunkie
    • 25. August 2025 um 16:13

    Ich vermute mal, dass du lediglich den Quelltext heruntergeladen hast.

    Es gibt da einen Punkt "Releases". Dort findest du die kompilierten Versionen.

    Die aktuelle wäre diese hier: https://github.com/hasherezade/pe…64_win_vs22.zip

  • Welche DLLs benutzt mein Programm.

    • AspirinJunkie
    • 25. August 2025 um 15:15
    Zitat von DOheim

    1. PE-Bear > heruntergeladen und extrahiert.

    Aber wie nun weiter? Es gibt keine exe-Datei.

    Du hast doch dein Skript kompiliert oder nicht?
    Dann hast du doch deine Exe.
    Wenn man das mit deinem Beispielskript MsgBox(0,"Autonom","Hallo Welt") macht und diese .exe dann mit PE-Bear öffnet dann klickt man nur noch auf den Reiter "Imports" und dann siehst du direkt, welche DLL-Dateien er verwendet:

    Wenn du in der Liste einen Eintrag anklickst siehst du auch welche Funktionen er konkret aus der DLL bezieht.
    Die meisten DLLs wirst du nicht dazulegen müssen, da die bei Windows mitgeliefert werden.

  • Welche DLLs benutzt mein Programm.

    • AspirinJunkie
    • 25. August 2025 um 11:23
    Zitat von DOheim

    Ich glaube, dass es kein Programm gibt, welches eine .exe darauf untersuchen kann, ob sie eine DLL verwendet.

    ? Genau das machen doch die von mir vorgeschlagenen Programme.
    Die sagen, welche Symbole in der PE-Datei stecken und auf welche DLLs diese gelinkt sind.
    Damit kannst du also ermitteln von welchen DLL-Dateien das jeweilige Programm abhängig ist.

    Zitat von DOheim

    Gibt es eine Möglichkeit ein Autoit-Programm so zu kompilieren, dass es die verwendeten DLLs mit einbindet?

    Genau das ist ja das Gegenteil der Idee von Dlls: Wenn man die Inhalte einbindet wäre das eine statische Linkung und dann kann nur das jeweilige Programm diesen Code nutzen.
    Dlls hingegen verlagern den Code extern und ermöglichen so, dass verschiedene Programme den gleichen Code nutzen können.
    Wenn du Dlls dem Programm beifügen möchtest die nicht im System registriert sind, dann musst du sie im Grunde nur ins selbe Verzeichnis wie deine exe-Datei legen.

  • Welche DLLs benutzt mein Programm.

    • AspirinJunkie
    • 24. August 2025 um 11:49

    Da könnte die Software Dependency Walker weiterhelfen.


    Edit: Gibt wohl einen aktuelleren Nachbau als Open-Source: Dependencies

    Edit2: PE-Bear ist wohl auch einen Blick wert.

  • JSON-UDF

    • AspirinJunkie
    • 13. August 2025 um 12:29

    Es gibt eine neue Version.
    Diese bringt eine doch erhebliche Performancesteigerung mit.
    _JSON_Parse() ist in meinen Tests nun rund 40–55% schneller und bei _JSON_Generate() beträgt der Zuwachs rund 15–35%.

    Ich hätte eigentlich nicht gedacht, dass noch ein solches Potential im Code schlummert.
    Ich hatte jedoch noch ein paar Ansätze im Kopf, die zwar eine ziemliche Umstrukturierung bedingten, ich jetzt aber mal entsprechend angepackt habe.
    Es hat sich aus meiner Sicht gelohnt.

    In diesem Zuge habe ich noch die ByRef überall entfernt, so dass nun eine direkte Wertübergabe bei allen Funktionen möglich ist (war mal ein Wunsch).

    Außerdem habe ich die Readme.md noch um Hinweise zum Umgang mit .json-Dateien ergänzt.

  • GUi lässt sich nicht schließen

    • AspirinJunkie
    • 4. August 2025 um 09:59

    So können wir halt nicht viel testen.
    Ein Minimalskript (ein kleinstmögliches Skript, welches direkt lauffähig ist und das Problem reproduziert), wäre gut.
    Ich habe mir aus deinem Code mal ein solches Minimalskript gebastelt und bei mir tut der Code was er soll:

    AutoIt
    #include <WindowsConstants.au3>
    #include <StaticConstants.au3>
    
    ; Wichtig: Globale Variablen, da diese in mehreren Funktionen verwendet werden
    Global $hSpinnerGUI, $idLabel
    
    ; GUI aktivieren
    ShowSpinnerGUI("🔍 Searching for '" & "Test" & "'...")
    
    ; eine bestimmte Zeit warten
    Sleep(2000)
    
    ; GUI komplett löschen
    HideSpinnerGUI()
    
    ; nochmal warten um zu zeigen, dass das Skript nach dem GUI löschen weiter läuft
    Sleep(3000)
    ConsoleWrite("hier kommt noch was - das Skript lief also weiter")
    
    
    Func ShowSpinnerGUI($sText)
    	; Größe des Spinner-Fensters
    	Local $iWidth = 400
    	Local $iHeight = 80
    
    	; Position der Haupt-GUI ermitteln
    	Local $aPos[] = [@DesktopWidth/2, @DesktopHeight/2, 200, 200]
    	Local $iX, $iY
    
    	If @error Then
    		; Falls nicht bekannt, einfach zentriert am Bildschirm
    		$iX = -1
    		$iY = -1
    	Else
    		; Zentriert relativ zur Haupt-GUI
    		$iX = $aPos[0] + Int(($aPos[2] - $iWidth) / 2)
    		$iY = $aPos[1] + Int(($aPos[3] - $iHeight) / 2)
    	EndIf
    
    	; Fenster mit Popup und Dialog-Rahmen erstellen
    	$hSpinnerGUI = GUICreate("Search in progress...", $iWidth, $iHeight, $iX, $iY, BitOR($WS_POPUP, $WS_DLGFRAME), $WS_EX_TOPMOST)
    
    	; Label mit Text und Spinner
    	$idLabel = GUICtrlCreateLabel($sText & " ", 10, 30, 380, 40, $SS_CENTER)
    
    	; Hintergrundfarbe setzen (weiß)
    	GUISetBkColor(0xFFFFFF, $hSpinnerGUI)
    
    	; Schriftgröße und Fett
    	;GUICtrlSetFont($idLabel, 12, 600)
    	GUICtrlSetFont($idLabel, 12, 600, 0, "Consolas") ; 12pt, fett, nicht kursiv, Consolas
    	; Fenster anzeigen
    	GUISetState(@SW_SHOW, $hSpinnerGUI)
    
    	; Timer für Spinner starten
    	AdlibRegister("UpdateSpinnerLabel", 100)
    
    EndFunc   ;==>ShowSpinnerGUI
    
    
    ; Im Update-Loop nur Spinner-Zeichen austauschen, z.B. so:
    Func UpdateSpinnerLabel()
    	; Nur das rotierende Zeichen ändern, Text bleibt gleich lang
    	Local $sBaseText = "🔍 search for '" & "Test" & "'... "
    	Local $iSpinnerIndex = Random(1, 1000, 1)
    	GUICtrlSetData($idLabel, $sBaseText & " " & $iSpinnerIndex)
    EndFunc   ;==>UpdateSpinnerLabel
    
    
    Func HideSpinnerGUI()
    	AdlibUnRegister("UpdateSpinnerLabel")
    	If $hSpinnerGUI Then
    		Local $bSuccess = GUIDelete($hSpinnerGUI)
    		ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $bSuccess = ' & $bSuccess & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
    		$hSpinnerGUI = 0
    	EndIf
    EndFunc   ;==>HideSpinnerGUI
    Alles anzeigen

    Das Problem scheint also woanders zu liegen und muss durch dich eingegrenzt werden.
    Dazu den Code schrittweise ausdünnen bis nur noch der für das Problem essentielle Teil vorhanden ist - das angesprochene Minimalskript.

Spenden

Jeder Euro hilft uns, Euch zu helfen.

Download

AutoIt Tutorial
AutoIt Buch
Onlinehilfe
AutoIt Entwickler
  1. Datenschutzerklärung
  2. Impressum
  3. Shoutbox-Archiv
Community-Software: WoltLab Suite™