Подтвердить что ты не робот

Как правильно проверить, запущен ли процесс и остановить его

Каков правильный способ определить, работает ли процесс, например FireFox, и останавливать его?

Я немного огляделся, и лучшим способом я нашел следующее:

if((get-process "firefox" -ea SilentlyContinue) -eq $Null){ 
        echo "Not Running" 
}

else{ 
    echo "Running"
    Stop-Process -processname "firefox"
 }

Это идеальный способ сделать это? Если нет, то какой правильный способ сделать это?

4b9b3361

Ответ 1

Как вы это делаете, вы дважды запрашиваете процесс. Также Линн поднимает хороший момент о том, чтобы быть хорошим первым. Вероятно, я бы попытался сделать что-то вроде следующего:

# get Firefox process
$firefox = Get-Process firefox -ErrorAction SilentlyContinue
if ($firefox) {
  # try gracefully first
  $firefox.CloseMainWindow()
  # kill after five seconds
  Sleep 5
  if (!$firefox.HasExited) {
    $firefox | Stop-Process -Force
  }
}
Remove-Variable firefox

Ответ 2

Если вам не нужно отображать точный результат "running" / "not runnuning", вы можете просто:

ps notepad -ErrorAction SilentlyContinue | kill -PassThru

Если процесс не запущен, результатов не будет. Если он был запущен, вы получите вывод get-process, и процесс будет остановлен.

Ответ 3

Спасибо @Джо. Это то, что я ищу.

Я просто приношу некоторые улучшения:

  • учитывать несколько процессов
  • чтобы избежать достижения таймаута, когда все процессы завершены
  • для упаковки целого в функции

function Stop-Processes {
    param(
        [parameter(Mandatory=$true)] $processName,
                                     $timeout = 5
    )
    $processList = Get-Process $processName -ErrorAction SilentlyContinue
    if ($processList) {
        # Try gracefully first
        $processList.CloseMainWindow() | Out-Null

        # Wait until all processes have terminated or until timeout
        for ($i = 0 ; $i -le $timeout; $i ++){
            $AllHaveExited = $True
            $processList | % {
                $process = $_
                If (!$process.HasExited){
                    $AllHaveExited = $False
                }                    
            }
            If ($AllHaveExited){
                Return
            }
            sleep 1
        }
        # Else: kill
        $processList | Stop-Process -Force        
    }
}

Ответ 4

@jmp242 - универсальный тип System.Object не содержит метод CloseMainWindow, но статическое приведение типа System.Diagnostics.Process при сборе переменной ProcessList работает для меня. Обновленный код (из этого ответа) с этим приведением (и изменением цикла для использования ForEach-Object) приведен ниже.

function Stop-Processes {
    param(
        [parameter(Mandatory=$true)] $processName,
                                     $timeout = 5
    )
    [System.Diagnostics.Process[]]$processList = Get-Process $processName -ErrorAction SilentlyContinue

    ForEach ($Process in $processList) {
        # Try gracefully first
        $Process.CloseMainWindow() | Out-Null
    }

    # Check the 'HasExited' property for each process
    for ($i = 0 ; $i -le $timeout; $i++) {
        $AllHaveExited = $True
        $processList | ForEach-Object {
            If (-NOT $_.HasExited) {
                $AllHaveExited = $False
            }                    
        }
        If ($AllHaveExited -eq $true){
            Return
        }
        Start-Sleep 1
    }
    # If graceful close has failed, loop through 'Stop-Process'
    $processList | ForEach-Object {
        If (Get-Process -ID $_.ID -ErrorAction SilentlyContinue) {
            Stop-Process -Id $_.ID -Force -Verbose
        }
    }
}