Powershell - 如果进程未运行,请启动它

Cha*_*tte 22 powershell

Noob请帮忙.我正在尝试编写一个脚本来检查进程是否正在运行,如果没有,请启动它.如果进程正在运行,它应该什么都不做.到目前为止,我已经提出了以下内容,但它正在启动一个新的流程实例,无论它是否已经运行.任何帮助表示赞赏.

$Prog = "C:\utilities\prog.exe"
$Running = Get-Process prog -ErrorAction SilentlyContinue
$Start = ([wmiclass]"win32_process").Create($Prog)
if($Running -eq $null)
{$Start}
else
{}
Run Code Online (Sandbox Code Playgroud)

jon*_*n Z 29

首先,这是代码中的错误.在您的代码中,在评估您的程序是否已在运行之前创建该过程

$Prog = "C:\utilities\prog.exe"
$Running = Get-Process prog -ErrorAction SilentlyContinue
$Start = ([wmiclass]"win32_process").Create($Prog) # the process is created on this line
if($Running -eq $null) # evaluating if the program is running
{$Start}
Run Code Online (Sandbox Code Playgroud)

可以通过将其包装在{}(脚本块)中来创建应在代码中进一步评估的代码块:

$Prog = "C:\utilities\prog.exe"
$Running = Get-Process prog -ErrorAction SilentlyContinue
$Start = {([wmiclass]"win32_process").Create($Prog)} 
if($Running -eq $null) # evaluating if the program is running
{& $Start} # the process is created on this line
Run Code Online (Sandbox Code Playgroud)

但是,如果您正在寻找一个简短的单行程来解决您的问题:

if (! (ps | ? {$_.path -eq $prog})) {& $prog}
Run Code Online (Sandbox Code Playgroud)


Enr*_*lio 10

Get-Process cmdlet中,进程名称参数必须是没有文件扩展名的可执行文件的名称.尝试替代$Prog = "C:\utilities\prog.exe"使用$Prog = "prog".

在我看来,如果您使用Where-Object cmdlet过滤掉进程,那么您的脚本将更具可读性.这是一个例子:

$programName = "prog"
$isRunning = (Get-Process | Where-Object { $_.Name -eq $programName }).Count -gt 0

if ($isRunning)
 # ...
else
 # ...
Run Code Online (Sandbox Code Playgroud)

这样你就可以摆脱这个-ErrorAction SilentlyContinue论点,如果找不到Get-Process 如果找不到具有指定名称的进程就会抛出错误,那么这个参数可能会让人感到困惑.


Jen*_*zlo 6

$path = "C:\utilities\prog.exe"        
$list = get-process | where-object {$_.Path -eq $path }     
if ($list -eq $null) { start-process -filepath $path }
Run Code Online (Sandbox Code Playgroud)

或者

$path = "C:\utilities\prog.exe"
get-process | where-object {$_.Path -eq $path } | measure-object | where-object { $_.Count -eq 0} | foreach-object {start-process -filepath $path }
Run Code Online (Sandbox Code Playgroud)

这将为您节省 if 语句和一个变量声明。它也可以是一行命令:

  1. 获取进程
  2. 选择您感兴趣的路径
  3. 使用度量对象获取有关您拥有的列表的统计信息
  4. 仅当 stats 的计数值为 0 时才继续管道
  5. 启动进程

不要让最后的 foreach 让你失望。度量对象将仅返回一项,而 where 将返回 1 或零。foreach 仅在结果为零时执行。它不会启动多个进程。:)


Joe*_*oey 5

请记住,PowerShell处理对象而不仅仅是文本.在普通批处理文件中,您可以将变量设置为字符串,然后将其用作命令:

set Foo=dir /b
%Foo%
Run Code Online (Sandbox Code Playgroud)

...这在PowerShell中不起作用.因此,您的分配$Start已经创建了新进程,因为=运行后的命令及其结果已分配给$Start.

此外,你不必要地使事情复杂化.我建议以下内容:

$Running = Get-Process prog -ErrorAction SilentlyContinue
if (!$Running) { Start-Process C:\utilities\prog.exe }
Run Code Online (Sandbox Code Playgroud)

由于Get-Process返回一个对象(计算结果为$true)或$null(计算结果为$false),您可以简化检查,如上所示.这称为类型强制,因为该if语句需要一个布尔值以及在上述情况下将被视为$true$false非常一致的规则.它看起来更好.

我还使用Start-Processcmdlet而不是WMI来创建新进程.你甚至可以使用以下内容:

if (!$Running) { C:\utilities\prog.exe }
Run Code Online (Sandbox Code Playgroud)

如果应用程序不是控制台应用程序(因此会阻止PowerShell脚本直到它退出).PowerShell仍然是一个shell,因此启动程序本身就能很好地工作:-)

你甚至可以内联$running变量,但我想一个评论是为了澄清你做了什么,然后.