In this article, I will show you how to compare the configuration of Windows services with the help of the Compare-Object cmdlet. You will also learn how to format the output for Excel and in HTML.

Displaying differences between services on the console ^

First, we have to collect all services available on the computer. You can use three methods for this purpose:

  • Get-WMIObject: available for all PowerShell versions
  • Get-CimInstance: available since PowerShell 3
  • Get-Service: available for PowerShell versions

Because you can’t read the service start mode with Get-Service, we will use Get-CimInstance for the examples in this post.

$Services_1 = Get-CimInstance win32_service | select name, caption, state, startmode

Now let’s change some service values to see what PowerShell can do to highlight differences.

We will stop the services below to compare the state property:

Adobe Acrobat Update service before change

Adobe Acrobat Update service before change

Adobe Acrobat Update service after change

Adobe Acrobat Update service after change

Print Spooler before change

Print Spooler before change

Print Spooler after change

Print Spooler after change

The command below collects the new state of the services:

$Services_2 = Get-CimInstance win32_service | select name, Caption, state, startmode

Now we can use Compare-Object to compare the contents of the two variables. The first variable is called the reference set and the second variable is the difference set. The IncludeEqual parameter ensures that values that appear in both sets will be displayed.

Compare-Object $Services_1 $Services_2 –includeequal –property name, caption

Comparing two variables in PowerShell

Comparing two variables in PowerShell

The SideIndicator (==) tells us that the name and the caption properties have the same value in both sets.

In the next example, we omit the IncludeEqual parameter and only list services that have different values with regard to the name, caption, and state properties.

Compare-Object –referenceObject $Services_1 –differenceObject $Services_2 –property name, caption, state

Displaying the differences between two variables

Displaying the differences between two variables

The AdobeARMservice and the Spooler service appear twice in the list because PowerShell displays the reference and the difference set with regard to their differences. For instance, the state of AdobeARMservice is set to “Stopped” in the reference set and is set to “Running” in the difference set. The SideIndicator => tells you that the state of AdobeARMservice is set to “Stopped” only in the reference set and the SideIndicator <= implies that the state of AdobeARMservice is set to “Running” only in the difference set.

You can pipe the comparison result to Out-Gridview to display an interactive table:

Compare-Object $Services_1 $Services_2 –property name, caption, state | Out-GridView

Displaying the comparison results in an interactive table

Displaying the comparison results in an interactive table

In the next example, we compare the services with regard to the startmode property. For this purpose, we first have to change the start mode of the Adobe Acrobat Update Service and the Print Spooler service from Automatic to Disabled.

Next, we collect the new values in the variable $Services_3 and then compare the values with $Services_1:

$Services_3 = Get-cimInstance win32_service | select name, Caption, state, startmode
Compare-object $Services_1 $Services_3 –property name, caption, startmode

Comparing the start mode of services

Comparing the start modes of services

We can also only display the values of the properties in the difference set using the Where filter:

Compare-Object $Services_1 $Services_3 –property name, caption, state, startmode | Where {$_.SideIndicator –eq "=>"} | Out-GridView

Displaying property values in the difference set

Displaying property values in the difference set

If you want to store the comparison in an Excel table, you can pipe the output to Export-CSV:

Compare-object $Services_1 $Services_3 –property name, caption, state, startmode | Where {$_.SideIndicator –eq "=>"} | export-csv –encoding UTF8 –notype c:\my_services_export.csv

This method also allows you to compare services between two computers. All you have to do is to first export the comparison results to a CSV and then import the results again to PowerShell variables:

$Services_1 = import-csv < YourPath >
$Services_2 = import-csv < YourPath >

To compare both files, use the same compare command as previously:

Compare-object $Services_1 $Services_2 –property name, state, startmode || Where {$_.SideIndicator –eq "=>"}

For better readability, you can change the column titles in the table. The example below uses the Group-Object and New-Object cmdlets for this purpose:

Compare-Object $Services_1 $Services_3 –property name, caption, state, startmode | Where {$_.SideIndicator –eq "=>"} | 
Group-Object -Property name | % { New-Object psobject -Property @{		
	Service_Name=$_.name
	Service_Caption=$_.group[0].caption
	Service_StartMode=$_.group[0].startmode
	Service_State=$_.group[0].state	
}} | Select Service_Name, Service_Caption , Service_StartMode, Service_State |export-csv -encoding UTF8 -notype -useculture < YourPath >

Using different column titles in the comparison table

Using different column titles in the comparison table

