Beiträge von Professor Bernd
-
-
Einige Stunden und 2 Kannen Kaffee später.
Nun habe ich deinen Code soweit studiert. Es wäre übertrieben zu sagen, ich würde halbwegs durchzusteigen. Um mich einzuarbeiten, habe ich deinen Code umformatiert, auseinadergezogen und mit _ArrayDisplay und Kommentaren ergänzt. Daran kannst du sehen, wie weit ich durchgestiegen bin. (siehe Anhang)
Mit dem Beispiel funktioniert es und hat auch kleinere Tests überstanden. Da das bis hierhin wirklich gut aussieht, folgt nun die Verfeinerung der Anforderungen.
Ausgangssituation:
- Im Log-Fenster wurde vom Compiler Output geschrieben.
- Eine beliebige Zeile wurde markiert, abhängig von verschiedenen Dingen (fehlerfrei oder Fehler/Warnings gefunden, Debug-Zeilen, alles von ConsoleWrite, usw.)
Schritte: (so wie sie nachher funktionieren sollen)
- Die Zeilen werden einzeln durchlaufen und durchsucht nach error, warning und "==>" Mustern, wie ganz oben beschrieben.
- Wird in einer Zeile nichts gefunden, gehts zur nächsten.
- Werden in einer Zeile Marker für error oder warning oder "==>" gefunden, wird angehalten und diese Zeile als aktive gesetzt.
- Werden in einer Zeile Marker für "==>" gefunden, wird zudem der Zahlenteil ergänzt, ein Leerzeichen entfernt und "error" hinzugefügt. Vorher/Nachher-Beispiel:
"D:\test files\FileQuantityLimit (Testdatei).au3" (163) : ==> Array variable has incorrect number of blabla ...
"D:\test files\FileQuantityLimit (Testdatei).au3"(163,1) : error: ==> Array variable has incorrect number of blabla ...
Hier das Ganze nochmal als Bild.
Das heißt, benötigt werden 2 Dinge:
- eine Erkennung, ob eine Zeile einen der Marker für error, warning oder "==>" enthält,
- eine Ersetzung für String-Teile, wenn "==>" gefunden wird.
Wie du im Code vom Anhang sehen kannst, habe ich noch nicht einmal die Ersetzung (einfügen von ",1) : error") hin bekommen. Kannst du deine RegExp's abändern, so dass sie die beiden Punkte erledigen können?
-
Hallo Kanashius.
Respekt! Schüttlest du sowas einfach aus dem Ärmel? Also für mich sieht das ungefähr so aus: Global $sPattern='????????????????'
Bis hierhin danke dafür! Da habe ich erstmal dran zu knappern, danach melde ich mich wieder. (Erst wollte ich schreiben, dass ich mich melde, sobald ich durchblicke, aber wer weiß, ob das jemals ... ?)
-
Ausgangssituation sind die Output-Zeilen von AutoIt bei "Run", "Compile", usw. wie sie z. B. in SciTE zu sehen sind. Für mein PSPad4AutoIt3 Projekt will ich die Fehlerzeilen aus dem Log-Fenster herausgefiltern, sowie den Pfad zum Script auslesen und Angaben ersetzten.
Folgende Arten von Fehlermeldungen sind mir bekannt:
Zitat"D:\test files\FileQuantityLimit (Testdatei).au3"(112,16) : warning: $iTest possibly not declared/created yet
"D:\test files\FileQuantityLimit (Testdatei).au3"(131,11) : error: zzzz(): undefined function.
"D:\test files\FileQuantityLimit (Testdatei).au3" (163) : ==> Array variable has incorrect number of subscripts or subscript dimension range exceeded.:
Erstes Suchkriterium sind error, warning und der Pfeil "==>", anhand derer die entsprechenden Zeilen gefunden werden können.
Das zweite Kriterium sind die 2 Zahlenangaben, getrennt durch ein Komma, eingeschlossen in runde Klammern.
Als drittes Kriterium steht der Pfad zum Script, der nicht nur erkannt, sondern ausgelesen werden soll.
Zusätzlich soll bei der Variante mit nur 1 Zahlenwert ein Komma und "1" hinzugefügt werden, sodass es auch dort 2 Zahlenangaben sind: Z. B. aus (163) wird (163,1). Auch ein "error:" soll hinzugefügt werden, damit der Higlighter die Fehlerzeile als solche einfärbt.
Erste Problematik ist, dass in Pfadangaben/Dateinamen einige der Suchkriterien vorkomen können, z. B. Zahlenangaben (123,17), der Pfeil "==>", ja man könnte sogar die Dateiendung inklusive Punkt mitten rein schreiben. Auch die einfachen Anführungszeichen, Semikolon, und $, +, -, &, usw. können darin vorkommen, was die Suche möglicherweise erschwert.
Auf der Positiv-Seite sind die Doppelpunkte zu erwähnen, die definitiv nicht in Dateipfaden/namen vorkommen können und die beiden doppelten Anführungszeichen, die den jeweiligen Pfad umschließen. Also gute Suchkriterien.
Mein erster Gedanke war, StringDies, StringDas. ... Mein zweiter war RegExp, nach dem Motto, investiere jetzt ein bisschen Einarbeitungszeit, dann hast du nachher eine solide Routine, und kannst dein Wissen auch bei anderen Aufgaben einsetzen. Über 2 Stunden habe ich verschiedene Quellen zu RegExp durchgelesen und ausprobiert, unter anderem das Tutorial von SEuBo. Dann plötzlich hatte ich den vollen Durchblick: Das wird nie was! Meine Erinnerungen kamen wieder und mir wurde klar, dass RegExp's definitiv nicht das gleiche sind, wie Suchstrings mit WildCards.
Leider habe ich keine Funktion gefunden, bei der mit WildCards gesucht werden kann. StringInStr($sLine, '.au3"(*,*) : error: ') funktioniert nicht.
Nach den vielen Infos und Tutorials habe ich dann mithilfe einer Website zum Testen von RegExp's folgendes geschafft:
(?i)(\"*\.au3\"\(\d{1,},\d{1,}\) : Warning: )
oder
(?i)\.au3\"\(\d+,\d+\) : Warning:
Beide funktionieren für error und warning. Für den Pfeil "==>" habe ich es nicht geschafft, eine RegExp zu erstellen. Vielleicht kann das ja ein RegExp-erte? Außerdem müssten noch 0 oder 1 Leerzeichen vor die Klammer mit dem Zahlenwert hinzugefügt werden.
Damit könnte man die Fehlerzeilen (wahrscheinlich) zuverlässig erkennen. Danach mit _StringBetween() den Dateipfad auslesen und mit StringLeft-Mid-Right... den Zahlen-Teil ermitteln, noch ein paar Routinen zusammenklöppeln, um den "einsamen" Zahlenwert ein Komma und einen zweiten Zahlenwert zu spendieren, ins Log zurückschreiben und fertig. (Nach meiner Schlappe mit StringRegExp wollte ich StringRegExpReplace nicht mehr ergründen.)
Wie würdet ihr an die Sache herangehen?
-
-
Gerne!
Wenn dir langweilig ist, sieh dir mal mein "PSPad4AutoIt3 Projekt DE" an. Ich würde mich über Helfer freuen!
Bernd.
-
Ich vermute mal, dass erfahrene Entwickler besser organisiert sind, aber bei mir muss ich erst noch den richtigen Weg finden. Die geplanten Features habe ich umrissen, recherchiert und angefangen. Da ergab sich eins zum anderen, und mal habe ich Code-Snippets und Tipps für das eine gefunden, mal für das andere. So sind mittlerweile mehrere angefangen, und eins habe ich gestern fertig gestellt:
Die Erweiterung der Suchbegriff-Erfassung, damit auch Wörter erkannt werden, wenn der Cursor direkt dahinter steht.
Das war gestern. Heute hat Jan Fiala die neueste Developer Version 5.0.2 (339) veröffentlicht. Darin ist dieses Feature nun enthalten. Ist das nicht ?
Ich freue mich sehr, dass Jan Fiala meinen Feature-Request erfüllt hat! Ebenso wie: Scripting - added variables for getVarValue(): %File% (file name without extension), %Ext% (file extension). Das kommt diesem Projekt zugute, weil damit in der VBScirpt-Schnittstelle 2 weitere Variablen hinzukommen.
Edit:
Fast vergessen: Im Posting #1 habe ich diese Infos im Spoiler "Aktuell geplante Features" und bei den Downloads die neueste PSPad Developer Version hinzugefügt. Den entsprechenden Punkt im Abschnitt "Einrichtung" habe ich angepasst.
-
Auf jeden Fall danke für den Vorschlag und die Infos!
-
Vielen Dank für den Tipp!
Aufgrund eines Tipps von BugFix nutze ich im Moment die Möglichkeit, in meinem Improvement Kit nur au3 Dateien als "externe Programme" zu benutzen. Das heißt, z. B. in den VBScripts erfolgt ein Aufruf der AutoIt3.exe, der ich die jeweilige au3 übergebe. Bei meinen bisherigen Tests hat das funktioniert und Windows-Defender hat sie nicht angerührt. Dadurch sind alle Codes einsehbar und das Improvement Kit ist klein.
Dennoch freue ich mich über deinen Tipp. Hätte a3x Vorteile demgegenüber?
-
@Greenhorn__
Herzlich willkommen!
-
War da nicht was, so wie du sagst, wenn man HWNDs benutzt?
-
Guter Tipp!
_WinAPI_GetParentProcess zusammen mit ProcessList habe ich mir gerade angesehen und ein wenig getestet. Für mein oben beschriebenes Thema konnte ich nicht direkt eine Verwendung finden, aber es ist mir gleich ein anderes Thema eingefallen, wo das helfen könnte.
Im Moment habe ich nur ein wenig mit dem Beispiel aus der Hilfe zu ProcessList() gespielt. Kannst du vielleicht ein besseres kleines Beispiel posten, damit ich später den Zusammenhang schneller wieder finde?
AutoIt: Nur Mischmasch und Geteste ;)
Alles anzeigen#include <MsgBoxConstants.au3> #include <Array.au3> #include <WinAPIProc.au3> Example() Func Example() ; ; Startet den Editor ; Run("notepad.exe") ; ; ; Wartet maximal 10 Sekunden bis das Editorfenster erscheint. ; Local $hWnd = WinWait("[CLASS:Notepad]", "", 10) ; Zeigt eine Liste der Editorprozesse an die durch ProcessList zurückgegeben wurde. ; Local $aProcessList = ProcessList("Notepad.exe") ; For $i = 1 To $aProcessList[0][0] ; MsgBox($MB_SYSTEMMODAL, "", $aProcessList[$i][0] & @CRLF & "PID: " & $aProcessList[$i][1]) ; Next ; Local $aProcessList = ProcessList("AutoIt3Help.exe") Local $aProcessList = ProcessList() _ArrayDisplay($aProcessList) Local $iParentPID = _WinAPI_GetParentProcess(0) ConsoleWrite("-> $iParentPID: " & $iParentPID & @CRLF) Local $iChildPID = $aProcessList[1][1] Local $iParentPID = _WinAPI_GetParentProcess($iChildPID) ConsoleWrite("-> $iParentPID: " & $iParentPID & @CRLF) ; ; Schließt das Editorfenster durch die Verwendung des von WinWait zurückgegebenen Handles. ; WinClose($hWnd) EndFunc ;==>Example
Gruß,
Bernd.
-
Eben war ich so in Gedanken, dass ich die Höflichkeit vergessen habe. Ich glaube, wir hatten noch nicht die Ehre, deshalb hier ein um so freundlicheres "Hallo Kanashius." und vielen Dank für die bisherigen Tipps!
Eigentlich ist die ursprüngliche Frage des Threads beantwortet: Die äußere Do-Until Schleife hat also doch einen Sinn, denn sie ist zuständig für das Warten auf das gewünschte Fenster bzw. Prozess.
Aber ohne deinen Tipp hätte ich vielleicht gar nicht bemerkt, dass das Warten wichtig ist. Wahrscheinlich hätte meine Routine die meiste Zeit funktioniert, weil man das Hilfe-Fenster oft geöffnet lässt, und ich hätte mich gewundert, warum es nicht funktioniert, wenn das HIlfe-Fenster noch nicht gestartet ist. Das hätte eine Sucherei ergeben, die du mir erspart hast!
Nun will ich den konkreten Fall nicht vorenthalten, ohne zu sehr in (langweilige) Details zu gehen:
In lang: Meine Routine "CallAutoIt3HelpExe" wird von PSPad (Editor) aufgerufen und startet per "Run" die "AutoIt3Help.exe" und übergibt ihr dabei einen Suchbegriff. Damit wird die AutoIt.chm geöffnet und die Infos zum Suchbegriff angezeigt. Leider kommt es manchmal vor, dass sich das Hilfe-Fenster hinter das aufrufende schiebt. Deshalb wird das Handle des Hilfe-Fensters gesucht und _WinAPI_SetForegroundWindow() durchgeführt.
In kurz: PSPad startet "CallAutoIt3HelpExe" => startet die "AutoIt3Help.exe" => startet die "AutoIt.chm" => Handle suchen => SetForeground...
Die beiden Fenster, um die es geht, sind "AutoIt3Help.exe" und "AutoIt.chm" (Hilfe-Fenster).
Leider habe ich von der "AutoIt3Help.exe" kein Source-Code gefunden, aber den Titel des unsichtbaren Fensters konnte ich mithilfe von WinList() auslesen: "AutoIt3Help". Also habe ich den Titel des Parent-Fensters (Prozesses?*). Das hat als Child-Fenster/Prozess die AutoIt-Hilfe. (*Leider kann ich gerade nicht ganz zuordnen, ob es sich um Fenster und/oder Prozesse handelt.)
Das Hilfe-Fenster kann ich nicht zuverlässig per Win-Titel ausfindig machen, da er sich je nach verwendeter Sprache ändert (DE, EN, FR, IT, ...) . Um also sprachunabhängig zu sein, habe ich "unveränderliche" Kriterien gesucht. Ob sie sich wirklich nicht verändern, kann ich nur annehmen. Dazu gehören folgende spekulative Annahmen:
- Der Titel der "AutoIt3Help.exe" scheint sich nicht zu verändern.
- Die "AutoIt3Help.exe" hat nur 1 Child.
- Das Hilfe-Fenster ist das Child davon. Titel verändert sich je nach Sprache und Datei-Version.
- Sowohl die "AutoIt3Help.exe", also auch das Hilfe-Fenster werden NICHT mehrfach ausgeführt!
Laut WinList() (und Taskmanager) gehören beide zum selben Prozess (PID ist bei beiden gleich). Somit habe ich einen Titel, um die PID der "AutoIt3Help.exe" zu ermitteln, und damit dann das HWND des Hilfe-Fensters. WinList() durchlaufen => if (PID gleich der vom Parent) and not (Titel gleich dem vom Parent) then => Child gefunden.
Nachdem ich nun WinWait("AutoIt3Help", "", 4) eingebaut habe, scheint alles zu funktionieren. Verbesserungsvorschläge willkommen.
-
Typisch Test-Szenarios: Auf manche Umstände kommt man nicht.
Gerade habe ich meinen Code ausprobiert. Er ruft die "AutoIt3Help.exe" auf und übergibt dabei einen Suchbegriff. Damit wird dann wiederum die "AutoIt.chm" aufgerufen. Solange die chm geöffnet ist, bleibt auch die "AutoIt3Help.exe" geöffnet. In meinen Test-Szenario habe ich die chm nicht geschlossen, deshalb ist mir das auch nie aufgefallen.
Ergebnis
Für den Aufruf von "GetHlpWinHandle()" (ähnlich dem GetHwndFromPID()" ) hat sich gezeigt:
- Sind exe und chm geöffnet, funtioniert der Aufruf, das HWND zum Hilfe-Fenster wird gefunden.
- Sind exe und chm NICHT geöffnet, versagt der Aufruf, es wird kein Handle gefunden.
- Mit WinWait() funktioniert es dann auch, wenn exe und chm beim Aufruf NICHT geöffnet sind.
WinWait scheint also zu funktionieren. Kann es damit Probleme geben und wäre die Do-Until Schleife die bessere Wahl?
-
Das ergibt Sinn!
In meinem Fall will ich die äußere Schleife nicht benutzen. Würde ein simples WinWait() vor dem GetHwndFromPID-Aufruf den Zweck erfüllen, oder gäbe es da Probleme? Wenn ich die Do-Until Schleife einbauen würde, würde ich dort auch ein Timeout benutzen.
-
PID ... mir schwirrt der Kopf!
Vorgeschichte
Ich brauchte das HWND zu einem bestimmten Fenster, hatte aber nur eine PID. Im Netz gibt es viele (kontroverse) Code-Snippets á la "HwndFromPid". Nun ja, eine PID hatte ich ja (scheinbar!), denn
"Run" gibt die PID des Prozesses zurück, der gestartet wurde.
Hat aber nicht funktioniert, bis ich herausgefunden habe, dass es mehrere PIDs gibt, wenn beim Aufrufen per "Run" das zu startende Programm schon läuft. (Korrigiert mich, wenn das nicht stimmt!) In meinem Fall war das Prog schon gestartet (Anzeigen der Hilfe-Datei). Es sollte mit jedem weiteren Aufruf weitere Suchbegriffe geöffnet werden. Die von "Run" zurückgegebene PID war dann nutzlos.
Ich habe das Probelm gelöst, indem ich mithilfe von WinList() das entsprechende PID gesucht habe. Mit dem richtigen PID konnte ich auch das entsprechende HWND ermitteln.
Thema
Bei meinen Recherchen habe ich im einen Code in den FAQ des EN Forums gefunden: "How can I get a window handle when all I have is a PID?" Dort gibt es am Ende des Abschnitts folgenden Code:
AutoIt
Alles anzeigen;Function for getting HWND from PID Func _GetHwndFromPID($PID) $hWnd = 0 $winlist = WinList() Do For $i = 1 To $winlist[0][0] If $winlist[$i][0] <> "" Then $iPID2 = WinGetProcess($winlist[$i][1]) If $iPID2 = $PID Then $hWnd = $winlist[$i][1] ExitLoop EndIf EndIf Next Until $hWnd <> 0 Return $hWnd EndFunc;==>_GetHwndFromPID
Meine Frage ist, wozu ist die Do-Until Schleife da? Wahrscheinlich stehe ich auf dem Schlauch, aber wird da nicht der immergleiche Code ausgeführt, der zu immergleichen Ergebnis führt?
Am Anfang wird das Array $winlist erstellt, es folgt die äußere Do-Until Schleife. Darin läuft die innere For-Next Schleife, die das Array durchläuft von 1 bis "gefunden" oder UBound. Die Do-Until Schleife wird mit Until $hWnd <> 0 abgebrochen, wenn das HWND gefunden wurde. Daraus ergeben sich zwei Möglichkeiten.
1. Das HWND wird gefunden => alle Schleifen werden abgebrochen, Ergebnis returniert.
2. Das HWND wird NICHT gefunden => die Do-Unti Schleife läuft bis zum jüngsten Tag.
Wenn das HWND gefunden werden kann, würde das doch beim ersten Durchlauf der For-Next Schleife passieren, oder nicht? Und wenn das HWND beim ersten Durchlauf NICHT gefunden wird, wieso sollte es dann beim zweiten oder 1.001-ten Durchlauf gefunden werden?
Hab ich da einen Denkfehler?
-
Wie water herausgefunden hat, kannst du meinen Nachtrag vergessen. Unter der auskommentieren Zeile folgt eine 2-zeilige Alternative, die ich übersehen habe.
-
Prima, somit wäre das Rätsel gelöst. Es tut mir leid, dass ich dich umsonst bemüht habe. Bin mit meinem Projekt derzeit schwer beschäftigt, weshalb ich das wohl nicht gesehen habe. Dafür hast du es entdeckt.
-
Das habe ich in der Tat ausprobiert. Du kannst es aber auch selbst ausprobieren, denn meine Beschreibung erklärt es dir nicht so gut, wie wenn du es dir selbst ansiehst.
Bei meinen Tests wurde ein blasses Kreuz in der Mitte des Bildschirms angezeigt, das aus vier Elementen besteht (4 kurze Striche). Mit der fehlenden Zeile wurden trotz 3 sek Sleep alle 4 nur für einen kurzen Moment angezeigt, dann waren sie schon wieder weg. Wenn die Zeile auskommentiert bleibt, werden nur 2 Striche für den kurzen Moment angezeigt, die anderen beiden blitzen nur kurz auf. So kurz, dass ich nicht feststellen konnte, ob es 2 waren, oder nur 1 war.
-
Funktion _WinAPI_GetWindowDC
Im Beispiel ist wohl irrtümlicherweise eine Zeile auskommentiert.
; _WinAPI_DrawLine($hDC, $iStart_x, $iStart_y + $iLength, $iStart_x, $iStart_y + 5) ; vertical down
Gruß,
Bernd.