Beiträge von chesstiger

    Gruß Musashi

    P.S. : Es gibt im engl. Forum einen User namens Chesstiger - bist Du das ? Falls ja, editiere ich meinen Beitrag dort, sodass die Meriten an die richtige Adresse gehen :) .

    Musashi Yes, das bin ich. Trete da aber nicht wirklich in Erscheinung. Da ist mir die deutsche Community lieber.

    Aber schön, dass Jon mit Zugriff auf den Sourcecode zum selben Ergebnis kommt wie ich mit externen Tools. 8)


    Ansonsten gebe ich euch recht. Es wäre wirklich cool, wenn wir am Core mitarbeiten könnten. Im Endeffekt ist das zwar Jons gutes Recht - aber ich glaube, wir würden alle davon profitieren.

    Könnt ihr mal alle Nachteile für a3x Dateien nennen?

    Dazu müsste man erstmal wissen, was denn a3x-Dateien überhaupt sind. Zitat aus der Hilfe:

    Zitat

    Compiling Scripts with Aut2Exe
    Note: Scripts can be compiled with .a3x extension. They should be run with AutoIt.exe filename.a3x. The .a3x contains the script itself with all referred #include plus the FileInstall files. This format allows you to distribute smaller files as they don't include the AutoIt3.exe in each compiled script. You still need to have it accessible on the target machine but just AutoIt3.exe.

    Kurz zusammengefasst: Eine a3x-Datei enthält das Originalskript, alle Inludes und alle per FileInstall eingebundenen Dateien. Im Gegensatz zur exe-Datei fehlt hier aber der AutoIt-Interpreter (AutoIt3.exe). Der Interpreter muss also auf dem Zielsystem vorhanden sein.


    An Nachteilen bei deinem Anwendungsfall fällt mir da gerade ein... Nehmen wir an, Du schreibst Deine ganzen Skripte für den Editor unter AutoIt 3.3.14.5. Du erzeugst dann die entsprechende a3x-Datei, von den Includes her passt alles. Jetzt führe ich diese a3x-Datei auf meinem System aus - dummerweise habe ich AutoIt nach der Erstinstallation aber nie aktualisiert, also läuft bei mir alles mit 3.3.8.1. Du benutzt jetzt in deinem Skript aber Sprachfeatures (ich meine keine UDFs!), die aus neueren AutoIt-Versionen stammen. Eine kleine Auswahl dieser Fallstricke: Ternärer Operator, leere Arrays, Direktzugriff auf Indizes von Array-Ausdrücken (sowas: StringSplit(...)[0]), das Keyword Null, ObjGet mit Instanz-Angabe... Und dann gibt es Bruch. Denn meine "alte" AutoIt3.exe kann dein neues a3x-Skript nicht ausführen. Vermutlich würde das ganze einfach mit einem Syntax Error abschmieren.


    Ich schließe mich der Meinung der anderen an dieser Stelle an... Unterstütz einfach nur die aktuellste AutoIt-Version. Es gibt (fast*) keinen Grund, eine alte Version von AutoIt zu verwenden. Im Gegenteil: Solche Sachen wie der haarsträubende Hex-Fehler sind ein guter Grund, immer die aktuellste Variante zu nehmen.


    * PluginOpen war schon cool...

    Erster Durchlauf 16,219 Sekunden, zweiter Durchlauf 17,092 Sekunden. Das Phänomen ist also deutlich deutlich abgeschwächt, wenn nicht sogar verschwunden. Das kann eigentlich nur damit zusammenhängen, dass PeekMessageW mit Monitoring deutlich länger zum Ausführen braucht.

    Tja, beim nochmal lesen kommen einem schon mal Ideen... Nach ein paar Stunden hab ich den Wald vor lauter Bäumen nicht mehr gesehen. Das hat rein gar nichts mit dem beobachteten Phänomen zutun. PeekMessageW wird durch die Monitoring-Software quasi um eine konstante Zeit verlangsamt. Bei 1.000.000 Aufrufen lässt das den relativen, prozentualen Unterschied der beiden Messwerte natürlich erheblich schrumpfen. Aber der absolute Unterschied ist ja immernoch bei rund 0,85 Sekunden. Das ist in der selben Größenordnung wie die Differenz im ersten Durchgang. Von daher: Vergesst diesen Absatz. Die WinAPI-Aufrufe haben nichts mit der Verzögerung zutun, das ist rein AutoIt-Intern.


    Und danke für das Lob. Das ist wirklich ein spannendes Thema.


    Mars Die Error-Checks klingen gar nicht so unplausibel. Der nächste Schritt wäre jetzt, mit einem Tool wie IDA an die Sache ranzugehen und zu schauen, welche AutoIt-Internen Funktionen nach dem Erstellen einer GUI länger zum Ausführen brauchen.


    Edit: Es hat mir einfach keine Ruhe gelassen! Es gibt von Intel ein Tool namens VTune. Damit kann man super maschinennahe x86-Anwendungen profilen, d.h. hinsichtlich Geschwindigkeit optimieren. Der API-Monitor ist zwar cool, aber die Intel-Software liefert definitiv die besseren und verlässlicheren Daten. VTune ist dann in der Lage, genau aufzulisten, wie viel CPU-Zeit in welcher Funktion draufgegangen ist. Ohne den passenden Quellcode zur Binärdatei geht das leider nur eingeschränkt... Aber es geht. Ich habe also folgendes Programm kompiliert und mit VTune ausgeführt:

    Es ist also ein Programm, welches je nach Übergabe eines Kommandozeilenarguments vorher ein Fenster erstellt oder eben nicht. Das von AutoIt gemessene Ergebnis landet dann in einer Logdatei.


    VTune kennt mehrere Möglichkeiten, eine Anwendung zu profilen. Ich habe mich für die Detaillierteste entschieden, welche aber auch den meisten Overhead produziert: Auf Hardware-Basis, mit Stack-Verfolgung. Im Rahmen dieses Profilings hat die AutoIt-Anwendung selber folgende Zeiten ausgegeben:

    Code
    01:26:08> OHNE Fenster: 2262.843 ms
    01:26:53> MIT Fenster: 7075.408 ms

    Nicht ganz der Faktor 10, wie er sonst auf meiner Hardware auftritt, aber dennoch ist das Phänomen definitiv erkennbar.

    VTune misst zunächst mal grob die gesamte Ausführungszeit (also CPU + Idle) und dazu dann noch die gesamte CPU-Zeit:

    ProgrammAutoIt gemessen (ms)VTune Ausführungszeit (ms)VTune CPU-Zeit (ms)
    Ohne Fenster22632677803
    Mit Fenster707572063513
    Verhältnis M/O3,1272,6924,375


    Nun, hier erkennt man nicht nur, dass die Variante ohne Fenster nicht nur deutlich schneller ist, sondern auch offensichtlich wesentlich weniger Zeit im Idle "verschwendet". Aber natürlich ist auch die CPU-Zeit sehr interessant. Wir sprechen hier von einer Differenz von 2,7 Sekunden - nur für das Erstellen eines Fensters.


    Und jetzt das Interessante: Die detaillierte Ausgabe von VTune. Man kann eleganterweise sogar zwei Durchgänge direkt in VTune vergleichen. Im sog. Bottum-Up findet man dann alle relevanten Funktionen aufgelistet (inkl. Herkunfts-Modul), zusammen mit der CPU-Zeit vom Prozess ohne Fenster, mit Fenster und mit der Differenz. Die komplette Tabelle ist als CSV im Anhang, hier möchte ich nur einen kurzen Ausschnitt anfügen, nämlich die zeitlich signifikantesten Funktionen.

    Function / Call Stack ModuleCPU Time: Difference CPU Time: HW+Stack, with window CPU Time: HW+Stack, without window
    PeekMessageW user32.dll2.21418 2.30831 0.0941345
    [wow64cpu.dll] wow64cpu.dll0.228307 0.229308 0.00100129
    func@0x410b30 calltester3.exe0.133167 0.20928 0.0761127
    func@0x6b101742 wow64cpu.dll0.0390594 0.0400607 0.00100125
    func@0x6b101cb0 wow64cpu.dll0.014992 0.0279829 0.0129908
    func@0x18000fcc0 wow64cpu.dll0.0149883 0.0149883 0
    func@0x40e5c4 calltester3.exe0.00900523 0.0210254 0.0120201
    func@0x40a000 calltester3.exe0.00899911 0.0570712 0.0480721

    Wer jetzt nicht selber rechnen mag: Die summierte Differenz entspricht 2,66 Sekunden - also quasi der kompletten Differenz der CPU-Zeiten der beiden Programmvarianten. Nun, was haben wir denn hier für Funktionen? Alle "func@..." aus dem Modul calltester3.exe (so heißt mein kompiliertes AutoIt-Programm) sind vermutlich interne AutoIt-Funktionen, die z.B. eine Skriptzeile interpretieren könnten, eine UDF aufrufen könnten... Was auch immer. Alle Funktionen, die zum Modul wow64cpu.dll gehören, sind vermutlich Teil der Win32-Abstraktionsschicht. Grundsätzlich arbeiten mittlerweile alle Windows-internen Funktionen als 64-bit Software. Damit vorhandene 32-bit Software weiterhin lauffähig bleibt, kommt diese Abstraktionsschicht zum Einsatz, die die 32-bit Funktionsaufrufe in 64-bit Funktionsaufrufe übersetzt. Und zu guter Letzt hätten wir unseren Hauptübeltäter: PeekMessageW aus der user32.dll. Wer's nicht weiß: Diese Funktion ist zum Verarbeiten von Thread- und Fenster-Nachrichten innerhalb der Win32-API. Das ist quasi die Funktion, die hinter AutoIts GUIGetMsg steht. Üblicherweise wird diese PeekMessage-Funktion immer und immer wieder in einer Schleife aufgerufen, um auf Interaktionen mit dem Fenster reagieren zu können.


    Dieser Test ist auf demselben System durchgeführt worden, wie der zwei Posts davor, also mit Windows 10 1904. Das ganze werde ich morgen mal noch auf einer Windows 7 Maschine machen. Und ich wette damit, dass PeekMessageW dann nicht mehr so viel Zeit frisst.


    Ins Blaue hineingeraten würde ich Mars' Begründung hier auch übernehmen. Irgendwas am Windows-Verhalten hat sich geändert, was die AutoIt-EXE dazu bringt, PeekMessageW unverhältnismäßig oft aufzurufen.

    Dateien

    • result.zip

      (4,09 kB, 13 Mal heruntergeladen, zuletzt: )

    Also, ich habe jetzt in stundenlanger Kleinarbeit mal versucht, mittels eines API-Monitors (http://www.rohitab.com/apimonitor) herauszufinden, welcher Systemaufruf nach dem Erstellen eines Fensters länger dauert oder öfter auftritt. Ich habe dazu das folgende Testskript in kompilierter Form (x86) verwendet::


    Das ist das bereits bekannte Testscript, leicht modifiziert. Die FileWrites stehen deshalb da, weil man die im API-Monitor recht schnell finden kann (CreateFileW mit dem Dateiname als erster Parameter).


    Dabei habe ich ein paar recht interessante Erkenntnisse gewonnen. Vorneweg: Die Ursache für die Verlangsamung konnte ich leider nicht ausmachen, es waren nur "Indizien" zu finden.


    Also, steigen wir mal ein. Das Experiment findet statt auf meinem Notebook mit einem i7-7700HQ und Windows 10 Buildnummer 18362 (Windows 10 1903). Mit dem eingangs erwähnten API-Monitor kann man während der Laufzeit eines Programmes herausfinden und protokollieren, welche Funktionen in welchen (System-)Bibliotheken aufgerufen werden. Netterweise zeigt diese Software nicht nur die Parameter der aufgerufenen Funktion sowie deren Rückgabewert an... Nein, auch die Dauer des Aufrufs (also quasi die Differenz der Zeiten von CALL und RET) wird ermittelt. Das funktioniert, indem die jeweiligen Funktionen durch eine DLL Injection durch "Zwischenfunktionen" ersetzt werden. Das hat jedoch den Nachteil, dass die entsprechenden Systemaufrufe deutlich länger zum Ausführen brauchen. Leider ist es quasi unmöglich, alle Systemaufrufe auf einmal zu protokollieren. Das Log wird schlichtweg zu groß und der API-Monitor macht das nicht mit.


    Daher habe ich im ersten Durchgang ein paar Funktionen mittels der Exclude-Funktionalität des API-Monitors ausgeschlossen. Und zwar HeapAlloc, HeapFree und PeekMessageW sowie nahezu alle anderen GUI-Funktionen. Die GUI-Funktionen hatte ich vorher in Einzeltest schon als Ursache ausschließen können. Dieser Durchgang ist im Anhang als ODS-Datei (innerhalb des ZIP-Ordners) enthalten. Kurz dazu: Das erste Tabellenblatt enthält das gesamte Log vom Start der EXE bis hin zur Anzeige der MsgBox mit den Ergebnissen am Ende. Danach kommen nur noch Aufräum-Arbeiten von AutoIt. Farblich im Log markiert sind... In gelb die Aufrufe von CreateFileW und alles, was damit zusammenhängt. Und in rot der Aufruf von CreateWindowEx zwischen den beiden Berechnungsfunktionen sowie alles, was dazu gehört. Auf dem zweiten und dritten Tabellenblatt sieht man dann, was noch an API-Aufrufen bei den beiden Berechnungsdurchläufen übrigbleibt. Nicht sonderlich viel. Im ersten Durchlauf sind es rund 23 API-Aufrufe, im zweiten Durchlauf 61. Wobei beim zweiten Durchlauf der erste Teil noch zur "Zerstörung" des Fensters gehören könnte. Verglichen mit der riesigen Gesamtmenge an API-Aufrufen sind diese Zahlen allerdings so oder so nicht relevant. Das sieht man auch schön, wenn man die Aufrufzeiten mal addiert. Die 23 API-Aufrufe im ersten Durchlauf brauchten 0,0000181 Sekunden. Die 61 API-Aufrufe im zweiten Durchlauf brauchten 0,0000368 Sekunden. Wenn man mal das rausrechnet, was auch noch zur GUI gehören könnte, kommt das so ziemlich auf's selbe raus. Verglichen mit der Gesamtlaufzeit der beiden Durchläufe laut AutoIt (sieht man im Gesamtlog ganz unten) sind das ohnehin verschwindend geringe Zeiten. Dort brauchte der erste Durchlauf ca. 0,3 Sekunden, der zweite Durchlauf etwa 1 Sekunde. Das zu untersuchende Phänomen ist also definitiv vorhanden, allerdings kann ich einen Zusammenhang mit den untersuchten Systemaufrufen dadurch nahezu ausschließen. Das sollte dann auch die Theorie widerlegen, dass Microsoft da absichtlich ausbremst. :D


    Im zweiten Durchgang schließlich wollte ich dann die bisher ausgeschlossenen Funktionen untersuchen, die sonst mehrere hunderttausend Male während eines Programmdurchlaufes ausgeführt werden: HeapAlloc, HeapFree und PeekMessageW. Ich habe also - um die Datenmenge überschaubar zu halten - nur die Funktionen CreateFileW, CreateWindowEx und PeekMessageW überwacht. Da das Log ob der schieren Größe (~900 MB) kaum noch in LibreOffice Calc zu verarbeiten war, habe ich nur mit den Zeilennummern gearbeitet. Sowohl vor als auch nach der Fenstererstellung wird PeekMessageW in etwa 1.000.000 mal aufgerufen. Also auch da keine Diskrepanz. Das Interessante an dieser Stelle ist jetzt aber, dass ich in diesem Durchlauf (größenordnungsmäßig reproduzierbar) die folgenden Zeiten gemessen durch AutoIt erhalten habe: Erster Durchlauf 16,219 Sekunden, zweiter Durchlauf 17,092 Sekunden. Das Phänomen ist also deutlich deutlich abgeschwächt, wenn nicht sogar verschwunden. Das kann eigentlich nur damit zusammenhängen, dass PeekMessageW mit Monitoring deutlich länger zum Ausführen braucht.


    Nun, was gewinnen wir an Wissen daraus? Ich bin mir nicht ganz sicher, wie das Ergebnis zu deuten ist. Den ersten Durchlauf hätte ich so gedeutet, dass die "Bremse" AutoIt-Intern sein muss, da kein WinAPI-Aufruf signifikant länger dauert. Und mit AutoIt-Intern meine ich, dass weder eine WinAPI-Funktion langsamer ausgeführt wird als vorher, noch eine WinAPI-Funktion öfter aufgerufen wird als vorher.


    Aber was ich mit dem Ergebnis des zweiten Durchgangs anfangen soll, weiß ich selber noch nicht so ganz...

    Dateien

    • api_calls.zip

      (328,65 kB, 12 Mal heruntergeladen, zuletzt: )

    Puh, das ist echt interessant. Ich teste Mars' Skript mal mit dem Kram, an den ich gerade über Remote Desktop drankomme...


    01. Notebook (Windows 10)

    Gewichtungsfaktor 0.85

    Code
    = = = Test Results = = =
    991.69 (100.00%)
    131.94 (13.30%)
    = = = System Info = = =
    CPU Name: Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
    CPU Physical Cores: 4
    CPU Logical Cores: 8
    OS Version: WIN_10
    OS Build: 18362
    OS Arch: X64


    02. Server 1 (Hyper-V, Windows Server 2019)

    Gewichtungsfaktor 0.28

    Code
    = = = Test Results = = =
    1006.03 (100.00%)
    387.00 (38.47%)
    = = = System Info = = =
    CPU Name: AMD EPYC 7252 8-Core Processor
    CPU Physical Cores: 1
    CPU Logical Cores: 2
    OS Version: WIN_2016
    OS Build: 17763
    OS Arch: X64


    03. Server 1 (physikalisch, Windows Server 2019)

    Gewichtungsfaktor 0.75

    Code
    = = = Test Results = = =
    1055.76 (100.00%)
    268.10 (25.39%)
    = = = System Info = = =
    CPU Name: AMD EPYC 7252 8-Core Processor
    CPU Physical Cores: 8
    CPU Logical Cores: 16
    OS Version: WIN_2016
    OS Build: 17763
    OS Arch: X64


    04. Server 2 (physikalisch, Windows Server 2012)

    Gewichtungsfaktor 0.23

    Code
    = = = Test Results = = =
    996.25 (100.00%)
    1014.38 (101.82%)
    = = = System Info = = =
    CPU Name: Intel(R) Xeon(R) CPU E5-2609 0 @ 2.40GHz
    CPU Physical Cores: 4
    CPU Logical Cores: 4
    OS Version: WIN_2012
    OS Build: 9200
    OS Arch: X64


    05. Server 2 (Hyper-V, Windows Server 2016)

    Code
    = = = Test Results = = =
    1052.24 (100.00%)
    1039.83 (98.82%)
    = = = System Info = = =
    CPU Name: Intel(R) Xeon(R) CPU E5-2609 0 @ 2.40GHz
    CPU Physical Cores: 2
    CPU Logical Cores: 2
    OS Version: WIN_2016
    OS Build: 14393
    OS Arch: X64


    Ich mache im Laufe des Sonntags mal einen Abstecher in die Firma und teste mal auf verschiedenen Clients... Windows Server 2019 ist aber auf jeden Fall auch betroffen. Auffällig ist, dass mein Server mit AMD Epyc CPU extreme Schwankungen aufweist. Das zweite Testergebnis fällt immer irgendwo zwischen 25 und 50 Prozent, was - verglichen mit meinem Notebook - eine echt große Schwankung ist. Dennoch scheint die AMD-CPU nicht ganz so stark davon betroffen zu sein (Faktor 2-4 verglichen mit Faktor 8 bei Intel). Edit: Bei den beiden Maschinen mit Windows Server 2019 möchte ich kurz auf die Build-Nummer hinweisen. Das ist die LTS-Variante von Server 2019, welche auf Windows 10 1809 basiert. Wenn es ein grundsätzliches Problem in Windows 10 ist, kann das also nicht erst mit 1904 oder 1909 aufgetreten sein.


    Das ist echt spannend.

    Das ist für eine Interpretersprache nicht realisierbar.

    Na, da muss ich aber mal kurz widersprechen. Warum sollte das nicht realisierbar sein? Das ist jetzt zwar ein bisschen OT, aber grundsätzlich ist das natürlich möglich. Eine Interpretersprache geht ja im Endeffekt das Programm auch nur Schritt für Schritt durch, genau wie ein Hardware-Prozessor den Maschinencode. Und auch eine Interpretersprache könnte nach jedem Schritt den aktuellen Status des Programmes (Speicherinhalt, Program Counter usw.) zur Verfügung stellen, sodass man ihn mit einer interaktiven Befehlszeile (Debugger) auswerten kann. AutoIt kann das nicht, da hast du völlig recht. Aber die Spracharchitektur im Sinne einer Interpretersprache ist nicht der technische Grund dafür.


    Man müsste vielleicht mal in den Sourcecode der letzten Open Source AutoIt-Version gucken. Wenn wir uns mal kurz auf die reine technische Realisierbarkeit beschränken und jegliche juristischen/lizenzrechtlichen Hindernisse ignorieren... Soweit ich weiß, wird in den meisten Interpretersprachen auch eine Art Baumstruktur des Skriptes erzeugt, ähnlich wie beim Kompilieren bei einer Compiler-Sprache (Google-Stichwörter Lex und Yacc). In dieser Baumstruktur wird das komplette Skript in sogenannte Ausdrücke zerlegt. Zur Auswertung dieser Ausdrücke wird es eine einzelne Funktion innerhalb des AutoIt-Interpreters geben. Wenn man diese Funktion ausfindig machen kann und (meinetwegen auch live während der Ausführung) so modifiziert, dass diese unmittelbar vor dem Return eine von uns geschriebene Blockier-Funktion aufruft... Dann haben wir eigentlich schon eine schrittweise Ausführung hinbekommen.


    Man korrigiere mich, wenn ich falsch liege oder was übersehen habe.

    Ich möchte aber nochmal darauf hinweisen, dass das rein theoretische Überlegungen sind. Außer, irgendwer holt eine offizielle Erlaubnis des Rechteinhabers ein.

    Vom Gefühl her würde ich ein Dictionary oder eine HashTable ausprobieren. Die weisen ja auch quasi konstante Zugriffszeiten auf.


    Edit:

    So irgendwie. Theoretisch könnte man auch von Hand einen BST implementieren.

    cURL sollte eigentlich dafür nicht nötig sein - im Gegenteil, das wird vermutlich eher noch Probleme schaffen.


    cURL ist eine externe Anwendung (*.exe), die Du aus AutoIt heraus aufrufen würdest. Dabei musst Du sämtliche Parameter als Startparameter für die EXE übergeben. Dazu muss alles korrekt maskiert/escaped sein (Anführungszeichen, Sonderzeichen, Leerzeichen etc..). Das führt üblicherweise zu Problemen.


    Eleganter und weniger fehleranfällig wäre es, hier direkt auf WinHTTP oder WinInet zurückzugreifen. Beide Bibliotheken sprechen - ebenso wie cURL - HTTP. Und nichts anderes ist CalDAV ja am Ende: Ein XML-String, der per HTTP übertragen wird.

    Noch zur Vollständigkeit:


    Dass es keine dateispezifischen Scopes geben kann, wird schnell klar, wenn man überlegt, was bspw. eine Anweisung wie "#include" ist.


    Man nennt diesen Typ von Anweisungen auch Präprozessoranweisungen. Was ist das? Ein Präprozessor ist ein Programm, was den Code durchgeht und genau diese Anweisungen ausführt/auswertet, BEVOR alles dann an den Interpreter/Compiler übergeben wird. Das heißt im Falle von Include also, dass der Präprozessor diese Anweisung erkennt, dann die dort angegebene Datei einliest und deren Inhalt anstelle der Include-Anweisung in das Skript einfügt. Diese Anweisung ist nebenbei an den C-Präprozessor angelehnt. Jedenfalls sieht der Interpreter/Compiler später gar nicht mehr, dass das eigentlich mal zwei (drei, vier, N) Dateien waren. Daher kann er auch nachher nicht mehr den Zugriff auf eine Variable verbieten, die nur in einer Datei vorkommt.

    Hi,


    bei uns in der Firma laufen diverse Tools aus meiner Hand, die teilweise als Hauptaufgabe, teilweise als Nebenaufgabe auch etliche verschiedene Berichte in Dokumentenform erzeugen. Nach viel Rumprobieren bin ich bei HTML und wkhtmltopdf gelandet. Somit geben alle meine Tools schöne PDF-Dateien aus, die der Benutzer dann entweder drucken oder per Mail direkt an andere Mitarbeiter oder sogar Kunden schicken kann. Meistens lasse ich die dann einfach nach der Erzeugung mit ShellExecute mit dem Default-PDF-Reader öffnen und gut ist.

    Das Pattern ist korrekt. Ich nutze zur "Entwicklung" von regulären Ausdrücken fast immer regex101.com. Da muss nichts escaped werden. Für die Verwendung mit AutoIt muss dann entweder das Apostroph oder die Gänsefüßchen maskiert werden, bspw. so:

    Code
    ^Func\h*(\w+\h*(\((((''|")((((?!\5).)*)|(?4))*\5)|([^()]*)|(?2))*\)))\h*(;.*)?\h*\R*$


    Hatte ich jetzt gerade beim Posten nicht drüber nachgedacht. ^^

    Die Flinte nicht so schnell ins Korn werfen. RegEx kann ziemlich viel. :D

    Das Pattern ist jetzt zwar etwas ausgeartet, aber es funktioniert einwandfrei. Zumindest habe ich nichts gefunden, was falsch gematcht wird.

    Code
    ^Func\h*(\w+\h*(\(((('|")((((?!\5).)*)|(?4))*\5)|([^()]*)|(?2))*\)))\h*(;.*)?\h*\R*$

    Das ist dann jetzt wie angekündigt eine doppelte Rekursion mit Backreference Match.

    Sogar das hier wird korrekt gematcht:

    Code
    _Strip(11, "Func _SciTE_ShowFuncName('Das hier ist ""böse"". ;)')")

    Mit ein bisschen RegEx-Magie kann man auch das Nesting abbilden. ;)

    Ich habe mal alpines' Pattern als Basis genommen. Würde allerdings statt \s definitiv \h bevorzugen. Vertikale Whitespaces sind an diesen Stellen nämlich nicht zulässig.


    Pattern:

    Code
    ^Func\h*(\w+\h*(\(((?:[^()]*)|(?2))*\)))\h*(;.*)?\h*\R*$

    Ergebnis:


    Aber ganz unrecht hat alpines trotzdem nicht. An gewissen Stellen geht auch das "kaputt". Man füge mal zu dem Test-Skript folgendes hinzu: _Strip(10, 'Func _SciTE_ShowFuncName("Das hier ist böse. ;)")')...

    Das könnte man eventuell mit einer Art Doppel-Rekursion lösen (außen Klammern, innen Anführungszeichen). Wobei bei den Anführungszeichen dann wieder eine Backreference nötig wäre, um " und ' gerecht zu werden. Da wäre es fast einfacher, vorher alle Strings rauszuparsen.

    Hiho,


    in der letzten Woche ist bei mir aus einem beruflichen Bedürfnis heraus eine kleine Software entstanden.


    Schon seit etlichen Jahren arbeiten wir mit einem eigenen Folienplotter zwecks Beschriftung mit dem Schwerpunkt Fahrzeuge. Vor kurzem ist dann noch eine Textilpresse (Beschriftung von Kleidungsstücken) sowie ein HP-Latex-Drucker hinzugekommen, sodass wir mittlerweile mit diversen Werbetechnik-Unternehmen mithalten können, obwohl dies nicht unser Schwerpunkt ist. Früher hat das alles mein Vater nebenbei gemacht, mittlerweile bin ich eher dafür zuständig.

    Oftmals sind die Kunden am Design-Prozess beteiligt. Mir ist aufgefallen, dass eines der größten Probleme beim Entwurf das Finden der richtigen Schriftart ist. Teilweise kommt dann als Auftrag auch nur so eine Aussag wie "Ja, der Schriftzug 'Dorfjugend Blabla' auf den Rücken bitte", ohne Angabe einer Schriftart. Auf der einen Seite kann man sich dann natürlich kreativ austoben, aber meistens endet das in einem ewigen Hin- und Her. Und selbst beim kreativen Austoben ist es eine große Hilfe, einfach mal alle Möglichkeiten vor sich zu sehen.


    Daher habe ich mir ein kleines Skript gebastelt, welches einen beliebigen Schriftzug in allen installierten Schriftarten in einer beliebigen Größe darstellt. Auf Wunsch kann das Ergebnis dann als PDF exportiert werden, um es dem Kunden bspw. per Mail zukommen zu lassen. Die ersten beiden Kunden, mit denen ich das getestet habe, haben schon gezeigt, dass die Idee goldrichtig war. :thumbup:


    Auf technischer Seite ist das insgesamt der dritte Versuch. Der erste war ein ListView mit OWNERDRAW, der zweite mehrere Labels in einer Child GUI mit Scroll-UDF. Das war beides - gelinde gesagt - Mist. Die Lösung über ein Embedded IE ist wesentlich einfacher und eleganter. Außerdem ist so der PDF-Export (über wkhtmltopdf) ziemlich leicht realisierbar gewesen. Erwähnenswert ist noch, dass ich mein eigenes Projekt (SynSug - Syntaktischer Zucker für AutoIt (Update v1.1.0 Dictionaries)) zur Umsetzung genutzt habe, konkret für die mehrzeiligen Strings in NowDoc/HereDoc-Syntax. Im angehängten ZIP-Archiv finden sich daher zwei Au3-Dateien, einmal mit "Syntactic Sugar" und einmal in purem AutoIt. Die wkhtmltopdf.exe muss bei Nutzung der Export-Funktion selber unter https://wkhtmltopdf.org/downloads.html heruntergeladen werden, da sie mit knapp 40 MB jedes Limit hier im Forum übersteigt.



    Nun, das war's eigentlich schon. Vielleicht kann ja außer mir noch jemand was damit anfangen. ^^


    Denkbar wäre in Zukunft noch, dass man noch mehr CSS-Schrifteinstellungen einstellbar macht, um z.B. den Zeichenabstand zu verändern oder andere Schrifteffekte umzusetzen.

    Dateien

    • FontShow.zip

      (5,33 kB, 83 Mal heruntergeladen, zuletzt: )

    Witzig, dass du das fragst. Ich habe in letzter Zeit auch versucht, in einer AutoIt-GUI eine sehr bunt formatierte Tabelle unterzubekommen. Bei mir war der konkrete Anwendungszweck, einen Schriftzug in wählbarer Größe in allen vorhandenen Schriftarten darzustellen.


    Selbst bei maximaler Fenstergröße benötigt dieser Anwendungszweck eine Art Scroll-Mechanismus. Ich habe insgesamt vier Ansätze gehabt:


    1. ListView-UDF mit OwnerDraw.

    2. RichEdit-UDF mit ES_READONLY.

    3. Native Labels auf Child-GUI mit Scrollbar-UDF.

    4. Embedded IE.


    Die im Endeffekt simpelste Methode für deinen Anwendungszweck wird vermutlich der Embedded IE sein. Einfacher als per HTML/CSS kriegst du die Tabelle nicht hin.

    Performanter wären ListView und Label, allerdings beide deutlich aufwendiger zu implementieren. ListView ginge vermutlich noch einfacher, man kann in der Ownerdraw-Funktion für jedes (Sub-)Item eigene Styles definieren. RichEdits zu guter letzt können mit Tabellen umgehen - aber die AutoIt-UDF sieht dies nicht vor.

    Eine Sache ist mir noch nicht ganz klar. Du schreibst von einem webbasiertem Monitoring-System. Wenn es nicht gerade eine uralte Flash- oder Java-Webanwendung ist, wäre es doch deutlich eleganter, den Status über die IE.au3 oder noch besser per TCP/HTTP abzufragen. Mit Pixel-Farben zu hantieren ist immer irgendwie Mist und neigt zur Fehleranfälligkeit und Unzuverlässigkeit. Hast du das schon versucht?