For the most part, the various Remove cmdlets found in the Microsoft Lync Server 2010 implementation of Windows PowerShell are simple and straightforward. For example, suppose you want to remove a voice policy that has the Identity site:Redmond. That’s fine; all you have to do is call Remove-CsVoicePolicy followed by the Identity of the policy to be removed:

 

Remove-CsVoicePolicy –Identity site:Redmond

 

Like we said, simple and straightforward.

 

Except, of course, for one exception. (And you’re right, it seems like there’s always an exception, doesn’t it?) Suppose you have a voice policy with the Identity global. (And trust us, you do have a voice policy with the Identity global.) Furthermore, suppose you have modified that policy in some way; for example, suppose you used the following command to disable team calling:

 

Set-CsVoicePolicy –Identity global –EnableTeamCall $False

 

Finally, suppose you now run this command:

 

Remove-CsVoicePolicy –Identity global

 

Whew.

 

Now, what do you think will happen after you type in this command and then press ENTER? Well, if you’re thinking, “This sounds like a trick question,” you’re absolutely right: this is a trick question. As it turns out, you can’t remove the global policy; Microsoft Lync Server won’t let you do that.

 

Note. OK, so at a very technical level you might be able to argue that Microsoft Lync Server does allow you to remove a global policy or a global configuration (e.g., the Address Book server configuration), sort of. From a practical standpoint, however, you cannot remove a global policy or global configuration. And we’re nothing if not practical.

 

So does that mean you get an error message if you try to remove the global voice policy? Well, maybe not an error message, but definitely a warning message. Like this:

 

WARNING: Global configuration for “VoicePolicy” cannot be removed. Instead of removing it, the Global configuration for “VoicePolicy” has been reset to the default value.

 

When we run the preceding command to remove the modified global policy and then run Get-CsVoicePolicy, this is what we’ll get back:

 

Identity                   : Global

PstnUsages                 : {}

Description                :

AllowSimulRing             : True

AllowCallForwarding        : True

AllowPSTNReRouting         : True

Name                       : DefaultPolicy

EnableDelegation           : True

EnableTeamCall             : True

EnableCallTransfer         : True

EnableCallPark             : False

EnableMaliciousCallTracing : False

EnableBWPolicyOverride     : False

PreventPSTNTollBypass      : False

 

Notice anything interesting here? That’s right: EnableTeamCall is now set to True. Why? Because that’s the default value for EnableTeamCall. If you delete a global policy or collection of settings that has been modified in some way, that policy won’t be deleted; in this case, the global voice policy still exists. However, all the settings within that policy will be reset to their default values. As far as global items are concerned, a cmdlet like Remove-CsVoicePolicy actually functions more like Reset-CsVoicePolicy.

 

Note. So is there a way to reset other items (e.g., policies set at the site or per-user scope) to the default values? Sort of. Take a look at this article for more information.

 

If you remove a global policy that has not been modified, you’ll still receive the warning message, but no changes will take place because the policy already contains the default values.

 

What Happens When I Remove a Policy?

 

To begin with, we should point out that removing policies is very easy; for example, if you want to remove a per-user voice policy with the Identity RedmondPolicy all you have to do is run the following command:

 

Remove-CsVoicePolicy –Identity RedmondPolicy

 

That was easy enough. But the question remains: what exactly happens when you remove a policy?

 

Well, to begin with, the policy itself is deleted; if you run the command Get-CsVoicePolicy you will no longer see RedmondPolicy in the collection of returned policies. In other words, Remove-CsVoicePolicy removes the specified voice policy. That makes sense.

 

However, there’s one thing that removing a policy doesn’t do: it doesn’t remove the policy from the user account for any user (say, Pilar Ackerman) who was assigned that policy. For example, suppose we remove RedmondPolicy (with an Anchor value of 1; we’ll explain that in a moment) and then check Pilar Ackerman’s user account. Here’s what we’ll see:

 

DisplayName           : Pilar Ackerman

ClientPolicy          :

