When is a Boolean Not a Boolean?

If you've ever read Alice in Wonderland, you might recall the famous riddle posed by the Mad Hatter: "Why is a raven like a writing desk?" And that -- hmmm, that is an interesting question, isn't it? Why is a raven like a writing desk?

Of course, one reason why the riddle has become so famous is that in the book, the Mad Hatter never bothers to answer the riddle. Many years later Carroll himself explained why the Mad Hatter never bothered the answer the riddle: there was no answer to the riddle. According to Carroll "Enquiries have been so often addressed to me, as to whether any answer to the Hatter's Riddle can be imagined, that I may as well put on record here what seems to me to be a fairly appropriate answer, viz: 'Because it can produce a few notes, tho they are very flat; and it is never put with the wrong end in front!' This, however, is merely an afterthought; the Riddle, as originally invented, had no answer at all."

Well, here at the Lync Server PowerShell blog we like to consider ourselves the Lewis Carroll of the Microsoft Lync Server 2010 world. (Or at least the Windows PowerShell part of that world.) And that means that if Lewis Carroll can pose a riddle, well, by golly, we can pose a riddle, too. And here goes: When is a Boolean value not a Boolean value?

OK, maybe that's not quite as catchy as "Why is a raven like a writing desk?" On top of that, it's nowhere near as mysterious and challenging. After all, our riddle seems to have a pretty straightforward answer: there is no answer, because a Boolean value is always a Boolean value. In fact, if you do a quick search for the word Boolean you'll invariably find definitions similar to this:

"In computer science, the Boolean or logical data type is the most primitive data type, having one of two values (true or false), intended to represent the truth values of logic and Boolean algebra."

There you have it: a Boolean value is a data type that has two possible values: a Boolean value is either True or a Boolean value is False. As the immortal Ken Kesey used to say, you're either on the bus or you're off the bus.

Note. We should probably point out that Ken Kesey isn't truly immortal; he died back in the year 2001. Before he died, however, Kesey did write the novel One Flew Over the Cuckoo's Nest. The protagonist of that novel was a red-headed Irishman named Randle Patrick McMurphy. When the novel was made into an Academy Award-winning movie, McMurphy was played by, uh, Jack Nicholson.

Incidentally, as good as One Flew Over the Cuckoo's Nest was, the novel Sometimes a Great Notion was even better. Don't listen to what anyone else has to say, take it from us: Sometimes a Great Notion is better. Hey, if you can't trust the Lewis Carroll of the Microsoft Lync Server 2010 world who can you trust?

In other words, Boolean values are pretty straightforward: they're either True or they're False. So then when is a Boolean value not a Boolean value? Here's the answer to the riddle: When that Boolean value represents the Enabled attribute that gets added to Active Directory when you install Microsoft Lync Server.

Note. Or when it can produce a few notes, tho they are very flat; and it is never put with the wrong end in front! We'll accept either answer.

Let's see if we can explain what we mean when we say that the Boolean attribute Enabled is not a Boolean attribute. Up till now, we've been under the impression that the Enabled attribute, like all good Boolean attributes, can be either True or False: we've been assuming that the value is True if a user has been enabled for Lync Server and False if a user has not been enabled for Lync Server. And, the fact is, for most of the things you do with Lync Server PowerShell, you can act as though that really is the case. However, there's an exception to that general rule, an exception you should know about it.

As it turns out, the Enabled attribute actually has three possible values:

· If the user has been enabled for Microsoft Lync Server 2010 then his or her Enabled attribute is equal to True (or, in Windows PowerShell-speak, $True).

· If the user has had their Lync Server account temporarily disabled, then his or her Enabled attribute is equal to False ($False). What do we mean by "temporarily disabled?" Well, let's suppose we've enabled Ken Myer for Lync Server; that means his Enabled attribute is equal to True. We now run this command to temporarily disabled Ken's Lync Server account:

Set-CsUser -Identity "Ken Myer" -Enabled $False

At that point, Ken's Enabled attribute will be set to False. To restore his account, and set the Enabled attribute back to True, we need to run this command:

Set-CsUser -Identity "Ken Myer" -Enabled $True

· If the user is not enabled for Lync Server then his Enabled attribute is set to a null value ($Null). That's an important distinction. A null value means "no value at all." A False value is an actual value; it's just False rather than True. But because it is a real value, it's not a null value. And there's a difference.

That should clear everything up, eh?

Let's take a look at three users and then show you why this distinction is important:

User

Account Status

Enabled Attribute

Ken Myer

Enabled for Lync Server

$True

Pilar Ackerman

Lync Server account temporarily disabled

$False

April Reagan

Not enabled for Lync Server

$Null

Suppose we run the following command, which returns the value of the DisplayName and the Enabled attributes for all our Active Directory users:

Get-CsAdUser | Select-Object DisplayName, Enabled

In return we get back data that looks like this:

DisplayName Enabled

----------- -------

Ken Myer True

Pilar Ackerman False

April Reagan

OK, so far so good; all our users are there. Now we want to get back data just for users who have been enabled for Lync Server. That means we're going to run this command:

Get-CsAdUser –Filter {Enabled –eq $True} | Select-Object DisplayName, Enabled

In other words, this time we only want to get back information for users who have an Enabled attribute equal to $True: {Enabled –eq $True}. And if we run that command we should get back this:

