When you use the Select-Object cmdlet, how come PowerShell doesn't tell you that you asked for a property that doesn't exist?
Let's explain the scenario that caused two different people to ask this question while attending our instructor-led lab at TechReady. In our lab, one of the tasks involved assigning a line URI to a user, a task that required a command similar to this one:
Set-CsUser "Ken Myer" –LineUri "TEL:+14255551298"
After setting the line URI, the next task was to use the Get-CsUser cmdlet to return the display name and line URI for the user, and verify that the line URI had been assigned correctly. That task required a command like this:
Get-CsUser "Ken Myer" | Select-Object DisplayName, LineUri
That's where we ran into problems. In two different cases, people accidentally typed LineUri as LineUrl:
Get-CsUser "Ken Myer" | Select-Object DisplayName, LineUrl
As a result, when they ran the command they got back this:
Naturally, they first thought that the line URI hadn't been assigned. After a little debugging, we figured out what the problem was: just a simple typo in the property name. As soon as that was fixed and we requested the correct property name (LineUri) we got back the expected results:
Ken Myer TEL:+14255551298
But that led to a very obvious question: why didn't Windows PowerShell tell them that they were requesting a property – LineUrl – that doesn't actually exist?
Well, to be honest, we can't answer that question with 100 percent certainty; consequently, we'll just shrug our shoulders and say, "It is what it is." Instead of worrying about why we thought we might better use our time by reviewing a few quick ways to verify that a property really is a valid property for a given cmdlet. (Note that this isn’t a behavior exclusive to Lync Server PowerShell, this is part of Windows PowerShell. So whether you’re working in Windows PowerShell, Lync Server Management Shell, Exchange Server Management Shell, etc., this is how Select-Object works.)
One way to verify that a property is valid is to simply grab the object in question, pipe that object to the Select-Object cmdlet, then let Select-Object show you all the properties of that object:
Get-CsUser "Ken Myer" | Select-Object *
That approach works just fine; the only problem with it is that you're going to have to read through that big, long list of properties and try to determine for yourself whether or not LineUrl is a valid property. And who wants to do all that work yourself when you have a computer to do it for you, right?
So here's another option:
(Get-CsUser "Ken Myer" | Get-Member | Select-Object –ExpandProperty Name) –contains "LineUrl"
Good question: what the heck are we doing here? Well, to begin with, we're using Get-CsUser to retrieve a user object, then piping that object to the Get-Member cmdlet, a cmdlet that can retrieve information about the properties and methods of any object passed to it. We then hand that data over to the Select-Object cmdlet and ask it to use its ExpandProperty parameter to "expand" the Name property. In this case, that's simply going to give us a list that contains the name of each and every property of the user object we started with. (In other words, all the properties of Ken Myer's user account.) We then use the –contains operator to ask PowerShell if this list of property names includes the property LineUrl. Here's what we get back:
And what if we ask for a valid property, like LineUri:
(Get-CsUser "Ken Myer" | Get-Member | Select-Object –ExpandProperty Name) –contains "LineUri"
Well, in that case, we get back this:
Simple and to the point. Something you rarely see here on the Lync Server PowerShell blog, eh?