我有一个空数组,它存储了我的所有Windows服务,这些服务以某些字符串开头,例如OPS-AmazonServer,我提供的代码中没有包含我解析服务的地方,只是说它就是这样。应用名称。
然后我有一个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 :(得分: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
如果您想要解析,您可以随时将其传递给Where
子句,或使用-IncludeEqual
和-ExcludeDifferent
参数的组合:
$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"}