More Square (and Not-so-Square) PowerShell 2.0 Holes

As you look at the help file for your favorite cmdlets, you’ll notice (if you use –full) that many of the parameters of those cmdlets provide support for pipeline input. Most of them, though, don’t accept pipeline input “ByValue” — they accept it “ByPropertyName”. This means that when an object is passed to this cmdlet on the pipeline, a “ByPropertyName” parameter of the cmdlet watches that incoming object to see if the object has a property with the exact same name as that parameter. If there’s an exact match, the value of that object’s property is applied to that parameter. Hoo, boy. Example time.

Imagine I wrote a PowerShell function that produces objects of my own design. My objects are of type PSObject (which is to say, they are generic). My objects represent students in my classroom, and they have the following properties: Name, StudentID, and EyeColor. If I invoke that function (let’s call it Get-Student), it will generate a list of student objects and put them on the pipeline. Left unattended, those will travel down the pipeline, find nothing else to do, and get written out to the screen. But what if I pipe those objects somewhere? What if I said, for example, Get-Student | Restart-Service? Sounds ridiculous, and, yeah — you’re right about that. Just go with me for a minute…

What happens when those student objects hit Restart-Service? The –InputObject parameter looks up to see if what’s coming is a System.ServiceProcess.ServiceController. It’s not, and that parameter goes back to sleep. Then the –Name parameter wakes up, and looks to see if the incoming object has a Name property. It does, and so this parameter binds to the value in the name property. Restart-Service will try to restart a service that has the same name as one of my students. It’s not likely to work (unless I’ve got a student whose name is Browser or FontCache), but nonetheless, the pipeline is assuming that I know what I’m doing.

What does this mean? It means I can write code that produces objects that have properties that match the names of parameters of cmdlets that I want to work with. I can then pass those objects to cmdlets that expect objects with that matching set of properties. So maybe this isn’t an example of a square peg in a square hole, but of an octagonal peg in an octagonal hole.

In this article

Join the Conversation