如何正确检查进程是否正在运行并停止它

问题描述 投票:0回答:6

确定进程(例如 FireFox)是否正在运行并停止它的正确方法是什么?

我环顾四周,发现最好的方法是这样的:

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

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

这是理想的做法吗?如果不是,正确的做法是什么?

powershell
6个回答
161
投票

您执行此操作的方式会查询该流程两次。林恩还提出了一个很好的观点,那就是首先要友善。我可能会尝试如下所示:

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

22
投票

如果您不需要显示确切的结果“正在运行”/“未运行”,您可以简单地:

ps notepad -ErrorAction SilentlyContinue | kill -PassThru

如果该进程未运行,您将不会得到任何结果。如果它正在运行,您将收到

get-process
输出,并且该进程将停止。


5
投票

@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
        }
    }
}

3
投票

谢谢@Joey。这就是我正在寻找的。

我只是带来了一些改进:

  • 考虑多个流程
  • 避免在所有进程终止时达到超时
  • 将整体封装在一个函数中

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        
    }
}

2
投票

首先从进程终止开始,这里

python
,我的 2 美分:

Get-Process python3.9|Stop-Process

0
投票

就 powershell 语法而言,接受的答案有点过时。当前版本:

# get Firefox process
$firefox = Get-Process firefox -ErrorAction SilentlyContinue
if ($firefox) {
  # try gracefully first
  $firefox.CloseMainWindow()
  # kill after five seconds
  Start-Sleep -Seconds 5
  if (!$firefox.HasExited) {
    $firefox | Stop-Process -Force
  }
}
Remove-Variable firefox
© www.soinside.com 2019 - 2024. All rights reserved.