; #NoTrayIcon #include #include #include #include #include #include ; #include ; wird für nur für _ArrayDisplay benötigt. ; #include ; #include AutoItSetOption("MustDeclareVars", 1) ; Nur 1 Programm-Instanz zulassen. If _Singleton("PSPad->AutoIt3_CompilerRunner", 1) = 0 Then ; Meldung für User. MsgBox($MB_SYSTEMMODAL + $MB_ICONERROR, "AutoIt3_CompilerRunner: - Error -", _ '"AutoIt3_CompilerRunner" is already running') Exit EndIf ; AutoIt3PID global deklarieren, damit sie auch in "Terminate_ChildAu3()" verfügbar ist. Global $g_iAutoIt3PID = 0 AutoIt3_CompilerRunner_Main() ; ========================================================================= ; AutoIt3_CompilerRunner_Main ; ; Aufruf dieses Script nur aus PSPad sinnvoll. Beim Aufruf sollten folgende ; Parameter übergeben werden: ; $CmdLine[1]: TypToRun ("/Run", "/Compile", "/CompileDialog", "/Check") ; $CmdLine[2]: ActiveAu3Path ($sAu3FilePath) ; ------------------------------------------------------------------------- Func AutoIt3_CompilerRunner_Main() Local $hPSPad = Null Local $tLogCtrls Local $iParamsCount Local $sRunParams Local $sTypToRun Local $sAu3FilePath Local $sExeFilePath Local $sAutoIt3Command ; PSPad-Handle ermitteln. ; WinWaitActive("[CLASS:TfPSPad]") ; <== Nur für Tests das hier benutzen. $hPSPad = _WinAPI_GetForegroundWindow() If $hPSPad = Null Then MsgBox($MB_SYSTEMMODAL + $MB_ICONWARNING, 'AutoIt3_CompilerRunner: - Error -', 'No handle found for PSPad!') Exit(2) ; 2 = PSPad-hwnd nicht gefunden. EndIf ; Code nur ausführen, wenn das Fenster ein PSPad-Fenster ist. If _WinAPI_IsClassName($hPSPad, "TfPSPad") Then Local $iParamsCount = $CmdLine[0] ; $CmdLine[x] sind die übergebenen Startparameter als Array, ; wobei $CmdLine[0] die Anzahl der übergebenen Startparameter angibt, ; $CmdLine[1] beinhaltet den ersten Parameter usw. ; Falls keine Parameter übergeben wurden, eine Meldung zeigen. If ($iParamsCount = 0) Then MsgBox($MB_SYSTEMMODAL + $MB_ICONINFORMATION, "AutoIt3_CompilerRunner", _ " - - - - Es wurden keine Parameter übergeben. - - - - " & @CRLF & @CRLF & _ " - - - - - - - No parameters were passed - - - - - - - " _ ) Else ; falls mindestens ein Parameter angegeben wurde ; Handle und ID vom Log-Fenster ermitteln. $tLogCtrls = PSPad_GetLogControls($hPSPad, 'Log') ; LogWin wird in PSPad dynamisch erstellt. Prüfen ob es existiert. If $tLogCtrls.hWnd_ListBox > 0 then ; Hint: Es lohnt nicht, das Log-Win in PSPad von hier aus sichtbar zu machen. ; Die Verzögerung ist zu groß und lässt das Programm träge erscheinen. ; Log-Fenster leeren. _GUICtrlListBox_ResetContent($tLogCtrls.hWnd_ListBox) Else ; Log-Fenster konnte nicht gefunden werden. MsgBox($MB_SYSTEMMODAL + $MB_ICONERROR, "AutoIt3_CompilerRunner: - Error -", _ "The log window of PSPad could not be found.") Exit EndIf ; [1]: TypToRun ("/Run", "/Compile", "/CompileDialog", "/Check") ; [2]: ActiveAu3Path ($sAu3FilePath) ; Run: /prod /in "%File%" /run /ErrorStdOut /UserParams ; Compile: /prod /in "%File%" /out "%Dir%%Name%.exe" ; /prod /in "%File%" /out "%Dir%%Name%.exe" /NoStatus ; CompileDialog: /prod /in "%File%" /ShowGui ; Check: /prod /in "%File%" /AU3check ; Check (Short): "C:\Program Files (x86)\AutoIt3\Au3Check.exe" "%File%" $sTypToRun = $CmdLine[1] $sAu3FilePath = $CmdLine[2] Switch $sTypToRun Case '/Run' $sRunParams = ' /prod /in "' & $sAu3FilePath & '" /run /ErrorStdOut /UserParams' Case '/Compile' $sExeFilePath = StringReplace($sAu3FilePath, ".au3", ".exe", -1) $sRunParams = ' /prod /in "' & $sAu3FilePath & '" /out "' & $sExeFilePath & '"' ; & ' /NoStatus' Case '/CompileDialog' $sRunParams = ' /prod /in "' & $sAu3FilePath & '" /ShowGui' Case '/Check' $sRunParams = ' /prod /in "' & $sAu3FilePath & '" /AU3check' Case Else MsgBox($MB_SYSTEMMODAL + $MB_ICONINFORMATION, "AutoIt3_CompilerRunner", _ 'Wrong parameter for "TypToRun": ' & $sTypToRun) EndSwitch $sAutoIt3Command = _ '"' & @ProgramFilesDir & '\AutoIt3\AutoIt3.exe"' _ & ' "' & @ProgramFilesDir & '\AutoIt3\SciTE\AutoIt3Wrapper\AutoIt3Wrapper.au3"' _ & $sRunParams ; MsgBox(0, "", $sAutoIt3Command) $g_iAutoIt3PID = Run($sAutoIt3Command, "", @SW_HIDE, $STDOUT_CHILD) ; Ausgabe nach Error-Lines durchsuchen und korrigieren, denen Spaltenangaben fehlen. CaptureAutoIt3Output_AndSendToLogWin($hPSPad, $tLogCtrls) EndIf Else ; Falls das Fenster KEIN PSPad-Fenster ist. EndIf EndFunc ; ==> AutoIt3_CompilerRunner_Main ; ========================================================================= ; CaptureAutoIt3Output_AndSendToLogWin ; ; Ausgabe von AutoIt3 auslesen, aufbereiten und ans Log-Fenster von PSPad ; senden. ; ------------------------------------------------------------------------- Func CaptureAutoIt3Output_AndSendToLogWin($_hPSPad, $_tLogCtrls) Local $hLB_hwnd Local $hLB_ID Local $sRead Local $iFoundPos Local $sLine Local $hUser32DLL Local $StartTime_OfCtrlBreak = 0 ; Handle und ID vom Log-Fenster. $hLB_hwnd = $_tLogCtrls.hWnd_ListBox $hLB_ID = $_tLogCtrls.ID_ListBox $hUser32DLL = DllOpen("user32.dll") ; For "_IsPressed". While 1 ; Eine Portion aus dem Output-Stream lesen. $sRead = StdoutRead($g_iAutoIt3PID) ; Schleife beenden, falls Prozess beendet wurde oder StdoutRead Fehler zurückgibt. If @error Then ExitLoop ; Wenn ein Script gestartet ist und unterbrochen wird, z. B. weil eine GUI oder ; eine MsgBox angezeigt wird, kommt in der Zeit kein neuer Output an. Deshalb zum ; einen ein Sleep einbauen, damit die Schleifen nicht die CPU hochdrehen, und zum ; anderen die innere Do-Schleife nur ausführen, wenn Output ankommt, weil sonst ; das Log-Fenster in PSPad heftig flackert, wenn man ins Log-Fenster klickt. If $sRead = "" Then Sleep(10) Else ; Deaktiviert die Aktualisierung der ListBox. ; Sehr wichtig! Ohne Deaktivierung wird die Ausgabe verfälscht. _GUICtrlListBox_BeginUpdate($hLB_hwnd) Do $iFoundPos = StringInStr($sRead, @CRLF) ; Wenn die Output-Portion kein @CRLF enthält, die Portionen solange ; sammeln, bis ein @CRLF gefunden wird. If $iFoundPos = 0 then $sLine = $sLine & $sRead $sRead = "" Else ; Output-Portion mit @CRLF in einzelne Zeilen aufteilen. ; Neue Portion auslesen bis zum ersten @CRLF und mit den schon ; gesammelten Portionen kombiniern. "$iFoundPos - 1" = Zeichen VOR dem @CRLF. $sLine = $sLine & StringLeft($sRead, $iFoundPos - 1) $sLine = PrepareAutoIt3Output($sLine) ; Zeichen für den LogParser ergänzen. _GUICtrlListBox_AddString($hLB_hwnd, $sLine) ; Zeile ans Log senden. $sLine = "" ; Gesammelte Portionen löschen. ; Den Teil inklusive @CRLF aus der Portion entfernen. ; "$iFoundPos - 1" = Zeichen VOR dem @CRLF. $sRead = StringMid($sRead, $iFoundPos - 1 + StringLen(@CRLF)) ; Sollte ein Portion enden mit einem Teil ohne @CRLF, den Teil sammeln. ; Es wird davon ausgegangen, dass der Output mit @CRLF in Zeilen ; geteilt ist, und dass es keine letzte Zeile OHNE @CRLF gibt. If ($sRead <> "") And (StringInStr($sRead, @CRLF) = 0) Then $sLine = $sRead $sRead = "" EndIf EndIf Until $sRead = "" ; Blockierung aufheben (aktiviert die Aktualisierung). _GUICtrlListBox_EndUpdate($hLB_hwnd) EndIf ; Ermitteln ob Ctrl+Break gedrückt wurde. (03: Control-break processing) If _IsPressed("03", $hUser32DLL) And ($_hPSPad = _WinAPI_GetForegroundWindow()) Then ; Countdown nur starten beim ersten Ctrl+Break. If ($StartTime_OfCtrlBreak = 0) Then $StartTime_OfCtrlBreak = _NowCalc() EndIf ; Wenn Ctrl+Break gedrückt wurde, den ChildAu3-Prozess beenden, falls er ; nach 4 Sekunden noch existiert. If ($StartTime_OfCtrlBreak > 0) And ProcessExists($g_iAutoIt3PID) Then If (_DateDiff('s', $StartTime_OfCtrlBreak, _NowCalc()) > 4) Then Terminate_ChildAu3() ; ExitLoop EndIf EndIf WEnd DllClose($hUser32DLL) ; For "_IsPressed". EndFunc ; ==> CaptureAutoIt3Output_AndSendToLogWin ; ========================================================================= ; PrepareAutoIt3Output ; ; Aufbereiten der Zeilen, die Debug- und Laufzeitfehler-Meldungen enthalten, ; sodass der LogParser mit allen Zeilen zurecht kommt. ; ; Beide Meldungsarten haben eine Zeilenangabe ohne Spaltenangabe. Diese ; werden ergänzt. ; ------------------------------------------------------------------------- Func PrepareAutoIt3Output($_sLine) Local $arRowInfo ; Example lines ------------------------------------------------------- ; "E:\FileQuantityLimit (Testdatei).au3"(112,16) : warning: $iTest possibly not declared/created yet ; "E:\FileQuantityLimit (Testdatei).au3"(131,11) : error: zzzz(): undefined function. ; "E:\FileQuantityLimit (Testdatei).au3" (163) : ==> Array variable has incorrect number of subscripts or subscript dimension range exceeded.: ; @@ Debug(66) : $hMyCtroHWND = 0x001D0C6E ; Zeile untersuchen, ob eine "Debug"-Meldung drin ist. If StringInStr($_sLine, "@@ Debug(") Then ; Zahlenteil zwischen den Klammern auslesen. $arRowInfo = _StringBetween($_sLine, "@@ Debug(", ") : ") If IsArray($arRowInfo) Then If StringInStr($arRowInfo[0], ",") = 0 Then ; Kein Komma enthalten. ; Zahlenteil ergänzen (und " error:" einfügen, damit die Zeile eine roten Marker bekommt). ; Vorher: .au3" (163) : ==> Array ... ; Nachher: .au3" (163,1) : error: ==> Array ... $_sLine = StringReplace($_sLine, ") : ", ",1) : ", 1) EndIf EndIf ; Zeile untersuchen, ob eine "Pfeil"-Meldung drin ist (= Laufzeit-Fehler). ElseIf StringInStr($_sLine, ") : ==>") Then ; Zahlenteil zwischen den Klammern auslesen. $arRowInfo = _StringBetween($_sLine, "(", ") : ==>") If IsArray($arRowInfo) Then If StringInStr($arRowInfo[0], ",") = 0 Then ; Kein Komma enthalten. ; Zahlenteil ergänzen (und " error:" einfügen, damit die Zeile eine roten Marker bekommt). ; Vorher: .au3" (163) : ==> Array ... ; Nachher: .au3"(163,1) : error: ==> Array ... $_sLine = StringReplace($_sLine, '.au3" (', '.au3"(', 1) $_sLine = StringReplace($_sLine, ") : ==>", ",1) : error: ==>", 1) EndIf EndIf EndIf ; Rückgabe Return $_sLine EndFunc ; ==> PrepareAutoIt3Output ; ========================================================================= ; PSPad_GetLogControls ; ; Funktion zum Ermitteln der Controls des Log-Fensters. ; ; Wichtig: $_sSheetText = 'Log' funktioniert in allen Sprachen. Für ; 'Search', ..., 'FTP' muss die jeweilige in PSPad eingestellte ; Sprache mit den Suchbegriff für $_sSheetText übereinstimmen! ; ------------------------------------------------------------------------- Func PSPad_GetLogControls($_hPSPad, $_sSheetText = 'Log') Local $sStruct_LogCtrls = _ 'hwnd hWnd_PageControl;' & _ ; TPageControl: Parent von TabSheet. 'int ID_PageControl;' & _ 'hwnd hWnd_TabSheet;' & _ ; TTabSheet: Parent von TListBox. 'int ID_TabSheet;' & _ 'hwnd hWnd_ListBox;' & _ ; TListBox: Zeigt den Inhalt des Log-Fensters. 'int ID_ListBox;' Local $tResult = DllStructCreate($sStruct_LogCtrls) Local $aEnum Local $sSheet Local $i, $x ; Alle ChildWindows in ein Array speichern. $aEnum = _WinAPI_EnumChildWindows($_hPSPad, False) If IsArray($aEnum) Then For $i = 1 To $aEnum[0][0] ; Nach Klasse "TTabSheet" suchen. If $aEnum[$i][1] = "TTabSheet" Then $sSheet = ControlGetText($_hPSPad, '', _WinAPI_GetDlgCtrlID($aEnum[$i][0])) ; Prüfen ob 'Log', 'Search', ..., 'FTP' gesucht werden soll. If $sSheet = $_sSheetText Then ; TabSheet gefunden. ; Daten von TabSheet gleich mal im Struct speichern. $tResult.hWnd_TabSheet = $aEnum[$i][0] $tResult.ID_TabSheet = _WinAPI_GetDlgCtrlID($tResult.hWnd_TabSheet) ; 'PageControl' beinhaltet das Sheet und das Log-Fenster. Daten speichern. $tResult.hWnd_PageControl = _WinAPI_GetParent($tResult.hWnd_TabSheet) $tResult.ID_PageControl = _WinAPI_GetDlgCtrlID($tResult.hWnd_PageControl) ; Verbleibende Childs durchsuchen, denn nächst folgendes ; Handle der Klasse "TListBox" gehört zum TabSheet. For $x = $i + 1 To $aEnum[0][0] ; Nach Klasse "TListBox" suchen. If $aEnum[$x][1] = "TListBox" Then $tResult.hWnd_ListBox = $aEnum[$x][0] $tResult.ID_ListBox = _WinAPI_GetDlgCtrlID($tResult.hWnd_ListBox) Return $tResult ; Wenn gefunden, dann raus aus der Funktion. EndIf Next EndIf EndIf Next EndIf ; Falls nicht gefunden, leeres Result zurückgeben, um Laufzeitfehler zu vermeiden. Return $tResult EndFunc ; ==> PSPad_GetLogControls ; ========================================================================= ; Terminate_ChildAu3 2019-11-16 ; ; Alle von diesem Script gestarteten AutoIt Prozesse beenden. ; Wichtig wenn sich ein Script aufgehängt hat, z. B. wegen Endlosschleife. ; ; AutoIt3Wrapper registriert die folgenden beiden HotKeys: ; "Ctrl+Alt+Break to Restart" and "Ctrl+Break to Stop" ; Die funktionieren auch soweit, außer wenn sich ein Script aufgehängt hat, ; z. B. in einer Endlosschleife. ; "Ctrl+Alt+Break to Restart" funktioniert auch dann, ; "Ctrl+Break to Stop" funktioniert dann NICHT! ; ------------------------------------------------------------------------- Func Terminate_ChildAu3() If $g_iAutoIt3PID <> 0 Then ProcessClose($g_iAutoIt3PID) MsgBox($MB_SYSTEMMODAL + $MB_ICONERROR, "AutoIt3_CompilerRunner: - Error -", _ "The process did not react. An abrupt termination was forced!") ; For debug and user notification. EndIf EndFunc ; ==> Terminate_ChildAu3