How to pass xml element to scriptBlock when using invoke command

Using PowerShell 3.0, I use the Invoke-Command cmdlet to pass xmlElement to the script block. The problem is that I believe that scriptBlock receives this parameter as an arrayList and not as an xmlElement (in fact, I know that the resulting parameter is an ArrayList when I logged out of $service.GetType() ).

Here is my XMLElement:

 <Service> <ServiceName>Spooler</ServiceName> <Startup>Disabled</Startup> </Service> 

Here is my Block script:

 $scptModifyService = { param ( $service ); Set-Service -Name $service.ServiceName -StartupType $service.Startup; } 

Here is my code calling scriptBlock:

 ## Modify remote Services: foreach($service in $XML.QCSettings.Services.Service) { Invoke-Command -ScriptBlock $scptModifyService -ComputerName $ComputerName -ArgumentList $service; } 

From what I understand about the Invoke-Command (get-help invoke-command) cmdlet, the ArguementList can accept an object as input, so I don’t think this is a problem with what I call the script block in the foreach loop " above. Hope this makes sense.

Does anyone have any ideas on how to capture a parameter in my script block as xmlElement, and not as an ArrayList ?

I have already tried several things (in my script block):

 param( $service = [xml]Get-Content args[0] ); 

And other code options.

+4
source share
2 answers

From what you showed, I don't see how the script block gets an ArrayList, but you can still do the job. Does ArrayList have valid XmlElements? If so, you can make your function more reliable by simply processing one or more service records, for example:

 $scptModifyService = { param ( [Xml.XmlElement[]]$service ); foreach ($s in $service) { Set-Service -Name $s.ServiceName -StartupType $s.Startup; } } 

Then you can call it like this:

 Invoke-Command -ScriptBlock $scptModifyService -ComputerName $ComputerName -ArgumentList $XML.QCSettings.Services.Service 
0
source

You must be careful when using the PowerShell accelerator [xml] and dynamic properties. What looks like a regular XML document object model is added to an ArrayList and other insincere objects.

Of course, when I load your XML into the DOM and call GetType() on the Service element, I get 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 are using PowerShell 3, you can use the using scope to refer to an XML block in a remote script block:

 $services = $xml.QCSettings.Services.Service Invoke-Command -ScriptBlock { $using:services | ForEach-Object { Set-Service $_.ServiceName -StartupType $_.StartupType } } 

Since this code is transmitted in all objects of the service, you register only on each computer once, whereas earlier you registered once for the service.

If you cannot use the using scope, I will just live with an 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 $_ } 
0
source

Source: https://habr.com/ru/post/1489915/


All Articles