You have to be careful when using PowerShell's [xml]
accelerator and dynamic properties. What looks like a normal XML document object model gets casted around to ArrayList
and other unsavory objects.
Sure enough, when I load your XML into a DOM, and call GetType()
on the Service
element, I get an Object[]
:
> $xml = [xml]'<QCSettings><Services><Service /><Service /></Services></QCSettings>'
> $xml.QCSettings.Services.Service.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
Since you're using PowerShell 3, you can use the using
scope to reference the XML block inside your remote script block:
$services = $xml.QCSettings.Services.Service
Invoke-Command -ScriptBlock {
$using:services | ForEach-Object {
Set-Service $_.ServiceName -StartupType $_.StartupType
}
}
Since this code passes in all the service objects, you're only logging into each computer once, whereas before, you were logging in once per service.
If you can't use the using
scope, I would just live with the ArrayList
and write your script block to accept a list of objects:
$scptModifyService = {
param (
[Object[]]
$service
);
$service | ForEach-Object {
Set-Service -Name $_.ServiceName -StartupType $_.StartupType
}
}
$XML.QCSettings.Services.Service |
ForEach-Object {
Invoke-Command -ScriptBlock $scptModifyService -ComputerName $ComputerName -ArgumentList $_
}