ClientVersionPolicy   :

ImArchivingPolicy     :

ImFilterPolicy        :

LocationPolicy        :

LocationProfilePolicy :

MeetingPolicy         :

PresencePolicy        :

VoicePolicy           : 1

 

Interesting: rather than a policy name, we now see a number. We also see this message:

 

WARNING: “VoicePolicy” with identity “1” assigned to “sip:packerman@litwareinc.com” has been removed from configuration store.

 

Every time we display Pilar’s account, we’ll be reminded that the voice policy she’s been assigned no longer exists. Is that going to cause problems?

 

Fortunately, the fact that the policy isn’t actually removed from the user account isn’t a problem. Ideally Pilar’s user account would be updated to show that she is now using the site or global policy. (When you delete a policy, the next policy in the hierarchy automatically takes over.) But, that doesn’t happen. Fortunately, however, having an invalid per-user policy won’t cause any problems.

 

When Pilar logs on to Microsoft Lync Server the system will check to see which voice policy she has been assigned. If the system cannot find the specified policy it will simply use the next policy in the hierarchy. Voice policies can be assigned at the global, site, or per-user scope. If Pilar doesn’t have a per-user policy assigned to her, or if the assigned policy can’t be found, then the system will look for a site policy. If there is no site policy for the site Pilar’s account is homed on then the global policy will be used.

 

Which brings up a related issue: When you remove a policy you remove the actual policy itself; in other words, that policy no longer exists. That’s a very different operation from taking that policy away from a specific user. For example, suppose you want to keep RedmondPolicy; you just don’t want to apply that policy to Pilar Ackerman.

 

In that case, don’t call Remove-CsVoicePolicy; that will delete the policy, meaning it will no longer apply to anyone. Instead, you need to assign Pilar a new policy. For example, this command assigns Pilar a policy named RedmondPolicy:

 

Grant-CsVoicePolicy –Identity "Pilar Ackerman" –PolicyName RedmondPolicy

 

And this command assigns her the global or site policy:

 

Grant-CsVoicePolicy –Identity "Pilar Ackerman" –PolicyName $null

 

Note that, when assigning the global or site policy, you specify a null policy name.

 

Anchors? What are Anchors?

 

You might have noticed that the VoicePolicy refers to the policy with identity 1. Well, needless to say, no voice policy has that Identity. (Unless, of course, you actually named your policy “1”, which you can do, but it’s not something we’d encourage.) Instead, Active Directory stores the value of the policy Anchor property. Each time you create a new policy its Anchor property is assigned an incremental number: the first voice policy you create is assigned the number 1, the second voice policy you create is assigned the number 2, and so on.

 

Note. These numbers are “immutable;” that is, they won’t change. Suppose you have policies 1, 2, and 3, and you delete all 3 policies. When you create your next policy, that policy will be assigned Anchor number 4.

 

Interestingly enough, when you use Get-CsVoicePolicy to retrieve information about a voice policy you won’t see a value for Anchor. By default Get-CsVoicePolicy suppresses the display of this property value. If you want to see the value of the Anchor property for a policy you will need to call Get-CsVoicePolicy and then pipe the resulting information to Select-Object, like so:

 

Get-CsVoicePolicy | Select-Object *

 

Note. In case you’re wondering, the asterisk (*) tells Select-Object to return all the properties of an object, even those that are typically suppressed.

 

When you do that you’ll be able to see the value of the Anchor property:

 

PstnUsages                 :  {}

Description                :

AllowSimulRing             :  True

AllowCallForwarding        :  True

AllowPSTNReRouting         :  True

Name                       : DefaultPolicy

EnableDelegation           :  True

EnableTeamCall             :  True

EnableCallTransfer         :  True

EnableCallPark             :  False

EnableMaliciousCallTracing : False

EnableBWPolicyOverride     :  False

PreventPSTNTollBypass      :  False

ScopeClass                 :  Tag

Anchor                     :  (2) UserVoicePolicy

Identity                   :  Tag:UserVoicePolicy