powershell "if" (programm läuft)?


09.12.2022, 14:52

Bim im Moment voll von Powershell fasziniert und möchte es praktisch nutzen können.

2 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

@Nythdoll hat für Deine Frage bereits die Lösung geliefert. Aus den Kommentaren ergibt sich jedoch, das es um etwas völlig anderes geht.

if (Get-Process "Teams" -ErrorAction SilentlyContinue)
 {taskkill /IM Teams.exe /F
...usw...

Du verwendest in Powershell Taskkill zum beenden von Programmen. Dieser Befehl hat in Powershell nichts zu suchen. Taskkill gibt seine Statusmeldungen im Errorstream aus . Der komplette Output könnte in PowerShell mit 2>&1>$null ins "Nirvana" umgeleitet werden.

taskkill /im teams.exe 2>&1>$null

... bleibt jedoch trotzdem, das Taskkill nicht hierher gehört.

PowerShell hat seine Eigenes Cmdlet zum Beenden von Programmen Stop-Process .

dein Script sähe damit so aus:

if (Get-Process 'Teams' -ErrorAction SilentlyContinue){
    Stop-Process -name 'teams'
    write-host "Teams wurde geschlossen" -ForegroundColor yellow
}
else {
    write-host "Teams ist bereits geschlossen" -ForegroundColor red
}
sleep 1
if (Get-Process 'Hofer.ADV.AZE.UI' -ErrorAction SilentlyContinue){
    Stop-Process -name 'Hofer.ADV.AZE.UI'
    write-host "AZE wurde geschlossen" -ForegroundColor yello
}
else {
    write-host "AZE ist bereits geschlossen" -ForegroundColor red
}
sleep 1
if (Get-Process 'outlook' -ErrorAction SilentlyContinue) {
    Stop-Process -name 'outlook'
    write-host "Outlook wurde geschlossen" -ForegroundColor yellow
}
 else {write-host "Outlook ist bereits geschlossen" -ForegroundColor red
 }
''
sleep 3
Write-Host "Schönen Tag" -ForegroundColor yellow
pause

Gruseliger Spagetticode 😱 Wenn man für verschiedene Dinge imme das gleiche machen möchte geht das in PowerShell viel einfacher:

 #alle  Namen in die Pipe  werfen
'Teams','Hofer.ADV.AZE.UI','outlook'|
    ForEach-Object{ #für  alles in der Pipe  
        if (Get-Process $_ -ErrorAction SilentlyContinue){
            Stop-Process -name $_
            write-host "$_ wurde geschlossen" -ForegroundColor yellow
        }
        else {
            write-host "$_ ist bereits geschlossen" -ForegroundColor red
        }
        sleep 1
    }

Aber wozu erst Prüfen und dann Killen? Stop-Process prüft ja ohnehin selbst. und man kann Positive Kills in die Pipe schicken. Wenn man denn auch noch sagen möchte was nicht geklappt hat, kann man hinterher nachschauen.

$KillList = 'Teams','Hofer.ADV.AZE.UI','outlook'
$Kills = Stop-Process -Name $KillList -Passthru -ErrorAction SilentlyContinue|
    %{ Write-Host "$($_.ProcessName) wurde geschlossen" -ForegroundColor yellow;$_.ProcessName}
$KillList|
    ?{ $_ -notin $Kills}|
    %{write-host "$_ war  bereits geschlossen" -ForegroundColor red}


Woher ich das weiß:eigene Erfahrung – Ich mach das seit 30 Jahren
SirFabio413 
Fragesteller
 11.12.2022, 23:37

Junge ich blick nicht mehr durch. Um das zu verstehen muss ich mir die nächsten zwei Tage frei nehmen hahah :) Aber vielen Dank für deine Tipps und die verschiedenen Varianten. Kenn mich echt nicht gut aus und hab im Internet einfach den Befehl taskkill gefunden. Aber danke dass du mir andere Möglichkeiten gezeigt hast. Um den Part mit dem ForEach zu verstehen brauch ich noch bisschen Zeit hahah.

1
Erzesel  12.12.2022, 07:44
@SirFabio413

Powershells Pipelining ist einfach zu verstehen.

  • Stell dir einen Trichter mit einem Rohr vor, in den du was reinwirfst. 
  • Das kann ein Befehl, Einzelne Daten, oder Variablen usw. sein.
  • Das Rohr führt zu einem Cmdlet/Befehl, der was tut 
  • und das Ergebnis wieder ins Rohr gibt,
  • welches zum nächsten Befehl geht
  • usw. Bis die Pipline zu Ende ist.
  • Das Ergebnis wird ausgegeben oder in eine Variable gespeichert. 

Das Zeichen '|' nennt sich Pipe , ist also das Rohr zum nächsten Befehl. 

Daten | Machwas | MachwasAnderes | usw. 

Da man (oder ein Cmtlet/Befehl) mehrere Objekte in die "Röhre" werfen kann, aber jedes einzeln behandeln möchte gibt es das Cmdlet ForEach-Object (abgekürzt: foreach oder %). Übersetzt: Für Jedes Ding (in der Pipline).

Das führt für jedes "Ding" in der Pipe die in {...} angegeben Operationen aus. 

