Some time ago one of the authors had to go through the always-enjoyable experience of getting cable television hooked up to her new house. This involved disconnecting the cable from her old residence and then setting up a connection at the new house. Before the cable company could do any of this the service representative had to ask for the author’s name, address, phone number and the last four digits of her Social Security number. (The author was asked for this again when her call was transferred, was asked for it again when she got disconnected and had to call back, was asked for it again when…well, you get the idea.) Why did the cable company need all this information? They needed it because they had to ensure that they were disconnecting cable from the correct residence (very important); that they were re-connecting to the correct residence; and that the person they were talking to actually had the authority to make these changes. (In other words, that this person is the one who was going to pay the bill.) They got these assurances by requesting the identifying information we just listed.
Managing Microsoft Lync Server with Windows PowerShell is kind of like being the cable company representative – you need to make sure you’re working with the correct “residences;” in the case of Lync Server, that means the correct user, the correct voice route, the correct application, and so on. After all, if you change something at the wrong location then you could have quite a problem on your hands – just like the cable company would have if they got the location wrong.
The kind of identifying information you need in order to manage Microsoft Lync Server with Windows PowerShell depends on the feature you’re trying to manage. This is where we start to diverge from the cable company; the cable company is concerned only with identifying people and addresses. In Lync Server you need to deal with all sorts of entities: devices, voice configurations, conferencing settings, and so on. So how do you go about identifying all these different features from within PowerShell? Well, most of the time you use the Identity.
Note: What you’re about to read is a pretty simple concept, yet it’s still going to sound a little confusing at first. Stick with us: we promise this will be easier than dealing with the cable company.
But, then again, what isn’t?
What is an identity?
Identity is a property of almost every Lync Server object that can be accessed through Windows PowerShell. The Identity property holds a unique identifier, something that can be attributed to only one conferencing policy, one Address Book configuration, one Lync Server-enabled user, etc. Almost every single Lync Server cmdlet includes an Identity parameter. You will use this parameter to act on a particular object. After all, you don’t want to accidently remove the wrong voice normalization route, or to grant the wrong policy to a user. The Identity helps make sure you have exactly the object you need.
So what exactly is a unique identifier? For a person this could be a government-issued identifier (such as a Social Security number) or a name (although, unlike Social Security numbers, names aren’t always unique). But in Lync Server it gets a little more complicated. As we mentioned, the Identity varies with the type of object. In this section we’ll go over some of the more common identities you’ll come across, when to use them, and how to figure out which one to use.
Note. We should probably mention that, under-the-covers, Microsoft Lync Server uses GUIDs to uniquely identify objects. That’s fine, except that GUIDs look like this: 24DD18D4-C902-497F-A64B-28B2FA741661. Needless to say, no one wants to type in a GUID any time he or she wants to look at a meeting policy or retrieve a user account. The Identity property acts as a sort of alias: it provides an alternate way to uniquely refer to an object. An identity like site:Redmond might seem a little clunky at first, but compared to an identity like 24DD18D4-C902-497F-A64B-28B2FA741661, well ….
Identities with scopes
We’ll discuss scopes in more detail in the aptly-named Scopes article, but, briefly, scopes specify the level at which a particular policy or configuration applies. Depending on that policy or configuration, Lync Server uses the following scopes:
• Global, where the policy or settings can potentially impact the entire Lync Server deployment.
• Site , where the policy or settings can, at best, impact only the users, devices, and other objects homed on a specific site.
• Service, where policies can, at most, impact only objects making use of a particular Lync Server service.
• Per-user , where polices can only impact users who have specifically been assigned that policy.
As we said, we’ll discuss scopes more in the Scopes article; for now we just want to point out that an Identity often includes the scope. To be more specific, sometimes an identity includes only the scope, sometimes it includes the scope and a name, and sometimes the Identity includes just the name, with the scope being implied.
Got all that? Good point: maybe we should show you a few examples of what we’re talking about.
Our first example involves a new meeting configuration:
New-CsMeetingConfiguration –Identity site:Redmond
The Identity in this example is the scope (in this case site), followed by the name of the site. This format is enough to provide a unique Identity for a meeting configuration; that’s because there can be only one meeting configuration per site (that is, one meeting configuration for the Redmond site, one meeting configuration for the Dublin site, etc.).
Here’s another example, one that requires the scope plus an associated name (the combination of the scope and the name must be unique):
New-CsVoiceNormalizationRule –Identity site:Redmond/RedmondRule1
Here we again specified the scope (site:Redmond), but we then followed that with a slash (/) and a name. In the case of the object we’re creating here (a voice normalization rule), it’s possible to have more than one rule for a given scope; for example, the Redmond site can have a whole slew of voice normalization rules. (This is an unusual case, but it does happen.) Because of that, we need more than just the scope to identify a voice normalization rule; an identity like site:Redmond could refer to any voice normalization rule assigned to the Redmond site. Therefore, in this case we use the scope plus an additional name in order to uniquely identify the object.
See? That wasn’t so bad, was it?
OK, we’ve seen scope-only identities and we’ve seen scope plus name identities. Now let’s look at an Identity that includes an implied scope:
New-CsCallParkOrbit –Identity "Orbit Number 1"
In the case of Call Park Orbits, the only possible scope is Global; you can’t create a Call Park Orbit for a specific site or assign a Call Park Orbit to a user. Instead, Call Park Orbits must be defined globally within a Lync Server installation. That means that, for Call Park Orbits, we can leave off the scope and simply give the object a name, in this case Orbit Number 1.
One final example, just to get your head spinning a bit more before we slow things down:
New-CsVoicePolicy –Identity UserVoicePolicy
This command creates a new voice policy that can be assigned to a user. This will be explained in the Scopes section, but trust us: after running this command you can now grant the voice policy UserVoicePolicy to a user.
Discovering Identity Types
The obvious questions we’re sure are running through your head are “Why are there so many different ways of identifying things?” and “How in the world do I know what Identity I’m supposed to use?” If you recall, we already answered that first question: with so many different types of Lync Server objects that need to be managed it’s not possible to have a single type of Identity. (Well, not unless you want to go back using GUIDs.)
As for the second question: how in the world do you know which Identity to use? Well, one simple way is to take a look at the help. Try typing this command from the PowerShell prompt:
Get-Help New-CsVoiceNormalizationRule –detailed
The preceding command returns help on how to use the New-CsVoiceNormalizationRule cmdlet, including a description of the Identity parameter. (Don’t forget the –Detailed parameter: if you don’t include that parameter, or the -Full parameter, you won’t see the parameter descriptions.) Scroll up to the Parameters section of the help and you’ll see something like this:
A unique identifier for the rule. The Identity specified must include the scope followed by a slash and then the name.
For example: site:Redmond/Rule1, where site:Redmond is the
scope and Rule1 is the name.
Note. Yes, the help will be wrapped around like that. (Don’t ask us; it’s a PowerShell thing.) In a more perfect world, that paragraph would actually look like this:
A unique identifier for the rule. The Identity specified must include the scope followed by a slash and then the name. For example: site:Redmond/Rule1, where site:Redmond is the scope and Rule1 is the name.
For better or worse, however, this isn’t a more perfect world.
In case you haven’t noticed.
You can scroll to the bottom of the help and look at the Examples (or type Get-Help Get-CsVoiceNormalizationRule –Examples to see only examples). There you’ll see examples of how to specify an Identity for the given cmdlet.
See? Sometimes help really is your friend.
Your other option is to check the data type in the syntax statement for the cmdlet in question. Try this command:
Get-Command New-CsVoicePolicy –Syntax
That command returns a statement that looks like this:
New-CsVoicePolicy [-Identity] <XdsIdentity> [-PstnUsages <PSListModifier>] [-AllowSimulRing] [-AllowCallForwarding] [-AllowPSTNReRouting] [-Name <String>] [-EnableDelegation] [-EnableTeamCall] [-EnableCallTransfer] [-EnableCallPark] [-EnableMaliciousCallTracing] [-EnableBWPolicyOverride] [-PreventPSTNTollBypass] [-InMemory] [-Tenant <Nullable`1>] [-LocalStore] [-Verbose] [-Debug] [-ErrorAction <ActionPreference>] [-WarningAction <ActionPreference>] [-ErrorVariable <String>] [-WarningVariable <String>] [-OutVariable <String>] [-OutBuffer <Int32>] [-WhatIf] [-Confirm]
Notice the very first parameter following the cmdlet name: [-Identity] <XdsIdentity>. The type XdsIdentity (a data type specific to Lync Server) tells you that the Identity must include a scope (or a name for a user scope).
Yes, we know: this all seems a little complicated, to say the least. In reality, though, all we’ve done is to make sure that the unique identifier for objects is called Identity. No matter what cmdlet you’re using (for the most part – as you know, there are exceptions to every rule) you can expect to see an Identity parameter. The type of information that goes into the Identity is based on what the cmdlet does. Once you start using it you’ll see that it’s not as complicated as it seems, and that the consistency of knowing which parameter is the identifier can be pretty comforting.
Speaking of comforting, let’s go over a few other identities you’ll run into at some point. One of the times you’ll probably find PowerShell most useful for managing Lync Server is when you’re working with user accounts. Officially, the Identity for a user account is the user’s distinguished name (DN):
PS C:\> Get-CsUser
SamAccountName : User1
UserPrincipalName : User1@litwareinc.com
DistinguishedName : CN=User1,OU=Finance,DC=litwareinc,DC=com
Identity : CN=User1,OU=Finance,DC=litwareinc,DC=com
Before you start worrying about having to know (and type in) user DNs, read the article Retrieving Active Directory and Microsoft Lync Server User Accounts. In that article we explain how to retrieve specific users and groups of users without having to type in a distinguished name. We didn’t show you this to scare you, we just wanted you to see another example of an Identity.
Had enough yet? No? (We’re pretty sure we heard at least one “no” out there.) Okay, here’s one more:
Get-CsExUmContact –Identity sip:firstname.lastname@example.org
This cmdlet retrieves a particular Microsoft Exchange Unified Messaging contact. In this case the Identity happens to be the SIP address of the contact.
All right, we’re done. You may run across one or two other types of identities. But now you’ll never forget that, whatever the unique identifier is for an object, you’ll need to use the Identity parameter to access it.
What if I don’t specify an Identity? What happens then?
Ah, good question. And the answer is: it depends. In particular, it depends on the type of cmdlet (or, more correctly, the cmdlet verb) that you are using. Suppose you are using a Get cmdlet (for example, Get-CsVoicePolicy) and you leave off the Identity:
In that case, PowerShell will assume you want to retrieve all the voice policies, and that’s exactly what you’ll get: all the voice policies. Now, suppose you are using a Set cmdlet and you don’t include an Identity there:
Set-CsVoicePolicy –AllowSimulRing $False
In this case, Windows PowerShell will assume you want to modify the global policy. Actually, it won’t just assume that: it will go ahead and modify the global policy. In this example, that means setting the value of the AllowSimulRing property to False.
And what if you use a Grant, a New, or a Remove cmdlet, all without including an Identity; you know, like this:
Well, in each of these instances PowerShell will prompt you for an Identity. For example, if you issue the New command shown above PowerShell will display the following information:
cmdlet New-CsVoicePolicy at command pipeline position 1
Supply values for the following parameters:
You will then have to enter a valid voice policy identity before you can create the new voice policy.
Be honest now: if nothing else, that was easier than trying to get your cable hooked up, wasn’t it?
Well, assuming you’ve actually been able to get your cable hooked up. Some of us are still waiting on that.