Help with Comparing XML Objects

Need help with with comparing XML Objects, I am trying to write a script which starts automatic services only which were running before reboot of a server.

$Bfr_Rbt = Import-Clixml -Path “C:\BR_Stp.xml”
Get-WmiObject -Class win32_service | where {$.startmode -eq ‘Auto’ -and $.state -ne ‘Running’ } | Export-Clixml -Path “C:\AR_Stp.xml”
$Aft_Rbt = Import-Clixml -Path “C:\AR_Stp.xml”
$Serv = Compare-Object $Bfr_Rbt $Aft_Rbt

The $serv will now PSCustomObject values. And I cannot pass this to Start-Service. Am I going wrong, Please assist.

When you run Compare-Object, use the -Property parameter to specify only the relevant properties. It will still output a PSCustomObject, but it will be structured in a way that can be passed to Start-Service.

$serv = Compare-Object $a $b -Property name,state

If you look at the syntax:

Start-Service [[b]-InputObject] [-Exclude ] [-Include ] [-PassThru ]

Start-Service [-Exclude ] [-Include ] [-PassThru ] -DisplayName  []

Start-Service [[b]-Name] [/b] [-Exclude ] [-Include ] [-PassThru ] []
Get-Service wuauserv | Start-Service
Start-Service -DisplayName"Windows Update"
Start-Service -Name  wuauserv

Notice that most params accept a string array as well, so you could find all required services and put them in an array to do something like:

$arrServices = @("WSearch"," wuauserv","wudfssvc")
Start-Service -Name $arrServices

If you review the help, it also indicates that -Name accepts pipeline input:

    Specifies the service names for the service to be started.

    Required?                    true
    Position?                    1
    Default value                
    Accept pipeline input?       true (ByPropertyName, ByValue)
    Accept wildcard characters?  false

As long as the object you are passing contains a “Name” property, it can be piped (e.g. $myObject | Start-Service). So, there are many ways to actually pass the information, but you don’t show how you are trying to do it. This is a basic example without the XML conversion:

$before = Get-WmiObject -Class Win32_Service -Filter "StartMode = 'Auto' And State  'Running'"

$after = Get-WmiObject -Class Win32_Service -Filter "StartMode = 'Auto' And State  'Running'"

Compare-Object $before $after -PassThru | Where{$_.SideIndicator -eq "<="} | foreach{
    "Starting {0}" -f $_.Name
    Start-Service -Name $_.Name

Hi Jason and Rob, It worked. Now i am able to compare the files and also pass on the output to start-service. I was not performing the where part before.
Thank you for the help.

Get-WmiObject -Class win32_service | where {$_.startmode -eq 'Auto' -and $_.state -ne 'Running' } | Export-Clixml -Path "C:\Before.xml"
$Before =  Import-Clixml -Path "C:\Before.xml"
Get-WmiObject -Class win32_service | where {$_.startmode -eq 'Auto' -and $_.state -ne 'Running' } | Export-Clixml -Path "C:\After.xml"
$after =  Import-Clixml -Path "C:\After.xml"
$tostart = Compare-Object $Before $After -PassThru | where { $_.SideIndicator -eq "=>" }
$tostart | Start-Service

Some services especially those where the name starts with “CLR_” will be set to auto but don’t need to stay running unless something calls them. In fact if you start them in the GUI you get a pop-up saying just that. The CMDLETs are really meant for working within PowerShell and don’t do a good job of working with true XML formats as well. Using the XML class is the way to go in my opinion.

For learning XML I found that Dr. Tobias Weltner’s PowerShell monthly issue #11 was a great resource!


This helped me learn XML but it was not easy.