DisplayName Enabled

----------- -------

Ken Myer True

The only information we get back this time is information about Ken Myer. Which is exactly what we should have gotten back. After all, Ken is the only user we have who's been enabled for Lync Server.

Now here's the part that could cause some confusion. Suppose we now want information about the users who have not been enabled for Lync Server. We know that the Enabled attribute is a Boolean value, and that Boolean values can either be True or False. Just a few seconds ago, to find all the users who have been enabled for Lync Server we used this command:

Get-CsAdUser –Filter {Enabled –eq $True} | Select-Object DisplayName, Enabled

Logically enough, we might then expect that the following command, which looks for user accounts where the Enabled attribute is equal to $False, will return all the users who have not been enabled for Lync Server:

Get-CsAdUser –Filter {Enabled –eq $False} | Select-Object DisplayName, Enabled

But guess what? It doesn't do that. Instead, this is what we get back:

DisplayName Enabled

----------- -------

Pilar Ackerman False

In this case, we get back just what we asked for: all the users where the Enabled attribute is False. What we didn't get back, however, is what we really wanted to get back: all the users who are not enabled for Lync Server. In our case, that would be April Reagan, the only user we have who hasn't been enabled for Lync Server. (Remember, Pilar Ackerman is enabled for Lync Server, but we've temporarily shut down her account.) We don't get back April Reagan because her Enabled attribute isn’t set to $False; instead, it's not set to anything at all (that is, it's equal to a null value). The returned data is a little deceiving, because we looked for users with an Enabled attribute equal to $False and we got back a collection of users who all have an Enabled attribute equal to $False. But we never should have looked for those users in the first place.

Instead, if you want to return all the Active Directory users who are not enabled for Lync Server, you need to use this command, which searches for accounts where the Enabled attribute is null:

Get-CsAdUser –Filter {Enabled –eq $Null} | Select-Object DisplayName, Enabled

That command returns April Reagan, and anyone else who hasn't been enabled for Lync Server:

DisplayName Enabled

----------- -------

April Reagan

See how that works and, equally important, why that works? If you've never been enabled for Lync Server, then your Enabled attribute is equal to a null value. That's also true if you were at one point enabled for Lync Server, but then had your account disabled by using the Disable-CsUser cmdlet:

Disable-CsUser "Pilar Ackerman"

When you use Disable-CsUser to disable an account, all the user account attributes related to Lync Server are wiped clean, including the Enabled attribute. That means our user accounts now look like this:

User

Account Status

Enabled Attribute

Ken Myer

Enabled for Lync Server

$True

Pilar Ackerman

No longer enabled for Lync Server

$Null

April Reagan

Not enabled for Lync Server

$Null

So then what happens if we run this command against the preceding set of user accounts:

Get-CsAdUser –Filter {Enabled –eq $Null} | Select-Object DisplayName, Enabled

You got it. This time we get back our two users who are not enabled for Lync Server:

DisplayName Enabled

----------- -------

Pilar Ackerman

April Reagan

The moral of the story? This:

 

· If you are enabled for Lync Server then the Enabled attribute is equal to $True.

· If your Lync Server account is temporarily disabled then the Enabled attribute is equal to $False.

· If your account is not enabled for Lync Server at all, then the Enabled attribute is equal to $Null.

Note. In case you're wondering, no, you can't actually set the Enabled attribute to null. This command will fail and give you the error message "Cannot bind argument to parameter 'Enabled' because it is null.":

Set-CsUser -Identity "Ken Myer" –Enabled $Null

So with Set-CsUser the Enabled property is a true Boolean: it can only be True or False. But with Get-CsAdUser, the Enabled property can be True or False or it can be null.

And people thought Wonderland was a crazy place.

Of course, in some cases you might be interested in returning information for users who can't currently log on to Lync Server; that includes users who are not enabled for Lync Server (Enabled attribute equals $Null) and users who have had their accounts temporarily disabled (Enabled attribute equals $False). How can you find both sets of users? That's easy; just look for users who do not have an Enabled attribute equal to $True:

Get-CsAdUser –Filter {Enabled –ne $True} | Select-Object DisplayName, Enabled

Finally, and just to complicate matters a little, we should add one last note. Suppose you have a user who has a SIP address but is not enabled for Lync Server. (Let's assume that April Reagan is a user like that.) Let's run this command:

Get-CsAdUser –Identity "April Reagan" | Select-Object DisplayName, Enabled

That's going to return data that looks like this:

DisplayName Enabled

----------- -------

April Reagan

OK, no problem there. Now let's try returning information about April Reagan by using the Get-CsUser cmdlet:

Get-CsUser –Identity "April Reagan" | Select-Object DisplayName, Enabled

Here's what we get back when we run that command:

DisplayName Enabled

----------- -------

April Reagan False

Oops. In this case, Get-CsUser tells us that April's Enabled attribute is equal to False. Unfortunately, that's not really true; her Enabled attribute actually is equal to a null value. These results lead us to believe that April's account is just temporarily disabled, and that's not really the case.

Which simply means that Get-CsUser can sometimes return misleading data. Therefore, the other moral of the story is to use Get-CsAdUser if you really want to know the status of all your users.

That's all we have for now; we're just going to sit back and wait for someone to make a movie version of this article. We can hardly wait.