2017-04-20 197 views
1

我有一個空數組,用於存儲以某些字符串(例如OPS-AmazonServer)開頭的所有Windows服務,未包含在我提供的代碼中的地方是我解析服務以表示它是應用程序名稱。將CSV與數組進行比較

然後我有一個CSV文件,其中包含「應用程序名稱」下標記的服務名稱列表。它看起來像這樣

應用程序名稱,例如,優先
AuthBridge ,, 1
AmazonServer ,, 1
AmexEC ,, 1

我想要做的就是將存儲在陣列中的服務CSV列表,但我似乎無法弄清楚邏輯如何流動。

$services = get-service Centinel* -ComputerName $serverName | select -expand name 
$centinelServices = @() 

$services = get-service OPS* -ComputerName $serverName | select -expand name 
$opsServices = @() 

$services = @() 
foreach($service in $centinelServices) { 
    $services += $service 
} 

foreach($service in $opsServices) { 
    $services += $service 
} 


$csvLocation = "\\logserver\Cardinal\OPS\QA\Task\conf\Centinel\app-restart.csv" 
$masterList = import-csv $csvLocation 
$applications = @() 
$masterList | ForEach-Object {$applications += $_.ApplicationName} 

forEach($service in $services){ 
    forEach($application in $applications){ 
     if($service -eq $application){ 
      "$service match found" 
     } 
     else { 
      "$service match not found" 
     } 
    } 
+0

您提供的示例中未定義/分配'$ services'嗎?另外,如果csv列中有一個空格,則需要引用它:'$ _。'Application Name'' –

+0

您說你正在存儲Windows服務。如果是來自'Get-Service' cmdlet,則需要在比較中指定每個服務的屬性,例如$ service.name或$ service.DisplayName,具體取決於該CSV的內容是什麼。 – TheMadTechnician

+0

@ MathiasR.Jessen編輯OP以獲得更好的說明。我很抱歉,我是新來的Stackoverflow –

回答

2

好,最容易做到這一點的方法是使用Compare-Object,並與Select一個小魔術。

我打算假設CSV中的ApplicationName列是與您的Windows服務列表中的Name屬性匹配的字符串列表。因此,讓我們從導入該CSV開始,並將ApplicationName的屬性名稱更改爲Name,以便它與Windows服務對象上的相關屬性匹配。

$masterList = Import-Csv $csvLocation | Select @{l='Name';e={$_.ApplicationName}} 

然後我們只需使用Compare-Object,看看有什麼在兩個列表:

Compare-Object (Get-Service) -DifferenceObject $masterList -Property Name -IncludeEqual 

如果你想解析的-IncludeEqual-ExcludeDifferent參數,你可以它總是管到Where條款,或使用組合:

$masterList = Import-Csv $csvLocation | Select @{l='Name';e={$_.ApplicationName}} 
$myServices = Get-Service 
$foundServices = Compare-Object $myServices -DifferenceObject $masterList -Property Name -IncludeEqual -ExcludeDifferent 
$servicesNotInMaster = Compare-Object $myServices -DifferenceObject $masterList -Property Name | Where {$_.SideIndicator -eq '<='} 
$servicesNotFoundLocally = Compare-Object $myServices -DifferenceObject $masterList -Property Name | Where {$_.SideIndicator -eq '=>'} 

或者使用Switch cmdlet來做到這一切一氣呵成:

$masterList = Import-Csv $csvLocation | Select @{l='Name';e={$_.ApplicationName}} 
$myServices = Get-Service 
Switch(Compare-Object $myServices -dif $masterList -prop Name -includeequal -PassThru){ 
    {$_.SideIndicator -eq '<='} {[array]$servicesNotInMaster += $_} 
    {$_.SideIndicator -eq '=>'} {[array]$servicesNotFoundLocally += $_} 
    {$_.SideIndicator -eq '=='} {[array]$foundServices += $_} 
} 

編輯:好的,從您的添加更新到OP。看起來你可以簡單地使用Where子句而不是一遍又一遍地獲得服務。

$services = Get-Service -ComputerName $serverName | Where{$_.Name -like 'ops*' -or $_.Name -like 'Centinel*'} | Select -Expand Name 

然後您導入CSV,並再次使用Select -Expand來獲得屬性的值,而不是通過其循環像你之前。

$masterList = Import-Csv $csvLocation | Select -Expand ApplicationName 

現在你只需要串的兩列,所以實際上變得比比較對象更簡單...您可以使用-in運營商在Where聲明是這樣的:

$services | Where{$_ -in $masterList} | ForEach{"$_ match found"} 

,基本上篩選$services陣列以查找$masterList陣列中的任何字符串。這將只適用於完全匹配,但!因此,如果該服務被列爲「OPS-AmazonServer」,但是在您的CSV文件中列出的只是'AmazonServer',它將無法使用!我特別使用這個例子,因爲你在你的問題中有你的例子。您專門調用名爲「OPS-AmazonServer」的服務,然後在您的CSV示例中列出「AmazonServer」。

如果CSV中的列表是您想要匹配的部分字符串,您可以使用RegEx來執行此操作。如果您對RegEx不熟悉,這可能意義不大,但這會起作用:

$services = Get-Service -ComputerName $serverName | Where{$_.Name -like 'ops*' -or $_.Name -like 'Centinel*'} | Select -Expand Name 
$masterList = (Import-Csv $csvLocation | ForEach{[regex]::escape($_.ApplicationName)}) -join '|' 
$services | Where{ $_ -match $masterList } | ForEach{"$_ match found"} 
+0

非常感謝您的幫助!我嘗試了您的解決方案,但無法實現,因此我在原始文章中添加了更多代碼,以幫助澄清我正在嘗試執行的操作。 –

+0

我更新了我的答案,以處理您在問題中更新的內容以及有關字符串匹配的聲音問題。 – TheMadTechnician