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

40 powershell

确定进程是否正在运行的正确方法是什么,例如FireFox,并将其停止?

我做了一些环顾四周,我找到的最好方法是:

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

else{ 
    echo "Running"
    Stop-Process -processname "firefox"
 }
Run Code Online (Sandbox Code Playgroud)

这是理想的做法吗?如果没有,这样做的正确方法是什么?

Joe*_*oey 78

你这样做的方式是你要两次查询这个过程.林恩也首先提出了一个很好的观点.我可能会尝试以下内容:

# 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
Run Code Online (Sandbox Code Playgroud)

  • 查尔斯 - 这正是你所需要的.注意Joey使用[CloseMainWindow()](https://msdn.microsoft.com/en-us/library/system.diagnostics.process.closemainwindow%28v=vs.110%29.aspx)方法.阅读该MSDN页面上的文档.他的脚本试图让应用程序很好地退出...然后尝试杀死.很好,乔伊:+1. (2认同)
  • @campbell.rw:当你调用`Stop-Process`(它对已退出的进程对象没有任何作用,但在不存在的进程上抛出错误)时,只查询进程一次就会避免竞争,因为该进程不再存在名称).至于好看,Firefox可能会花费很长时间才能关闭,尽管它已经变得更好了.他们应该使用对他们有意义的超时; 这只是一个例子. (2认同)

Ada*_*ski 9

如果您不需要显示"running"/"not runnuning"的确切结果,您可以简单地:

ps notepad -ErrorAction SilentlyContinue | kill -PassThru
Run Code Online (Sandbox Code Playgroud)

如果该过程没有运行,您将得不到任何结果.如果它正在运行,您将收到get-process输出,并且该过程将停止.

  • 对于像我这样的新手,完整的`Get-Process notepad -ErrorAction SilentlyContinue | 停止过程-PassThru` (12认同)

小智 5

@jmp242 - 泛型System.Object类型不包含该方法,但在收集变量时CloseMainWindow静态转换类型对我有用。使用此转换(并将循环更改为 use )更新的代码(来自此答案)如下。System.Diagnostics.ProcessProcessListForEach-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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)