Perfekt, danke - kann ich direkt so übernehmen.
Ich hatte an etwas wie "Kill Process Tree" beim Process Explorer gedacht, aber der kann natürlich genau so sequentiell arbeiten wie Dein Script.
Beiträge von HansJ54
-
-
-
Du hast Recht, durch das "Local" werden die Variablen ja im Prinzip schon gestackt. Und durch das "Local" kann man beide Werte platzsparend in nur eine Zeile schreiben. Das ging bei mir nicht, weil ich die Variablen außerhalb als "Global" deklariert hatte.
Das "called from" hatte ich schon mal mit einer eigenen Function() implementiert, brauche ich aber zum Debuggen eigentlich nicht. Mit "Local" statt "Global" komme ich super hin. Danke!
-
Du hast Recht. Ohne das "After" könnte man nach Beenden z.B. von verschachtelten Funktionen nicht wissen, wohin und ab wo man zurückgekommen ist. Wobei natürlich dann die Zeilennummern helfen könnten, wenn man nicht gerade zwischen 2 Includes hin- und her gesprungen ist.
Allerdings auch schwierig, wenn es innerhalb einer Funktion an mehreren Stellen Returns gibt. Dazu müsste man die Werte dann in einen Stack schreiben. Mit jedem Function-Call was obendrauf und jedem Return wieder weg.
Das wäre dann wohl ein "Feature Request" für AutoIt (mit wenig Chancen zur Verwirklichung)
-
Schade, aber danke - dann muss ich nicht weiter suchen.
Als Workaround ist natürlich möglich, dass ich in jeder Function() stattdessen $sFuncName="xxx" und $sInclude="yyy" vorne deklariere.
Um die Funktionen nicht zu sehr aufzublähen, ist es irgendwie möglich, 2 Befehle in eine Zeile zuschreiben?
Oder anderer Workaround: Func _Umgebung($sFuncName, $sInclude) und dann in jeder Function die Function als erstes aufrufen.
Oder noch eine Idee: bei irgendwelchen alten Programmiersprachen (Fortran, Cobol?), die ich mal vor vielen Jahren gelernt habe, konnte man irgendwelche Variablen für die Kompilierung definieren, die als erstes in einem Precompile einfach ersetzt wurden. Also oben $$Include="xxx" und unten im Programm wurden dann alle $$Include vor dem Compile durch "xxx" ersetzt.
-
He He - das ist nicht auf meinem Mist gewachsen.
Eure Namen sind zum Verwechseln ähnlich - zumindest wenn es so warm ist wie jetzt
Gleich noch eine doofe Frage: der String, den ich mit StringSplit in das Array stecke, hat am Ende einmal einen leeren Eintrag und dann noch einen mit 1 Byte. Jetzt brauche ich mal eine Idee, wie ich den String vor dem Zerlegen in Hex Byte für Byte anzeigen kann um zu sehen, was da hinten dran hängt. Auf Anhieb nichts dazu gefunden, wie das geht.
-
Quatsch, das ist so, als ob du Äpfel mit Birnen vergleichst... in Post #9 verwendest du in dem Run() den Befehl Find, in Post #14 machst du es ganz anders - ohne Find.
Könnte man so verstehen, aber ich meinte "das Problem mit dem Suchstring" - im neuen Script also ohne Problem da ohne Find und funktioniert ja perfekt
Dasselbe wie bei dir: Hiermit werden alle Prozesse, die dem Suchmuster entsprechen, terminiert (gekillt).
Kannte ich auch noch nicht, wieder was gelernt - merke ich mir für andere Einsätze, spart einiges an Code. Aber im Moment will ich den User noch fragen, ob er einverstanden ist mit dem Beenden seiner Fenster oder ob er sie lieber selbst schließt und das Programm wartet so lange.
Falls es interessiert: wir nutzen den Webdriver und die UDF dazu von DANp und haben es noch nicht geschafft, eine erneute Verbindung mit einem noch laufenden Webdriver aufzunehmen, wenn der User das Programm vorher beendet hat. Und da wir immer genau dasselbe Profil benötigen, hängt die Geschichte beim Neustart, da ein neuer Chrome nicht auf das noch in Nutzung befindliche Profil zugreifen kann und stattdessen ein neues produziert. Bleibt nur Terminieren von altem Webdriver und allen Chromes oder Edges, die ihr Profil blockieren. Falls jemand eine brauchbare Beschreibung findet, wie man die Verbindung zu einem laufenden Webdriver wieder neu aufnehmen kann, großen Dank!
Zitat von HansJ54 Und wmic path und wmic process sind gleich? Hä?
Wie schon erwähnt, ich kannte den Befehl wmic bis vorgestern überhaupt noch nicht, erst durch Deine Info. Und ich habe außer auf der Seite von Apfelböck nirgendwo eine brauchbare Beschreibung gefunden. Daher der Gedanke "Process" beschäftigt sich mit den Prozessen (das war mein Ziel) und "Path" war für mich gedanklich ganz etwas anderes. Funktioniert aber scheinbar für meinen Zweck genau so gut.
Auf jeden Fall danke für Eure Hilfe!
-
Der Suchstring für Find muss in Quote stehen!
$iPID = Run(@ComSpec & ' /c ' & 'WMIC path win32_process get Processid,Commandline |find "' & $iPIDSearch & '"')
Den Suchstring hatte ich im Script in #14 weiter oben schon korrigiert, läuft ja einwandfrei jetzt. Aber was macht das "call terminate" bei Dir?
Und wmic path und wmic process sind gleich?
-
Die schnellste Lösung ist meist PowerShell, so auch hier. Und die Ausgabe ist komplett.
Danke an beide! Jetzt habe ich endlich ein Beispiel, wie ich PowerShell in AutoIt nutzen kann, aber mit meinem Script hole ich mir schon die gesuchten PIDs in ein Array mit dem ich die betreffenden Prozesse beenden kann. Ich suche tatsächlich nicht chrome an sich, sondern die chromes, die ein bestimmtes Profil nutzen ($sSearch = "chrome_wd_profil"). Und wmic ist auch schnell (von wmic hatte ich noch nie etwas gehört)
Aber jetzt brauche ich noch einen Tipp, ob es eine AutoIt-Funktion gibt, die die letzten Elemente oder alle Elemente, die leer sind, aus einer Tabelle löscht oder ob man es nur in der Art wie mein _ArrayClear() machen kann.
-
Dank Deinem Tipp mit wmic habe ich eine eine Lösung gefunden, die das nicht mehr vollständig funktionierende _WinApi_GetProcessCommandline() umgeht. Funktioniert nach ersten Tests auch ohne Admin-Rechte und kann sicher für alle möglichen Zwecke umgestaltet werden.
AutoIt
Alles anzeigen#include <Array.au3> $sSearch = "chrome" Local $aPIDs = _GetPids($sSearch, "Commandline") _ArrayDisplay($aPIDs, 'GetPIDs @error=' & @error) Func _GetPids($sSearch, $sAlias = "CommandLine") ; returns ein Array der Prozess-IDs, in deren "$sAlias" $sSearch vorkommt, @error = 1 wenn nichts gefunden. $sAlias: CommandLine, Description ; Infos zu WMIC auf der Seite https://xn--apfelbck-s4a.de/wmic-wmi-console/ (falls jemand eine brauchbare Erklärung der möglichen WMIC-Parameter sucht) $iPID = Run('wmic process where (' & $sAlias & ' like "%' & $sSearch & '%" and not description ="wmic.exe") get processid', '', @SW_MINIMIZE, $STDERR_MERGED) ProcessWaitClose($iPID) Local $aOutput = StringSplit(StdoutRead($iPID), @crlf, $STR_ENTIRESPLIT) _ArrayClear($aOutput) If StringInStr($aOutput[1], 'ProcessId') Then SetError(0) $aOutput[1] &= '(searched "' & $sSearch & '")' Else SetError(1) $aOutput[1] &= ' ' EndIf Return $aOutput EndFunc Func _ArrayClear(ByRef $aArray) Local $i = $aArray[0] While $aArray[$i] <= "0" _ArrayDelete($aArray, $i) $i -= 1 WEnd $aArray[0] = $i EndFunc
Ausgabe:
Um die aus unerfindlichen Gründen entstehenden leeren Einträge am Ende des Arrays zu entfernen, habe ich _ArrayClear() geschrieben. Da gibt es aber sicher eine bessere direkte Funktion in AutoIt? Wäre nett, wenn Du mein Script ein wenig optimieren könntest.
-
Das sieht schon etwas anders aus...
Das funktioniert tatsächlich, aber dauert und das Admin-Fenster ist nicht so gut bei den einfachen Usern. Wenn ich mich auf Chrome beschränke, geht es schneller aber das Admin-Problem bleibt.
CodeFor $i = 1 To UBound($aList) -1 If $aList[$i][0] = "chrome.exe" Then $aList[$i][2] = _Proc($aList[$i][0]) If StringInStr($aList[$i][2],"Profile") Then ConsoleWrite('PID: ' & $aList[$i][1] & @TAB & $aList[$i][2] & @CRLF) EndIf Next
Hast Du eine Idee, was bei meinem Run() falsch ist?
-
Nö, falscher Fehler. Mit $sOutput = StdoutRead($iPID) hat es nicht funktioniert und dann kam ein Test, den ich nicht vollständig zurückgenommen habe: im Run noch >c:\temp\process.txt eingefügt um zu sehen, ob das Run() überhaupt was produziert - die Datei war leer. Also ist das Run() schon nicht ok. Den Output würde ich ja vielleicht in die Variable bekommen, aber wenn nichts da ist?
Daher: an den ""; liegt es nicht, sondern an meinem Unwissen insgesamt
-
WMIC path win32_process get Processid,Commandline |find "22788" > c:\temp\proxess4.txt
Der WMIC-Befehl funktioniert in CMD . Im Ergebnis kommen dabei allerdings 5 Zeilen raus, einmal die gesuchte Commandline und die PID, danach aber noch eine Leerzeile, eine Zeile in der das FIND und die PID stehen und weitere 2.
Und mein kurzes Script funktioniert auch nicht - habe noch nie den Output eines Run()-Befehls weiterverarbeitet:
Code
Alles anzeigen$iPIDSearch = "22788" $sSearch = "CHROME-WD-Profile" $iPID = Run(@ComSpec & ' /c ' & 'WMIC path win32_process get Processid,Commandline |find ' & $iPIDSearch) ProcessWaitClose($iPID) $sOutput = "";StdoutRead($iPID) ConsoleWrite('$sOutput = ' & $sOutput & @CRLF & '>Error code: ' & @error & @CRLF) If StringInStr($sOutput, $sSearch) > 0 Then ConsoleWrite('PID ' & $iPIDSearch & ' enthält String "' & $sSearch & @CRLF) Else ConsoleWrite('PID ' & $iPIDSearch & ' enthält String "' & $sSearch & '" nicht' & @CRLF) EndIf
Optimal wäre natürlich die Rückgabe nur der zu $iPIDSearch gehörenden Commandline oder umgedreht, falls mehrfach vorkommend, Ausgabe aller PIDs, in deren Commandline $sSearch vorkommt in einem Array (noch komfortabler).
Vielen Dank für die Unterstützung - und das am Feiertag!
-
Habe schon bei VBS nachgeschaut, soll damit einfach möglich sein und das könnte man ja dann von AutoIt aus aufrufen. Aber ich verstehe trotzdem nicht, wie es funktioniert.
-
-
Die Privilegien werden im Beispiel-Script doch gesetzt, oder sehe ich das falsch?
Leider sind die Fehler 20 und 40 nicht dokumentiert - das sind die angezeigten Fehler bei leeren Zeilen. Die abgeschnittene Zeile hat Error = 0.
Mit dem "undocumented" gebe ich Dir natürlich Recht. Aber da die Funktion ja teilweise noch funktioniert, könnte sich "Yashied" die Sache vielleicht noch mal anschauen?
-
Hat vor einiger Zeit funktioniert, aber heute liefert _WinAPI_GetProcessCommandLine() nur noch bei ganz wenigen Prozessen den Inhalt der Commandline obwohl laut ProcExplorer fast überall Werte stehen.
Problem: wir starten die Browser immer mit eigenen Profilen und müssen gelegentlich genau und nur die Fenster schließen, die mit diesen Profilen gestartet wurden - die anderen Chromes dürfen weiterlaufen. In der ProcessCommandLine steht dieses Profil laut ProcExplorer - wenn genutzt und wenn gefunden könnte ich den Prozess beenden.
Gibt es eine neue Funktion oder einen Workaround?
Test mit dem Script aus der Hilfe: das Ergebnis von _WinAPI_GetProcessCommandLine() über die kompletten Prozesse - Ergebnis: seitenweise leer, nur bei ganz wenigen Prozessen wird die CommandLine angezeigt. Bei einigen auch nur ein Teil der Commandline. Bei den leeren Zeilen kommt Error = 20 oder 40.
C
Alles anzeigen#RequireAdmin #include <Array.au3> #include <WinAPIHObj.au3> #include <WinAPIProc.au3> Local $aAdjust, $aList = 0 ; Enable "SeDebugPrivilege" privilege for obtain full access rights to another processes Local $hToken = _WinAPI_OpenProcessToken(BitOR($TOKEN_ADJUST_PRIVILEGES, $TOKEN_QUERY)) _WinAPI_AdjustTokenPrivileges($hToken, $SE_DEBUG_NAME, $SE_PRIVILEGE_ENABLED, $aAdjust) ; Retrieve command-line arguments for all processes the system If Not (@error Or @extended) Then $aList = ProcessList() For $i = 1 To $aList[0][0] $aList[$i][1] = _WinAPI_GetProcessCommandLine($aList[$i][1]) Next EndIf ; Enable SeDebugPrivilege privilege by default _WinAPI_AdjustTokenPrivileges($hToken, $aAdjust, 0, $aAdjust) _WinAPI_CloseHandle($hToken) _ArrayDisplay($aList, '_WinAPI_GetProcessCommandLine')
-
-
DAS ist überhaupt kein Problem, dazu kann ich eigene Sprungmarkendefinitionen erstellen. Weitaus problematischer ist die Farbgebung, da das nur mit Lexer möglich ist und ich wohl dazu versuchen müsste die styles umzubiegen.
Was ich sicher hinbekomme:
ConsoleWrite($sText, $bErr) ; $bErr=True(rot) / False(blau) bzw. auch die Farben der anderen style.errorlist.
!@@ Debug(1234) : Text Fehler
>@@ Debug(1234) : Text Sonstiges
Ist dann mit Sprungmarke.
Das wäre super. Vielleicht noch alternativ $iErr=0 <=> $bErr=False und $iErr<>0 <=> $bErr=True
-
Wofür die einzelnen style.errorlist.n zuständig sind habe ich doch oben detailliert angeführt:
n = 3 - Sprungmarke Fehler (Standard: rot)
n = 9 - Sprungmarke Info (Standard: pink)
n = 4, 10, 11, 12 - abhängig vom ersten Zeichen (z. B. ! - rot)
Habe ich verstanden. Idee war nur, dass eine der nicht genannten n noch was Sinnvolles machen könnte. Ich habe gesucht, wo die Dinger definiert sind, aber nicht gefunden.
Wäre dir geholfen mit einer Funktion: ConsoleWriteColor($sText, $iColor) ?
Sollte m.M. nach nicht allzu schwierig umzusetzen sein mithilfe des SciTEInterface.
Damit wäre mir sehr geholfen Ist aber, wie erwähnt, nur ein "Nice-To-Have" und erleichtert mir das Debuggen - falls nicht zu viel Aufwand ... Die müsste aber natürlich "Sprungmarke" beherrschen.
Ein wenig Hintergrund: ich habe ein sehr umfangreiches Programm unter Nutzung von DanPs Webdriver.udf geschrieben und mit jeder neuen Version des Chromedrivers oder Änderungen auf den genutzten Webseiten tauchen wieder neue ominöse Fehler auf. Ich gebe zu, größtenteils meine ( ) aber manchmal auch nicht.