2012-01-12 35 views
19

請Noob幫忙。我試圖編寫一個腳本來檢查一個進程是否正在運行,如果沒有,請啓動它。如果這個過程正在運行,它應該什麼也不做。到目前爲止,我已經提出了以下內容,但它正在啓動流程的新實例,無論它是否已經運行。任何幫助表示讚賞。Powershell - 如果一個進程沒有運行,啓動它

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

回答

24

首先,這是你的代碼有什麼問題。 在你的代碼,您評估程序是否已經運行之前創建的過程

$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} 
+0

好的謝謝你的明確解釋。 – Charlotte 2012-01-13 13:00:09

+0

我不明白你的解決方案將如何解決問題。 '$ Start = ...'這一行仍然會每次啓動該進程。我測試了代碼並開始了同一過程的多個部分。 (確保使用允許數個instanses自己的程序進行測試) – LosManos 2017-04-04 05:50:00

+0

Hi @LosManos,是否有可能忘記{}(scriptblock)? – 2017-04-04 09:33:55

3
$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語句和一個變量聲明。它可以是一個命令行的還有:

  1. 獲取處理
  2. 與你有興趣
  3. 使用度量對象,以獲取有關列表中的統計數據的路徑選擇那些你有
  4. 繼續管道只有統計的計數值是0
  5. 啓動過程

不要讓在末尾的foreach把你趕走。度量對象將只返回一個項,其中返回1或0。如果結果爲零,則foreach僅用於執行。它不會啓動更多的一個進程。 :)

+1

不需要使用度量/計數。值0被視爲$ false,非零值爲$ true。看看jon-z的答案是否能夠實際實施。 – x0n 2012-01-12 17:14:33

+0

你說得對。感謝小費;我學到了一些新東西。 jon-z的最後一個例子似乎是最好的。 – 2012-01-13 09:22:25

9

Get-Process cmdlet,進程名稱參數必須是沒有文件擴展名可執行文件的名稱。用$Prog = "prog"代替$Prog = "C:\utilities\prog.exe"

在我看來,如果您過濾的過程中出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拋出一個錯誤,如果它不能找到一個過程與指定的名稱。

+0

好的,我沒有想過這樣做,謝謝! – Charlotte 2012-01-13 14:41:02

+0

+1,因爲我在這裏導致我的錯誤是我包括擴展名。 – rbwhitaker 2013-12-24 22:41:56

5

請記住,PowerShell中處理對象,而不僅僅是文字。而在正常的批處理文件,你可以一個變量設置爲一個字符串,然後只是把它作爲一個命令:

set Foo=dir /b 
%Foo% 

...這不PowerShell的工作。因此,的分配已經創建新過程,因爲=運行後的命令以及其結果分配給$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的仍然是一個外殼,使啓動程序是一些作品本身非常好:-)

你甚至可以內嵌的$running變量,但我想評論是爲了澄清你做什麼,然後。

+0

您提到了真實/虛假的規則......一個很好的小貼子可以幫助理解Jeffrey,他們可以在這裏找到(http://blogs.msdn.com/b/powershell/archive/2006/12/24/布爾值 - 和 - operators.aspx)。 – 2012-01-12 14:29:34

+0

我認爲最令人困惑的部分是單元素數組的規則,但如果您考慮諸如'@(...)'之類的行爲並且因此表現得天真預期:-) – Joey 2012-01-12 16:05:43

相關問題