2017-04-20 195 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