Noob请帮忙。我正在尝试编写一个脚本来检查进程是否正在运行,如果没有,请启动它。如果进程正在运行,它应该什么都不做。到目前为止,我已经提出了以下内容,但它正在启动一个新的流程实例,无论它是否已经运行。任何帮助表示赞赏。
$Prog = "C:\utilities\prog.exe"
$Running = Get-Process prog -ErrorAction SilentlyContinue
$Start = ([wmiclass]"win32_process").Create($Prog)
if($Running -eq $null)
{$Start}
else
{}
答案 0 :(得分:28)
首先,这是你的代码中出了什么问题。 在您的代码中,在评估您的程序是否已在运行之前创建该过程
$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}
可以通过将代码块包装在{}(脚本块)中来创建应在代码中进一步评估的代码块:
$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
但是,如果您正在寻找一个简短的单行程来解决您的问题:
if (! (ps | ? {$_.path -eq $prog})) {& $prog}
答案 1 :(得分:10)
在Get-Process cmdlet中,进程名称参数必须是不带文件扩展名的可执行文件的名称。尝试用$Prog = "C:\utilities\prog.exe"
替换$Prog = "prog"
。
在我看来,如果您将流程过滤掉using the Where-Object cmdlet,那么您的脚本会更具可读性。这是一个例子:
$programName = "prog"
$isRunning = (Get-Process | Where-Object { $_.Name -eq $programName }).Count -gt 0
if ($isRunning)
# ...
else
# ...
这样你可以摆脱-ErrorAction SilentlyContinue
参数,这可能会让那些不知道Get-Process 抛出错误这一事实的人感到困惑找不到具有指定名称的进程。
答案 2 :(得分:5)
请记住,PowerShell处理对象而不仅仅是文本。在普通批处理文件中,您可以将变量设置为字符串,然后将其用作命令:
set Foo=dir /b
%Foo%
...这在PowerShell中不起作用。因此,$Start
的分配已经创建了新的流程,因为在运行=
并将其结果分配给$Start
之后的命令。
此外,你不必要地使事情复杂化。我建议如下:
$Running = Get-Process prog -ErrorAction SilentlyContinue
if (!$Running) { Start-Process C:\utilities\prog.exe }
由于Get-Process
返回一个对象(评估为$true
)或$null
(评估为$false
),您可以简化检查,如上所示。这称为类型强制,因为if
语句需要布尔值,并且在上述情况下,将被视为$true
和$false
的规则非常一致。它看起来更好。
我还使用Start-Process
cmdlet而不是WMI来创建新进程。你甚至可以使用以下内容:
if (!$Running) { C:\utilities\prog.exe }
如果应用程序不是控制台应用程序(因此会阻止PowerShell脚本直到它退出)。 PowerShell仍然是一个shell,因此启动程序本身就能很好地工作: - )
你甚至可以内联$running
变量,但我想一个评论是为了澄清你的所作所为。
答案 3 :(得分:4)
$path = "C:\utilities\prog.exe"
$list = get-process | where-object {$_.Path -eq $path }
if ($list -eq $null) { start-process -filepath $path }
或
$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 }
这将为您保存if语句和一个变量声明。它也可以是一行命令:
不要让foreach最终让你失望。 measure对象将只返回一个将返回1或0的项。 foreach仅用于在结果为零时执行。它不会启动多个进程。 :)