PowerShell FAIL Worked Around (+Awesome Remoting Trick)

Last week, I posted about a problem I was having with Invoke-Command. In short, I was trying to pipe in an object that had a ComputerName property, expecting it to bind to Invoke-Command's -computerName parameter, thus invoking a command on multiple remote computers. It doesn't work. That's because Invoke-Command's -inputObject parameter binds all pipeline input objects first (it binds objects of type [object] ByValue), so no other parameters even get a shot. That's a bug of sorts in Invoke-Command; given how -inputObject is constructed, my understanding is that nothing should claim to bind pipeline input ByPropertyName (I've actually logged it on Microsoft Connect, which is a site you should become familiar with if you encounter what you think is a bug in an MS product). But here's the workaround:

Don Jones

April 29, 2010

2 Min Read
ITPro Today logo in a gray background | ITPro Today

Last week, Iposted about a problem I was having with Invoke-Command. In short, I was trying to pipe in an object that had a ComputerName property, expecting it to bind to Invoke-Command's -computerName parameter, thus invoking a command on multiple remote computers. It doesn't work. That's because Invoke-Command's -inputObject parameter binds all pipeline input objects first (it binds objects of type [object] ByValue), so no other parameters even get a shot. That's a bug of sorts in Invoke-Command; given how -inputObject is constructed, my understanding is that nothing should claim to bind pipeline input ByPropertyName (I've actually logged it on Microsoft Connect, which is a site you should become familiar with if you encounter what you think is a bug in an MS product). But here's the workaround:
Invoke-Command –computername (Get-ADComputer -filter * -searchbase 'ou=domain controllers,dc=company,dc=pri'|select –expand Name) -script { Get-Service }
See the parentheses around that sub-command after -computername? Everything in those parentheses will be fed as input to the -computername parameter. So what's going on in there?
It's a sort of "nested pipeline." It's querying all Domain Controllers from the domain, and then selecting just their Name property as the final result. The secret magic sauce is in the -expand (that is, -ExpandProperty) parameter, which the documentation tells us will expand an array of values into individual values - which is what we want. In other words, rather than outputting a PSObject with a Name property, we'll get actual string values of the computer names. It's a bit of a complicated trick, and something I should probably dive into more later. But, the short explanation is that "if you need to take a single property of an object and make the values of that property your output, then use -expand property_name." 
So anyway, there you have it: A way to query computers from the domain (using the Win2008R2 ActiveDirectory module, which is compatible with Win2008 and Win2003 domains) and invoke a command on all of them, using PowerShell remoting. 
(Thanks to Lee Holmes via Jeffrey Snover for this trick)

Sign up for the ITPro Today newsletter
Stay on top of the IT universe with commentary, news analysis, how-to's, and tips delivered to your inbox daily.

You May Also Like