The method below can be used to compare multiple properties. It compares each name from the first CSV file with the second CSV file. If a name appears in both files, it will compare the startmode value for each service.

$Diff_startmode = ForEach ($line1 in $Services_1)   # Looking for all rows in the first CSV file
{
	ForEach ($line2 in $Services_3)   # Looking for all rows in the second CSV file
		{
			IF ($line1.name -eq $line2.name)   # If the same service name is found in both files
				{
					IF ($line1.startmode -ne $line2.startmode)   # If startmode is different
						{		
							New-Object -TypeName PSObject -Property @{
								Name = $line1.name   
								Caption = $line1.caption   
								Startmode_File1 = $line1.startmode
								Startmode_File2 = $line2.startmode 
								}  
						}
				}
		}												
}
$Diff_startmode | select Name, caption, Startmode_File1, Startmode_File2 | export-csv -encoding UTF8 -notype < YourPath>

Comparing multiple properties

Comparing multiple properties

Displaying the comparison results in Excel and HTML ^

The next sample script starts an Excel process and adds a workbook and a worksheet. It then loads the content of the CSV file and applies a TableStyle.

$xl = new-object -comobject excel.application   # Open Excel process
$xl.visible = $false   # Hide the Excel document during the conversion
$Workbook1 = $xl.workbooks.open($Diff_Startmode)   # Open the CSV previously exported 
				
$WorkBook0 = $xl.WorkBooks.add()
$sh1_wborkbook0 = $WorkBook0.sheets.item(1)   # first sheet in destination workbook
$sheetToCopy1 = $Workbook1.sheets.item(1)   # source sheet to copy
$sheetToCopy1.copy($sh1_wborkbook0)   # Copy source sheet to destination workbook
			
$Diffstartmode = $WorkBook0.Worksheets.item(1)
$Diffstartmode.name = 'Services with Diff StartMode'   # Give your sheet a name
$Diffstartmode.columns.autofit()   # Resize columns depending on the content
$Table_Diff = $Diffstartmode.ListObjects.add( 1,$equalboth.UsedRange,0,1)	
$Diffstartmode.ListObjects.Item($Table_ Diff.Name).TableStyle="TableStyleMedium6   # Apply Excel TableStyle6
					
$WorkBook0.SaveAs(<YourPath>,51)   # Save the current CSV to XLSX format
$WorkBook0.Saved = $True
$xl.Quit()

Displaying the comparison result in Excel

Displaying the comparison result in Excel

The next example displays the results in HTML.

$Title = "<p>Same services but different start mode</p>"								
$Diff_startmode = ForEach ($line1 in $Services_1)   
{
	ForEach ($line2 in $Services_3)   
		{
			IF ($line1.name -eq $line2.name)   
				{
					IF ($line1.startmode -ne $line2.startmode)  
						{		
							New-Object -TypeName PSObject -Property @{   
								Name = $line1.name
								Caption = $line1.caption
								Startmode_File1 = $line1.startmode
								Startmode_File2 = $line2.startmode 
								}  	
						}
				}
		}												
}
$html1 = $Diff_startmode | Select Name, Caption, Startmode_File1, Startmode_File2 | convertto-html 
$html_final = convertto-html -body "$Title $html1" | out-file -encoding ASCII <HTML_Path>
invoke-expression <HTML_Path>

Displaying the comparison result in HTML

Displaying the comparison result in HTML

It’s not very pretty, so now let’s give it more style by adding some CSS. In the next example, I have created a CSS file and applied it with the CSSUri parameter.

$Title = "<p class=notequal_list>Same services but different start mode</p>"	
$Diff_startmode = ForEach ($line1 in $Services_1)
{
	ForEach ($line2 in $Services_3)
		{
			IF ($line1.name -eq $line2.name)
				{
					IF ($line1.startmode -ne $line2.startmode)
						{		
							New-Object -TypeName PSObject -Property @{
								Name = $line1.name
								Caption = $line1.caption
								Startmode_File1 = $line1.startmode
								Startmode_File2 = $line2.startmode 
								}  	
						}
				}
		}												
}
$html1 = $Diff_startmode | Select Name, Caption, Startmode_File1, Startmode_File2 | convertto-html -CSSUri $CSS_File
$html_final = convertto-html -body "<div id=left>$Title $html1</div>" -CSSUri $CSS_File | out-file -encoding ASCII <HTML_Path>
invoke-expression <HTML_Path>

Displaying the comparison result in HTML with CSS

Displaying the comparison result in HTML with CSS

0 Comments

Leave a reply

Your email address will not be published.

*

© 4sysops 2006 - 2022

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account