1

I have an empty array that's storing all my windows services that start with certain strings such as OPS-AmazonServer,not included in the code I provided is where I parse the service to just say it's application name.

I then have a CSV file with a list of service names labeled under 'Application Name'. It looks like this

ApplicationName,Instance,Priority
AuthBridge,,1
AmazonServer,,1
AmexEC,,1

What I want to do is compare the service stored in the array to the CSV list but I can't seem to figure out how the logic flows.

$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"
        }
    }
4
  • $services is not defined/assigned in the sample you've provided? Also, if the csv column has a space in it, you need to refer to it as such: $_.'Application Name' Commented Apr 20, 2017 at 20:33
  • You say you're storing your Windows Services. If that is from the Get-Service cmdlet you will need to specify a property of each service, such as $service.name or $service.DisplayName in your comparison, depending on what the contents of that CSV is. Commented Apr 20, 2017 at 20:37
  • @MathiasR.Jessen Edited the OP for better clarification. I apologize, I am new to Stackoverflow Commented Apr 21, 2017 at 14:27
  • Your script makes no sense. You set $services, then set $centinelServices to an empty array. Then do the same thing again, but set $opsServices to an empty array. Then you try to use those empty arrays to add things to $services. Commented Apr 21, 2017 at 16:42

1 Answer 1

2

Ok, easiest way to do this is to use Compare-Object, and a little magic with Select.

I'm going to assume that the ApplicationName column in your CSV is a list of strings that match up with the Name property in your Windows Services list. So let's start by importing that CSV, and changing the property name of ApplicationName to just Name, so that it matches the related property on your Windows Service objects.

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

Then we simply use Compare-Object to see what's in both lists:

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

If you wanted to parse that you can always pipe it to a Where clause, or use combinations of -IncludeEqual and -ExcludeDifferent parameters:

$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 '=>'}

Or using the Switch cmdlet to do it all in one go:

$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 += $_}
}

Edit: Ok, updating from your addition to the OP. Looks like you could be well served by simply using a Where clause rather than getting services over and over.

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

Then you import your CSV, and use Select -Expand again to get the value of the property, rather than looping through it like you were before.

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

Now you just have two arrays of strings, so this actually gets even simpler than comparing objects... You can use the -in operator in a Where statement like this:

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

That basically filters the $services array to look for any strings that are in the $masterList array. This will only work for exact matches though! So if the service is listed as 'OPS-AmazonServer', but in your CSV file it is listed at just 'AmazonServer' it will not work! I use that example specifically because you have that in your example in your question. You specifically call out the service named 'OPS-AmazonServer' and then in your CSV sample you list just 'AmazonServer'.

If the listings in the CSV are partial strings that you want to match against you could use RegEx to do it. This will probably make less sense if you aren't familiar with RegEx, but this would work:

$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"}
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you so much for the help! I tried your solution and I could not get it to work so I added more code to my original post to help clarify what I am trying to do.
I updated my answer to work with what you updated in the question, as well as voice concerns about string matching.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.