'Wau','Miau',3, 7,'6'|%{
   #mach aus jedem Objekt (je  nach Art der Daten) das 3-fache
  $_ * 3
}
  • $_ ist ein einzelnes Datenobjekt in der Pipeline.
  • Powershell ist "intelligent" und weiß welchen Typ ein Objekt hat . und reagiert behandelt dieses entsprechend

Ergebnis:

WauWauWau
MiauMiauMiau
9
21
666

Kannst Du dich nicht Entscheiden was Du auf dem nächsten Lottoschein schreiben sollst?

1..6|%{
   "$_. Tip"
   1..49|Get-Random -count 6|sort
}

Natürlich kann man auch (wie in jeder beliebigen anderen Sprache) klassisch mit for und if etc programmieren. Aber will man das noch, wenn man das Prinzip der "Rohrleitung" verstanden hat?

1
SirFabio413 
Fragesteller
 12.12.2022, 08:22
@Erzesel

Wow! Danke habs kappiert! Krass klingt echt gut. :)

0

Um in der PowerShell zu überprüfen, ob ein bestimmtes Programm läuft, kannst du die Get-Process-Cmdlet verwenden. Hier ist ein Beispiel:

if (Get-Process "teams" -ErrorAction SilentlyContinue) {
   Write-Output "Hello"
} else {
   Write-Output "Bye"
}

Dieser Code überprüft, ob ein Prozess mit dem Namen "teams" läuft, und gibt dann "Hello" aus, wenn der Prozess läuft, oder "Bye" aus, wenn der Prozess nicht läuft.

Hinweis: Die Option -ErrorAction SilentlyContinue verhindert, dass die Cmdlet eine Fehlermeldung ausgibt, falls der Prozess nicht gefunden wird.

Ich hoffe, dass dies hilfreich ist.

SirFabio413 
Fragesteller
 09.12.2022, 15:07

Jaa omg, vielen Dank das ist sehr kurz un knackig wie man so sagt :) Ich dachte nicht dass man Get-Process so verwenden kann, aber das wird mir sehr weiterhelfen! Und danke für die Info mit dem ErrorAction das kann ich ab jetzt immer einbauen! :)

Schönen Tag dir!
Und danke nochmals für die tolle Hilfe!

0
SirFabio413 
Fragesteller
 09.12.2022, 15:26

Oh noch eine Frage: Habe gerade gemerkt, dass wenn ich jetzt folgendes Skript ausführe, (wenn teams geschlossen wurde) X mal steht:
"ERFOLGREICH: Der Prozess "Teams.exe" mit PID 26340 wurde beendet.
Dann erst kommen meine Write--Host Feedbacks. Woran liegt das?

Skript:

 if (Get-Process "Teams" -ErrorAction SilentlyContinue)

 {taskkill /IM Teams.exe /F

 write-host "Teams wurde geschlossen" -ForegroundColor yellow}

 else {write-host "Teams ist bereits geschlossen" -ForegroundColor red}

sleep 1

 if (Get-Process "Hofer.ADV.AZE.UI" -ErrorAction SilentlyContinue)

 {taskkill /IM Hofer.ADV.AZE.UI.exe /F

 write-host "AZE wurde geschlossen" -ForegroundColor yellow}

 else {write-host "AZE ist bereits geschlossen" -ForegroundColor red}

sleep 1

 if (Get-Process "outlook" -ErrorAction SilentlyContinue)

 {taskkill /IM outlook.exe /F

 write-host "Outlook wurde geschlossen" -ForegroundColor yellow}

 else {write-host "Outlook ist bereits geschlossen" -ForegroundColor red}

 echo ""

sleep 3

 Write-Host "Schönen Tag" -ForegroundColor yellow

 sleep 1

0
Nythdoll  09.12.2022, 15:51
@SirFabio413

Es ist möglich, dass die Ausgabe der Meldungen "ERFOLGREICH: Der Prozess "Teams.exe" mit PID 26340 wurde beendet." von dem Befehl taskkill verursacht wird, der verwendet wird, um den Prozess "Teams.exe" zu beenden.

Um diese Meldungen zu unterdrücken, kannst du den Befehl taskkill wie folgt ändern:

taskkill /IM Teams.exe /F /T

Das /T-Flag wird verwendet, um alle untergeordneten Prozesse des angegebenen Prozesses zu beenden, und das /F-Flag wird verwendet, um die Beendigung des Prozesses erzwingen. Dies sollte die Meldungen unterdrücken und dein eigenen Write-Host-Feedbacks sollten angezeigt werden.

hoffentlich hilft dir das weiter :D

0
SirFabio413 
Fragesteller
 09.12.2022, 16:02
@Nythdoll

Mein taskkill sieht exakt so aus nur ohne das /T werde es eben versuchen.

0
SirFabio413 
Fragesteller
 09.12.2022, 16:05
@SirFabio413

Leider geht es auch mit /T nicht. Ich denke schon dass die Ausgabe vom Taskkill kommt. Liegt es vielleicht am rest meines Codes? Also jeweils an dem was nach des Taskkills kommt?

0
Erzesel  10.12.2022, 09:58
@Nythdoll

in Powershell Consoleoutput ins Nirvana schicken :

taskkill /im teams.exe /f 2>&1>$null

0