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:
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)