Home > front end >  CSV comparison of Windows Services
CSV comparison of Windows Services

Time:11-11

I'm fairly new to Powershell and I'm stuck with this portion of a much larger script. I need to pull all Windows Services and compare them to see if their Startup Type of Status has changed. If there were any changes, I need to count them so I can put that value in the body of an e-mail. Also, I need to attach an HTML report showing the previous and current state of the Windows services that changed.

What I've done is the following:

That piece of code generates a CSV file showing the current state of the services.

Get-Service | Select-Object -Property Name,DisplayName,StartType,ServiceType,Status | Export-Csv -Path "C:\logs\after.csv"

Then i declare two variables, one for the current state, another one for the "template", the desired state of all Windows Services.

$before = Import-Csv -Path "C:\logs\before.csv"
$after = Import-Csv -Path "C:\logs\after.csv"

Then, i compare both of them, parsing only those service that've changed and generate a CSS styled HTML report based on that

Compare-Object $before $after -Property Name,DisplayName,StartType,ServiceType,Status | ConvertTo-html -Head $css | Set-Content "C:\logs\comparison.html"

This is what i get:

enter image description here

This is what it should look like:

enter image description here

Basically, i want to show the status of the latter CSV report in a new column after the Status column of the original CSV report. And I would also like to make a row count after that, so I can send an e-mail reporting HOW MANY services suffered any changes.

Any help will be deeply appreciated.

CodePudding user response:

You could use Group-Object after Compare-Object and parse out the columns you need from that.

$before = Import-Csv -Path "C:\logs\before.csv"
$after  = Import-Csv -Path "C:\logs\after.csv"

# find the differences in the StartType and Status columns. Use -PassThru to be able to process further
$groups = Compare-Object -DifferenceObject $before -ReferenceObject $after -Property StartType, Status -PassThru | 
          Sort-Object Name | Group-Object Name

$result = foreach ($group in $groups) {
    $refGroup = $after | Where-Object { $_.Name -eq $group.Name }
    # output an object with new StartType_* and  Status_* columns and capture that in variable $result
    $group.Group[0] | 
    Select-Object *, @{Name = 'StartType_Before'; Expression = {$_.StartType}},
                     @{Name = 'StartType_After'; Expression = {$refGroup.StartType}},
                     @{Name = 'Status_Before'; Expression = {$_.Status}},
                     @{Name = 'Status_After'; Expression = {$refGroup.Status}} -ExcludeProperty StartType,Status, SideIndicator
}

# now convert the $result to HTML and add a summary line with the number of services that have changed
$result | ConvertTo-Html -Head $css -PostContent "<br />Services affected: $($result.Count)" | 
          Set-Content "C:\logs\comparison.html"

If you also want output in the console do:

$result | Format-Table -AutoSize

Of course it is also possible to not use Compare-Object and do like below (will be slower, but easier to understand I guess):

$before = Import-Csv -Path "C:\logs\before.csv"
$after  = Import-Csv -Path "C:\logs\after.csv"

$result = foreach ($item in $before) {
    $diff = $after | Where-Object { $_.Name -eq $item.Name -and 
                                   ($_.StartType -ne $item.StartType -or $_.Status -ne $item.Status) }
    if ($diff) {
        $item | Select-Object *, @{Name = 'StartType_Before'; Expression = {$item.StartType}},
                                 @{Name = 'StartType_After'; Expression = {$diff.StartType}},
                                 @{Name = 'Status_Before'; Expression = {$item.Status}},
                                 @{Name = 'Status_After'; Expression = {$diff.Status}} -ExcludeProperty StartType,Status
    }
}

# output to console
$result | Format-Table -AutoSize

# convert to HTML
$result | ConvertTo-Html -Head $css -PostContent "<br />Services affected: $($result.Count)" | 
          Set-Content "C:\logs\comparison.html"

Output on screen will look something like

Name            DisplayName                                             ServiceType     StartType_Before StartType_After Status_Before Status_After
----            -----------                                             -----------     ---------------- --------------- ------------- ------------
AarSvc_8246b1   Agent Activation Runtime_8246b1                         224             Manual           Automatic       Stopped       Stopped     
AdobeARMservice Adobe Acrobat Update Service                            Win32OwnProcess Automatic        Automatic       Running       Stopped     
ALG             Application Layer Gateway Service                       Win32OwnProcess Manual           Automatic       Stopped       Stopped     
WdNisSvc        Microsoft Defender Antivirus Network Inspection Service Win32OwnProcess Manual           Manual          Running       Stopped  
  • Related