2017-07-25 35 views
3

這裏是下面的代碼,我使用:檢查PowerShell版本2中的進程和進程狀態,並根據單個進程或多個進程獲取兩個不同的輸出?

$ProcessesToCheckFor = (
    'company_name_uat-Historian' 
    ) 

$FoundProcesses = Get-Process -Name $ProcessesToCheckFor -ErrorAction SilentlyContinue 

foreach ($Item in $ProcessesToCheckFor) 
    { 
    if ($FoundProcesses.Name -contains $Item) 
     { 
     '{0} runn1ng' -f $Item 
     } 
     else 
     { 
     '{0} fai1ed' -f $Item 
     } 
    } 

代碼檢查,看是否company_name_uat-Historian過程是在服務器上運行,並且如果它正在運行,它將輸出runn1ngfai1ed如果沒有。

問題是,它只是在檢查一個進程時就像上面的代碼一樣工作,但在您嘗試檢查進程列表時不起作用。

我需要檢查的進程列表,所以當我鏈中的其餘部分如下:

$ProcessesToCheckFor = (
'company_name_uat-Historian', 
'company_name_uat-KEReviewCollector', 
'company_name_uat-lwm', 
'company_name_uat-MQAck', 
'company_name_uat-MQOutput', 
'company_name_uat-SQAC', 
'company_name_uat-Store', 
'company_name_uat-Store_STS', 
'company_name_uat-StoreLegacy', 
'spotify' 
    ) 

$FoundProcesses = Get-Process -Name $ProcessesToCheckFor -ErrorAction SilentlyContinue 

foreach ($Item in $ProcessesToCheckFor) 
    { 
    if ($FoundProcesses.Name -contains $Item) 
     { 
     '{0} runn1ng' -f $Item 
     } 
     else 
     { 
     '{0} fai1ed' -f $Item 
     } 

他們所有輸出fai1ed

如果我一個一個地去做,每個不同的過程都會返回runn1ng,只是所有的聚在一起就會返回fai1ed

旁註(如果你想知道):

  • runn1ngfai1ed是 '碼字' 是那些獲得通過使用JavaScript的圖像所取代。我正在製作一個HTML儀表板,用於監視我的Windows服務器的工作情況,因此請考慮綠色複選標記和紅色x標記以及不要的標記。
  • 使用PowerShell版本2根本不是我的選擇,我負責監控的一些服務器是Windows 2008 R2。我相信他們將在今年某個時候進行更新,但項目交付成果要求我立即制定監測解決方案。還有一些服務器是2012年我喜歡編寫PowerShell腳本的服務器。
  • spotify被列爲流程,因爲我知道這是一個合法的過程,但未安裝在我們的服務器上。當我編寫腳本時,我最初在我自己的個人計算機上進行了測試,如果我打開它,則使用spotify作爲測試runn1ng的手段,如果我關閉它,則使用fai1ed。如果我的所有進程都是runn1ng,並且spotify是fai1ed,那麼這就表明PS代碼正在工作。

它出現在PowerShell的版本2

任何想法是什麼原因造成,以及如何我可以重寫它發生?

回答

5

答案

if (($FoundProcesses | Select-Object -ExpandProperty Name) -contains $Item) { 

爲什麼

的PowerShell 3中添加一種叫做成員枚舉。如果在2.0中有一個對象數組,則不能直接調用數組的屬性,因爲它會在數組對象本身上查找這些屬性。在3.0+中,如果該成員不在數組中,它也會檢查成員的項目。使用Select-Object -ExpandProperty是調用成員的更明確方式。

您也可以將Get-Process呼叫轉移到foreach循環中。

foreach ($Item in $ProcessesToCheckFor) 
    { 
    if (Get-Process -Name $Item -ErrorAction SilentlyContinue) 
     { 
     '{0} runn1ng' -f $Item 
     } 
     else 
     { 
     '{0} fai1ed' -f $Item 
     } 
    } 
2

Patrick Meinecke's answer是有效的,有益的,但讓我嘗試了更詳細的解釋和更有效的解決方案:第一

第一件事:你的代碼在PSv3 +蠻好的,應提供的激勵離開PSV2落後於

PSv3介紹unified handling of scalars and collections through member enumeration,它彌合了困擾PSv2-的巨大標量/數組鴻溝。

具體來說,在PSv3你不用擔心Get-Process -Name $ProcessesToCheckFor是否恰好返回多個項目:在這兩種情況下,你可以在輸出打電話.Count計數的項目數返回,你可以調用結果中的成員(屬性),在數組結果(多項)的情況下,意味着該成員在每個元素(例如,.Name)上被調用,並且結果可以再次用作標量或根據需要排列

PSv2-,但是,你需要知道的是否爲cmdlet - situationally - 恰好返回單個項目或多個的,這意味着:

  • 使用數組子表達式運算符@(...)以確保即使所包含的命令恰好返回單個項目(標量),結果是陣列

  • 爲了收集給定陣列的或在一個新的數組或標量標量中的元素的屬性值,使用... | Select-Object -ExpandProperty - 再次,應用@(...)以確保結果是一個陣列

  • 注意PSv2-有一些統一標/數組處理,但只有相對於管道處理:發送一個標量(單項)的管道,你可以使用它原樣,無需包裝@(...)
    'foo' | ...工作得很好 - 不需要@('foo') | ...(即使它也可以)。

應用到你的代碼中,我們得到:

$ProcessesToCheckFor = (
'company_name_uat-Historian', 
'company_name_uat-KEReviewCollector', 
'company_name_uat-lwm', 
'company_name_uat-MQAck', 
'company_name_uat-MQOutput', 
'company_name_uat-SQAC', 
'company_name_uat-Store', 
'company_name_uat-Store_STS', 
'company_name_uat-StoreLegacy', 
'spotify' 
) 

# Collect the names of all running processes and 
# make sure the result is an array (`@(...)`). 
$FoundProcesses = @(Get-Process -Name $ProcessesToCheckFor -ErrorAction SilentlyContinue | 
    Select-Object -ExpandProperty Name) 

foreach ($Item in $ProcessesToCheckFor) { 
    if ($FoundProcesses -contains $Item) { 
    '{0} runn1ng' -f $Item 
    } else { 
    '{0} fai1ed' -f $Item 
    } 
}