Poweshell-Skript soll nur einmal gleichzeitig laufen dürfen?
Hi,
Ich habe ein Powershell-Skript, welches zyklisch Eingaben aus einer Datei einliest (solange es aktiv ist).
Wie verhindere ich das es aus versehen ein 2. Mal gestartet wird während das erste schon/noch läuft?
Ich müsste ja irgendwie prüfen, ob ein Prozess mit einem bestimmten Namen schon existiert, dann könnte ich beim Start des Skriptes darauf prüfen.
Vielen Dank für jegliche Denkanstöße oder Richtungsstupser
Jan
Ich habe ein Powershell-Skript, welches zyklisch Eingaben aus einer Datei einliest (solange es aktiv ist).
Wie verhindere ich das es aus versehen ein 2. Mal gestartet wird während das erste schon/noch läuft?
Ich müsste ja irgendwie prüfen, ob ein Prozess mit einem bestimmten Namen schon existiert, dann könnte ich beim Start des Skriptes darauf prüfen.
Vielen Dank für jegliche Denkanstöße oder Richtungsstupser
Jan
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 566186
Url: https://administrator.de/contentid/566186
Ausgedruckt am: 22.11.2024 um 05:11 Uhr
15 Kommentare
Neuester Kommentar
Klar, ein lockfile!
Die Methode hat einen entscheidenden Nachteil: Sollte dein Script unerwartet abbrechen/beendet werden wird die Datei nicht gelöscht und dein Script startet nie wieder. Zumindest so lange nicht bis jemand manuell die Datei löscht.
Deswegen würde ich das etwa so lösen:
If (Get-WmiObject win32_process | Where -Property CommandLine -Match "meinscript.ps1") {
machwas
} Else {
machwasanderes
}
Manuel
In die Richtung komme ich leider nicht weiter. In der Property "CommandLine" steht nur Powershell.exe - leider nicht das Skript, welches dort ausgeführt wird.
Doch, das steht da ganz sicher drin. Aber natürlich nur, wenn auch ein Script läuft. Genauer gesagt muss das Script auch über die Kommandzeile gestartet worden sein. Eine Powershell starten und dann darin das Script aufrufen führt nicht zum gewünschten Ergebnis. Aber das hast du normalerweise ja eher nicht. Entweder startet ein Benutzer das Script ja vermutlich über rechte Maustaste > mit Powershell ausführen oder es gibt eine Verknüpfung zum Script oder einen geplanten Task.
Das sagt ja auch die Property CommandLine. Wenn der Scriptname nicht in der aufrufenden Befehlzeile drin steht, dann ist die Bedingung naturlich nicht erfüllt.
Als Beispiel habe ich hier mal ein Script laufen lassen, das einfach nur eine Loop macht damit es ewig läuft. Als Ausgabe von
Get-WmiObject win32_process | Where -Property CommandLine -Match "testloop.ps1"
CommandLine:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" "-Command" "if((Get-ExecutionPolicy ) -ne 'AllSigned') { Set-ExecutionPolicy -Scope Process Bypass }; & 'C:\Users\<meinuser>\Desktop\testloop.ps1'"
Manuel
Hallo,
dafür gibt es Mutexe.
Siehe etwa https://www.msxfaq.de/code/powershell/ps-mutex.htm
Am Anfang des Skriptes versuchen, den Mutex zu erhalten, bei Fehler Skript abbrechen. Am Ende des Skriptes idealerweise den Mutex wieder freigeben. Selbst wenn das nicht erfolgt, wird er bei Beendendes Prozesses freigegeben, es wird dann nur bei der nächsten Abfrage eine Exception geworfen.
-> Saubere Zustandssynchronisierung über mehrere Prozesse, ohne Dateien, ohne darauf angewiesen zu sein, dass der Skriptname immer gleich ist, ohne Deadlock, wenn das Skript abstürtzt, ohne...
Grüße
Filipp
dafür gibt es Mutexe.
Siehe etwa https://www.msxfaq.de/code/powershell/ps-mutex.htm
Am Anfang des Skriptes versuchen, den Mutex zu erhalten, bei Fehler Skript abbrechen. Am Ende des Skriptes idealerweise den Mutex wieder freigeben. Selbst wenn das nicht erfolgt, wird er bei Beendendes Prozesses freigegeben, es wird dann nur bei der nächsten Abfrage eine Exception geworfen.
-> Saubere Zustandssynchronisierung über mehrere Prozesse, ohne Dateien, ohne darauf angewiesen zu sein, dass der Skriptname immer gleich ist, ohne Deadlock, wenn das Skript abstürtzt, ohne...
Grüße
Filipp
Moin,
du kannst dem Skript auch einfach einen eigenen Fenstertitel verpassen, nach diesem kannst du dann ganz leicht filtern
Gruß Thomas
du kannst dem Skript auch einfach einen eigenen Fenstertitel verpassen, nach diesem kannst du dann ganz leicht filtern
$Host.UI.RawUI.WindowTitle='Mein Skript'
if ((Get-Process Powershell| ?{$_.MainWindowTitle -match $Host.UI.RawUI.WindowTitle}).Count -gt 1) {Return}
# Ab hier läuft das Skript nur noch ein mal...
Gruß Thomas
Zitat von @jan-markus:
Hab das jetzt einmal als Test so umgesetzt.
Wenn du willst, dass dem Benutzer hier etwas angezeigt wird, musst du vor dem Return natürlich auch noch einen sleep oder ähnliches einbauen, sonst ist das Skript ja beendet, bevor du den write-host Befehl lesen kannstHab das jetzt einmal als Test so umgesetzt.
if ((Get-Process | ?{$_.MainWindowTitle -match $Host.UI.RawUI.WindowTitle}).Count -gt 1) {
Write-Host "Nein. Da ist noch ein anderer $ProcessName!"
Return
}
while ($true) {
Write-Host "Hallo? Bin ich allein?"
Start-Sleep 5
}
Weiß nicht, ob ich damit alle Fälle abdecke...
Was meinst du mit "alle Fälle"?! Es gibt doch nur 2 Fälle, entweder läuft bereits eine Instanz des Skripts - oder eben nicht.
Moin,
Es wird nach Prozessen mit dem Titel gesucht und wenn von dem Output .Count größer 1 ist, also mehr als eine Instanz gefunden wurde, erfolgt der Return.
Gruß Thomas
Zitat von @NordicMike:
So nebenbei, weil eine Lösung wurde mit Mutex schon genannt: Wie verhindert man, dass sich das Script selbst findet?
Guck dir das If-Statement mal genau an... wie man verhindert das sich das Script selbst findet - gar nicht So nebenbei, weil eine Lösung wurde mit Mutex schon genannt: Wie verhindert man, dass sich das Script selbst findet?
Es wird nach Prozessen mit dem Titel gesucht und wenn von dem Output .Count größer 1 ist, also mehr als eine Instanz gefunden wurde, erfolgt der Return.
Gruß Thomas