The Field Guide to Microsoft Lync Server 2010 Cmdlets

To hear some people tell it, the world’s fastest-growing pastime is Lync Server cmdlet-watching. All over the world countless numbers of people, binoculars and notebooks in hand, are tramping through the woods and the underbrush, trying to spot the elusive Lync Server cmdlets. If bird-watching is “Your lifetime ticket to the theater of nature” then cmdlet-watching is … well, something that probably isn’t your lifetime ticket to the theater of nature. But it is your lifetime ticket to effectively and efficiently managing Microsoft Lync Server 2010.


Note. What’s that? Well, sure. But, in our defense, we simply said “to hear some people tell it” Lync Server cmdlet-watching is the world’s fastest-growing pastime. We never claimed that these people actually knew what they were talking about.


Which brings up an interesting question: what is the world’s fastest growing pastime? Beats us. However, a quick online search unearthed about a million pastimes that claim to be the world’s fastest growing, including: geocaching; Internet poker; scuba diving; sled dog racing; scrapbooking; standup paddling; genealogy; competitive eating; snowboarding; wakeboarding; rock climbing; and, of course, broomball.


Figure 1. Lync Server cmdlet watchers on the lookout


Of course, by now you’re probably thinking, “Gee whiz, I’d love to get involved in Lync Server cmdlet watching myself, except that I don’t know the first thing about Lync Server cmdlets. In fact, I wouldn’t recognize a Lync Server cmdlet if it came up and bit me on the nose!”


Note. On the off chance that a cmdlet does come up and bite you on the nose please keep in mind that it couldn’t possibly be a Lync Server cmdlet; our cmdlets don’t bite. If you get bitten by a cmdlet we’d be willing to bet you’ll be bitten by an Exchange cmdlet.


Which brings up a good point: how are you supposed to know a Lync Server cmdlet from a Lichtenstein’s Sandgrouse? To be perfectly honest, bird-watching is easy. For example, suppose you see a large fly-eating bird with boldly streaked olive-brown upperparts and pale yellow underparts with dark brown patches. No doubt you’ll say to yourself, “Oh, a sulphur-bellied flycatcher.” You say you just saw a large swift-like bird, gray-brown overall with a white throat and undertail and whose wings were glossed with green, fly by? If that isn’t a white-throated needletail, well, then we don’t know what is.


Note. OK, so maybe we don’t know what a white-throated needletail is. But you get the idea.


Identifying Lync Server cmdlets is a little different, however. For one thing, very few Lync Server cmdlets have streaked olive-brown upperparts and pale yellow underparts with dark brown streaks; for another, even fewer of these cmdlets make a sound consisting of 2 or 3 clicks (like pebbles being tapped together), repeated over and over in a long series.


Note. Well, maybe the Get-CsFileTransferFilterConfiguration cmdlet does. But other than that ….


So does that make cmdlet-watching a difficult pastime? No, not really. As you know, most bird-watchers can’t immediately identify every single bird they see; that’s why birders carry a bird-watching Field Guide everywhere they go. Can the authors of this article immediately recognize every Lync Server cmdlet we see? Of course not, we — well, now that we think about it, maybe we can immediately recognize every Lync Server cmdlet we see; after all, that is our job. However, we’re willing to bet that most people can’t.


And that’s OK: that’s what The Field Guide to Microsoft Lync Server 2010 Cmdlets is for. In this Field Guide we’ll show you how to quickly and easily identify a Lync Server cmdlet; we’ll also show you how you can figure out just exactly what that cmdlet is for and how to make the best use of it.


Because, unlike birds, the world actually has a use for Lync Server cmdlets.


Note. We’re just joking: we actually love all the creatures on this good earth of ours.


Especially those that can be deep-fried in a secret blend of 11 herbs and spices.


Note to vegetarians. Just joking.



A Quick Note About the Field Guide


This Field Guide takes a look at cmdlet “families” (like the New-Cs cmdlets and the Grant-Cs cmdlets) without examining any one cmdlet in detail. If you’d rather see a list of all the current Lync Server cmdlets (we say “current” because the product is still in development) along with a brief description of what that cmdlet does, well, all you had to do was ask.


And no, you’re under no obligation to read the entire Field Guide. If you’d prefer to skip around a little, well, here are the different sections available to you:


·         Quickly Identifying a Lync Server Cmdlet

·         The Get-Cs Cmdlets

·         The Grant-Cs Cmdlets

·         The New-Cs Cmdlets

·         The Remove-Cs Cmdlets

·         The Set-Cs Cmdlets

·         The Test-Cs Cmdlets

·         Get-Cs Cmdlets That Have No Equivalent Set-Cs Cmdlet

·         Set-Cs Cmdlets That Have No Equivalent Get-Cs Cmdlet

·         Cmdlets That Have No New-Cs or Remove-Cs Cmdlets

·         Solitary New-Cs Cmdlets


Good luck, and have fun.


Note. Will you hurt our feelings if you decide to just jump around and not actually read the Field Guide from cover-to-cover? Probably. But hey, you gotta do what you gotta do, right?



Quickly Identifying a Lync Server Cmdlet


As everyone knows, the California Gnatcatcher is all-but indistinguishable from the Blacktailed Gnatcatcher; in fact, the only way to tell the two apart is to get a close look at the bird’s underparts (the California Gnatcatcher is a little grayer) and tail (the Blacktailed Gnatcatcher has more white in the tail). Can you tell the difference between a California Gnatcatcher and a Blacktailed Gnatcatcher? To be perfectly honest, you probably can’t. We’re not even sure if a Blacktailed Gnatcatcher can tell them apart.


That isn’t the case with Lync Server cmdlets, however; as it turns out, Lync Server cmdlets are readily-identifiable (even without binoculars). That’s because all Lync Server cmdlets have more gray in the underparts and less white in the tail.


Also, the names all follow the same exact pattern:


Verb –Cs Noun (which, technically includes the Cs portion of -Cs)


In other words:


Cmdlet Name



Noun (minus the Cs)

















What does that mean? That means that you can identify a Lync Server cmdlet simply by looking for the –Cs in the middle of the cmdlet name:







That does make things easy, doesn’t it?



Figure 2. No –Cs in the name? Then this isn’t a Lync Server cmdlet


Lync Server cmdlets can also be readily-identified because they spring from the same family tree: the Lync module. (A module is a PowerShell construction for grouping together cmdlets, functions, scripts, and other related items.) The fact that Lync Server cmdlets all originate in the same module means two things. First, you can always get a complete list of Lync Server cmdlets simply by running this command:

Get-Command * -Module Lync | more 

And what if you’re not convinced that any given cmdlet really is a Lync Server cmdlet? Then you can verify that by using a command similar to this one:


Get-Command Remove-CsVoiceNormalizationRole | Select-Object Module


If this command doesn’t return the value Lync then you don’t have a genuine Communications Server cmdlet.


But enough of all that. Let’s take a look at the individual species that make up the Lync Server cmdlets.


The Get-Cs Cmdlets


As everyone knows, the Xantus’s Murrelet is known as the Xantus’s Murrelet because … um … because … well, come to think of it, apparently no one knows why the Xantus’s Murrelet is known as the Xantus’s Murrelet. It just is.


Note. As a matter of fact, we did try to look this up. However, we kept running into sentences like this one:


“Like other synthliboramphine murrelets (e.g. the Ancient Murrelet) the chicks are highly precocial, leaving the nest within two days of hatching and running actively towards the sea, where the parents call to them.”


As soon as we encountered the term “synthliboramphine murrelets” we gave up.


Fortunately, we do know why Communications Server’s Get-Cs cmdlets were all given names that start with the verb Get:


1.    The cmdlets are highly precocial.

2.    The cmdlets are all designed to get information for you.


OK, so maybe the cmdlets aren’t highly precocial; we’re not really sure about that. However, they do get information for you. For example, do you need information about how your Address Book servers are configured? Then run this command:




Do you need information about your voice policies? Then run this command:




Do you need information about – well, you get the idea. Unlike synthliboramphine murrelets, the Get-Cs cmdlets are, at heart, information retrievers.


So do we know any other fascinating facts about the Get-Cs cmdlets? Of course we do. For example:


·         Unlike many of their fellow Lync Server cmdlets, you do not have to specify an Identity when calling one of the Get-Cs cmdlets. If you specify an Identity, you’ll get back just one item; for example, this command returns one voice policy, the voice policy that has the identity RedmondVoicePolicy:

Get-CsVoicePolicy –Identity “RedmondVoicePolicy”

And what if you don’t specify an Identity? Then you’ll get back everything. In other words, this command returns information about all your voice policies:


See? No Identity (or any other parameters) means you get back everything.

And yes, we know: that could result in an awful lot of information scrolling by on your computer screen, couldn’t it? That’s why we wrote the article Dealing With Information Overload: Displaying Select Microsoft Lync Server 2010 Property Values.

·         As a general rule (Get-CsAdUser and Get-CsUser are the two primary exceptions that come to mind) the Get-Cs cmdlets don’t let you use wildcards when specifying an Identity. For example, suppose you have multiple voice policies that have Identities beginning with the letter R. You might think this command would return all of those policies:

Get-CsVoicePolicy –Identity “R*”

As it turns out, though, that command won’t return anything, except for an error message that reads “Get-CsVoicePolicy: Cannot find VoicePolicy R* because it does not exist.” Why didn’t that command work? That command didn’t work because the –Identity parameter doesn’t know how to use wildcards. The –Identity parameter doesn’t know that R* is supposed to mean, “Find me all the voice policies that have an Identity that begins with the letter R.” Instead, -Identity takes the parameter value literally, and looks for a policy that has the Identity R*. Not too surprisingly, it can’t find one.

Fortunately, though, there’s a little trick that lets you use wildcards in order to retrieve multiple items using one of the Get-Cs cmdlets: the –Filter parameter. If you want to filter on the Identity (the only property you typically can filter on) then use –Filter instead of –Identity. This command will work:

Get-CsVoicePolicy –Filter “R*”

We promise.



The Grant-Cs Cmdlets


Before we talk about the Grant-Cs cmdlets let’s talk a little about cmdlet habitats. (Actually, we’re going to talk about Lync Server scopes, but the word “habitats” fits better with our bird-watching theme.) In Microsoft Lync Server 2010 there are various “scopes” where policies and configuration settings can be applied. In fact, there are 5 of these scopes. To quote from our article Scopes and Filters:


·         Global. The global scope is for configuration settings or policies you want enforced throughout your entire Microsoft Lync Server infrastructure. For example, when you configure a policy at the global scope that policy will be applied to every user in the organization.

·         Site. The site scope is for, well, sites. In Lync Server 2010, sites are typically based on geographic locations: a Redmond site, a Dublin site, etc.

·         Service. The service scope represents a service role. For example, the Registrar service is one Microsoft Lync Server service role; User Services is another. In the new Lync Server architecture, a given service role might be carried out by a single computer or by all the computers in a pool.

·         Per-User. To be honest, “per-user” isn’t really the name of a scope, it’s more a description of a scope. (We have yet to come up with a good name for this scope.) The basic concept behind the per-user scope is pretty straightforward. The per-user scope (which applies only to policies, and not to configuration settings) is reserved for policies that can be directly applied to a user or a set of users. This makes the per-user (or, more simply, the “user”) scope very different from the global, site, and service scopes, all of which are tied to your Lync Server infrastructure. For example, if you don’t have a site named Redmond then you can’t create a policy at the site:Redmond scope; a site-scoped policy must be tied to an actual site. The Identity of a site-scoped policy or a service-scoped policy is simply the Identity of the site or service – period.


Note. For more information about, and a slightly-better explanation of, Lync Server scopes, see the article Scopes and Filters.


So what does all this have to do with the Grant-Cs cmdlets? Well, the Grant-Cs cmdlets are used to assign per-user policies to users. If you want to apply a policy to a site or service, you don’t have to do any sort of policy assignment. Instead, the mere act of creating the policy and giving it the name of a site or service automatically assigns the policy to that scope. For example, what do you think happens when you run this command:


New-CsClientPolicy –Identity site:Redmond


You got it: a new policy will be created and automatically assigned to the Redmond site.


OK, that was easy; let’s try another one. What do you think happens when you run this command:


New-CsClientPolicy –Identity “RedmondClientPolicy”


Right again: a new per-user client policy will be created, a policy that has the Identity RedmondClientPolicy. But here’s a follow-up question: where will that policy be assigned?


Sorry; that was a trick question. As it turns out, the policy won’t be assigned anywhere. That’s because per-user policies aren’t assigned to anyone or anything by default. The policy RedmondClientPolicy will be created, but unless you explicitly assign that policy to a user or group of users, well, then the policy will just sit there, unassigned, unused and unappreciated.


Which does seem a little sad, doesn’t it? OK, then how do we assign a per-user policy to a user or a group of users? Good answer: you use the appropriate Grant-Cs cmdlet. For example, the following command assigns the per-user client policy RedmondClientPolicy to Ken Myer:


Grant-CsClientPolicy –Identity “Ken Myer” –PolicyName “RedmondClientPolicy”


In other words, if you want to assign a per-user policy to someone then you need to use the appropriate Grant-Cs cmdlet. That’s all there is to it.


Note. Well, OK, it’s possible that there might be a little more to it than that. See the article Assigning Policies for more information.


As an added bonus, the Grant-Cs cmdlets also provide a sneaky way for you to figure out what things can actually be assigned to users. How? Well, if something has a Grant-Cs cmdlet then that thing can be assigned to users. Is there a cmdlet named Grant-CsDialPlan? It turns out that there is; that means that you can assign dial plans to users. Is there a Grant-CsAddressBookConfiguration cmdlet? It turns out that there isn’t. That means that you can’t assign a particular Address Book server to a particular user. Etc., etc.



The New-Cs Cmdlets


As we’ve already seen, bird names tend to describe the birds themselves, and cmdlet names tend to describe the cmdlets themselves. For example, the Blue-crowned Motmot is named the Blue-crowned Motmot simply because the bird sports a crown of black head feathers bordered by a wide band of electric blue.


Note. In case you’re wondering, Blue-crowned Motmots are called Motmots because the motmots are a “family of birds in the near passerine order Coraciiformes.”


So then why are the New-Cs cmdlets named the New-Cs cmdlets? You got it: because these cmdlets sport a crown of black head feathers bordered by a wide band of electric blue.


Never mind; that’s not true. Instead, the New-Cs cmdlets are named the New-Cs cmdlets because they create new things for you. For example, when you install Microsoft Lync Server 2010 you get a global collection of Address Book settings. That’s nice, but suppose the Redmond site needs to have different Address Book settings than your other sites; for example, maybe you only want to keep change files for 15 days on the Redmond site rather than the default duration of 30 days. What can you do about that? One thing you can do is create a new collection of Address Book settings for the Redmond site, a collection that sets the KeepDuration property to 15 days. And to do that you need one of the New-Cs cmdlets:


New-CsAddressBookConfiguration -Identity site:Redmond -KeepDuration 15.0:00:00


Need a new whatever? Then just call the New-Cs whatever cmdlet.


You’re right: it can’t get much easier than that, can it?


Incidentally, the default behavior for most of the New-Cs cmdlets (there are a few exceptions that we’ll talk about later in this Field Guide) is to immediately create the new policy or collection of settings for you. For example, the minute you finish running the New-CsAddressBookConfiguration command we just showed you’ll have a new collection of Address Book server settings for the Redmond site. Is that good? As a matter of fact it is: more often than not that’s exactly what you want to happen. (After all, why run the New-CsAddressBookConfiguration cmdlet if you don’t want a new collection of Address Book configuration settings?)


Interestingly enough, however, there might be times when you don’t want a new collection of Address Book configuration settings, at least not right away. That’s why many of the New-Cs cmdlets include an InMemory parameter; this parameter enables you to create a new object that initially exists in memory only. (In fact, to keep this object from going extinct immediately after you create it you need to store the object in a variable.) For example, this command creates a new collection of Address Book settings that has the Identity site:Redmond. However, this collection isn’t immediately applied to the Redmond site; instead, it’s held in the variable $x:


$x = New-CsAddressBookConfiguration -Identity site:Redmond -KeepDuration 15.0:00:00 -InMemory


Why in the world would you want to do that? For one answer, take a look at the article Looking Up the Default Values For a Policy. Oh: and for more information on the New-Cs cmdlets, take a peek at the article Creating Objects.



The Remove-Cs Cmdlets


In the Seattle area, all you have to do is drop something on the ground and, within seconds, a flock of seagulls will appear and dispose of whatever it was you dropped. You say you just dropped a bag of French fries on the sidewalk? Don’t worry; wait about three seconds and you’ll never know those French fries even existed. We like to think of the Remove-Cs cmdlets as being the seagulls of Microsoft Lync Server.


Uh, scratch that analogy. The product team just reminded us that we don’t like to think of the Remove-Cs cmdlets as being the seagulls of Microsoft Lync Server. Instead, we like to think of the Remove-Cs cmdlets as being the cmdlets that you call if you need to remove a Lync Server object or objects. (Although we’re willing to bet that, if you dropped a Lync Server object on the ground, a seagull would dispose of that, too.)


In other words, anything you create using a New-Cs cmdlet you can (usually) delete using a Remove-Cs cmdlet. Are you already regretting the fact that you created a new voice policy with the Identity RedmondVoicePolicy? Then just use Remove-CsVoicePolicy to undo that policy creation:


Remove-CsVoicePolicy -Identity “RedmondVoicePolicy”


As you might expect, any time you run a Remove-Cs cmdlet against a policy or setting configured at the site, service, or per-user scope that policy or setting will be deleted. (In other words, the entity will be removed from the system, and it won’t be coming back. If you deleted a policy by mistake the only way to “restore” it is to create a new policy with the same identity as the one you just removed.)


However, that’s not what happens if you run a Remove-Cs cmdlet against a global policy or a global group of settings. So what does happen if you run a Remove-Cs cmdlet against a global policy or a global group of settings? To answer that, let’s take a look at the default values for an external access policy:









Now, suppose we’ve changed the global policy so that all these property values are set to True (something we would do using the Set-CsExternalAccessPolicy cmdlet):











Got that? OK, now run the following command:


Remove-CsExternalAccessPolicy –Identity global


Will the global external access policy be deleted? No, it won’t; that’s because Lync Server won’t let you delete a global policy or a collection of global configuration settings. (For more on that, see the article Resetting a Policy.) However, what the Remove-CsExternalAccessPolicy cmdlet will do is reset all the properties in the global policy back to their default values. In other words, we’ll be back to square 1:











Just something to keep in mind.


Here’s another characteristic of the Remove-Cs cmdlets: they strive to be as helpful and responsible as they can. For example, suppose you try to remove the voice policy RedmondVoicePolicy without realizing that this per-user policy is currently assigned to some of your users. Instead of wantonly removing the policy, Remove-CsVoicePolicy will stop and ask you for confirmation:


The policy Tag:RedmondVoicePolicy is currently assigned to one or more users. Assign a different policy to the users before removing this one.

The policy is in use

[Y] Yes   [N] No   [S] Suspend   [?] Help (default is “Y”):


To actually remove the policy RedmondVoicePolicy you’ll need to press Y and then press ENTER. If you never press Y then the policy will never be removed.


That’s a pretty nice little feature … unless, of course, you don’t want to deal with a confirmation request like this one. For example, suppose you’re trying to remove the policy by using a script or a scheduled task. In a situation like that, having everything grind to a halt while Remove-CsVoicePolicy waits for confirmation can be a little … uh … less nice ….


Note. We should also point out that the current error message is a little  misleading: you don’t have to assign a new voice policy to users before removing RedmondVoicePolicy. Suppose RedmondVoicePolicy is assigned to some of your users and you go ahead and remove the policy anyway. Is that going to leave those users in some sort of unmanaged state? In a word: no. If those users are in a site where a site-scoped policy has been assigned then those users will automatically be managed by the site policy. If those users are not in a site where a site-scoped policy has been assigned then they will automatically be managed by the global policy. That might not be optimal (after all, if these users were assigned a per-user policy in the first place that might be because the site policy or the global policy doesn’t quite suit their needs), but the users will always be left in a managed state of some kind.


So is there a way to bypass this confirmation prompt? In most cases, yes, there is. (There are a handful of cmdlets, like Move-CsManagementServer, that make such drastic changes to the system that you can’t bypass the confirmation prompt.) All you have to do is add the –Force parameter, like so:


Remove-CsVoicePolicy -Identity “RedmondVoicePolicy” -Force


Do that, and RedmondVoicePolicy will be removed no matter who it’s been assigned to.


The Set-Cs Cmdlets


Long-time PowerShell users might be surprised to see the huge number of Set-Cs cmdlets. After all, in much of the PowerShell world Set- cmdlets are something of a rarity. For example, when you install Windows PowerShell 2.0 you get, by default, 47 Get- cmdlets and only 19 Set- cmdlets.


Note. Seeing as how you asked, it turns out that there’s much debate about which is the rarest bird in the world, with many people picking Spix’s Macaw as the world’s rarest bird. Another contender for this somewhat-less-than coveted title: the aptly-named Doubtful Leiothrix.


To be honest, it’s not that big a deal that PowerShell ships with fewer Set- cmdlets than Get- cmdlets; after all, with Windows PowerShell you often change property values by using standard dot notation:


$x = Get-ChildItem C:\Scripts\Test.ps1

$x.IsReadOnly = $True


Note. If you aren’t sure what “standard dot notation” is then take a look at the article Setting Property Values.


However, in Lync Server property values typically aren’t changed by using dot notation; instead, these properties are changed by using one of the Set-Cs cmdlets. For example, if you run the Get-CsPinPolicy cmdlet one of the properties you get back is MinPasswordLength; this property specifies the minimum number of digits that must be included in a PIN number. By default, MinPasswordLength is set to 5. What if you want to set the global policy’s MinPasswordLength to 10? Well, let’s start out by saying that this approach won’t work:


$x = Get-CsPinPolicy –Identity global

$x.MinPasswordLength = 10


Instead of using standard dot notation to change the minimum password length property you need to use the Set-CsPinPolicy cmdlet and the –MinPasswordLength parameter. You know, like this:


Set-CsPinPolicy –Identity global –MinPasswordLength 10


Note. OK, if you want to get technical again you can use semi-standard dot notation to change property values, although you still need to use a Set-Cs cmdlet to do so. See Setting Property Values for more details.


See how that works? You want to change the MinPasswordLength property so you use the appropriate Set-Cs cmdlet and the –MinPasswordLength parameter. It’s a little different than what you’re used to but, then again, it’s so easy a waldrapp ibis could do it.


Note. Although there are a number of other contenders, many people consider the waldrapp ibis to be the world’s dumbest bird: for one thing, the waldrapp ibis doesn’t like to fly, which makes life difficult for a bird that does have a strong migratory instinct. In addition, the waldrapp ibis has no sense of direction whatsoever. If you ever see a bird sitting on a crosstown bus, staring in bewilderment at the map printed on the back of a bus schedule, well, that’s probably a waldrapp ibis.


As long as we’re on the subject, we should also state that there’s no truth to the longstanding myth that, when it rains, turkeys will stare up at the sky with their mouths open, at least until they drown.


If only we could say the same for some of our neighbors ….


By the way, here’s an interesting feature of the Set-Cs cmdlets: if you don’t specify an Identity then the Set-Cs cmdlet will apply the changes to the global policy or setting. What do we mean by that? Well, take this command, for example:


Set-CsVoicePolicy –Identity “RedmondVoicePolicy” –AllowSimulRing $False


What’s that command going to do? Yep: it’s going to grab the voice policy RedmondVoicePolicy and then set the AllowSimulRing property to False ($False).


OK, that makes sense. So then what do you think this command will do:


Set-CsVoicePolicy –AllowSimulRing $False


If you guessed, “It’s going to change the AllowSimulRing property on all your voice policies,” well, that’s a good guess. However, it’s also a wrong guess. As we saw earlier, if you run Get-CsVoicePolicy without specifying an Identity the cmdlet returns instances of all your voice policies. That’s because, with the Get-Cs cmdlets, no Identity means “bring back everything.”


However, that’s not the case with the Set-Cs cmdlets. If you leave off the Identity, the Set-Cs cmdlets will automatically modify the global instance (and only the global instance) of your policy or setting. In other words, the command we just showed you is equivalent to this:


 Set-CsVoicePolicy –Identity global –AllowSimulRing $False


Is that important to know? Well, we think so. With the Get-Cs cmdlets you can leave off the Identity. That won’t hurt anything; it just means that you might get back more information than bargained for. With the New-Cs and the Remove-Cs cmdlets you can also leave off the Identity; in that case, the cmdlet will prompt you to enter the appropriate Identity. However, if you leave off the Identity when running one of the Set-Cs cmdlets that cmdlet will go ahead and modify your global policy or setting. Needless to say, that may – or may not – be what you wanted to do. A good rule of thumb? Always specify the Identity when running one of the Set-Cs cmdlets.


The Test-Cs Cmdlets


The Test-Cs cmdlets are often referred to by their scientific names: synthetic transaction cmdlets. Synthetic transaction cmdlets are actually pretty cool: they provide a way for you to test various parts of your Lync Server infrastructure and to verify that those parts are actually working.


Note. If you’re like the authors of this article (which isn’t something you should admit to) then your knowledge of scientific names probably comes from old Looney Tunes cartoons. In those cartoons, the scientific name for the Road Runner included “Acceleratii Incredibilus;” “Burn-em upus asphaltus;” “Velocitus Incredibilus;” and “Birdibus Zippibus.”


In case you’re wondering, real Road Runners have the scientific name ”Geococcyx californianus.”


For example, suppose you’ve gotten an email from Jonathan Haas; Jonathan wants to know why he can’t send an instant message to Ken Myer. Why can’t Jonathan Haas send an instant message to Ken Myer? That’s a good question, and one that’s going to be very difficult for you to answer.


Unless you run the Test-CsIm cmdlet, of course.


So what does the Test-CsIm cmdlet do? As the name clearly implies (well, sort of, if you tilt your head a little and look at it sideways), Test-CsIm tests the ability of one user to send an instant message to another. If you know the user name and password for the two users you can see for yourself whether or not Jonathan Haas can (or cannot) send an instant message to Ken Myer:


$cred1 = Get-Credential “litwareinc\jhaas”

$cred2 = Get-Credential “litwareinc\kenmyer”


Test-CsIm -TargetFqdn -SenderSipAddress “” -SenderCredential $cred1 -ReceiverSipAddress “” -ReceiverCredential $cred2 -Verbose


So what’s going on here? Well, using the supplied user credentials, Test-CsIm is going to log on to Lync Server as both Jonathan Haas (litwareinc\jhaas) and Ken Myer (litwareinc\kenmyer). The software will check to see if Jonathan Haas can successfully send an instant message to Ken Myer, then it will log off. The whole thing will take place in a matter of seconds, and won’t disrupt the system in any way: for example, if the real Ken Myer is currently logged on to the system, he won’t see this instant message nor will he be logged off when Test-CsIm logs off. With synthetic transactions, everything happens under the covers.


That’s cool, but here’s something that might be even cooler. Sometimes you don’t care whether a particular person (Jonathan Haas) can send an instant message to another particular person (Ken Myer); instead, you just want to make sure that any user can send an instant message to any other user. (In other words, you aren’t interested in the specifics; you just want to see whether or not instant messaging itself is working.) In that case, you can set up a “health register” that features a pair of predefined user accounts. Do that and you can then run a test of your instant messaging system using a command no more complicated than this:

Test-CsIm -TargetFqdn -Verbose

In this example, all you have to do is specify the fully qualified domain name of the Registrar pool to be tested; Test-CsIm takes care of the rest, logging on to the system using the two predefined users, verifying that an instant message can be sent from one user to the other, then logging back off from the system.


We told you that was cool.


OK; that pretty much completes our overview of the major Communications Server cmdlet species. Now let’s take a look at some of the more interesting cmdlet sub-species.



Get-Cs Cmdlets That Have No Equivalent Set-Cs Cmdlet


Communications Server cmdlets tend to hang out together; for example, if you see a Get-CsAddressBookConfiguration cmdlet you’ll almost always see the following cmdlets as well:


·         New-CsAddressBookConfiguration

·         Remove-CsAddressBookConfiguration

·         Set-CsAddressBookConfiguration


On occasion, however, you’ll see a Get-Cs cmdlet that has no corresponding Set-Cs cmdlet. For example, Lync Server has a cmdlet named Get-CsPool that returns information about your Lync Server pools. And yet, try as you might, you can’t find a corresponding Set-CsPool. Are you doing something wrong?


Well, if you’re spending all your time Lync Server cmdlet watching, yes, someone could probably make that argument. But as far as tracking down the Set-CsPool cmdlet goes, no, you’re not doing anything wrong; that’s because there is no Set-CsPool cmdlet. Why not? One reason and one reason only: although you can retrieve pool information using Windows PowerShell you can’t change pool information using Windows PowerShell. To modify the properties of a pool you must use the Topology Builder tool. If there’s no PowerShell cmdlet that lets you change pool properties then you’re not going to be able to change pool properties using a PowerShell cmdlet.


Which, come to think of it, actually makes a lot of sense, doesn’t it?


Note. You know, now that you mention it, there is an easy way to locate individual families of Lync Server cmdlets. For example, we know there’s a Get-CsVoiceRoute cmdlet; how can we tell if there are any other CsVoiceRoute cmdlets?


Here’s how:


Get-Command –Noun CsVoiceRoute


All we’re doing here is asking the Get-Command cmdlet to return all the cmdlets that have the noun CsVoiceRoute. In turn, Get-Command should bring back the following:


CommandType   Name                 Definition

———–   —-                 ———-

Cmdlet        Get-CsVoiceRoute     Get-CsVoiceRoute [[-Iden …

Cmdlet        New-CsVoiceRoute     New-CsVoiceRoute [[-Iden …

Cmdlet        Remove-CsVoiceRoute  Remove-CsVoiceRoute [[-I …

Cmdlet        Set-CsVoiceRoute     Set-CsVoiceRoute [[-Iden …

Cmdlet        Test-CsVoiceRoute    Test-CsVoiceRoute [[-Ide …


As a general rule, if you have a Get-Cs cmdlet that doesn’t have a corresponding Set-Cs cmdlet then you’re dealing with a read-only object.



Set-Cs Cmdlets That Have No Equivalent Get-Cs Cmdlet


OK, so, if you have a Get-Cs cmdlet but no Set-Cs cmdlet then you’re dealing with a read-only object. So what happens if you have a Set-Cs cmdlet but no Get-Cs cmdlet; does that mean we’re dealing with some weird kind of write-only object?


Generally speaking, no. There’s no denying that there are a number of Lync Server nouns that only have a Set- cmdlet; for example:


·         Set-CsConferenceServer

·         Set-CsDirector

·         Set-CsEdgeServer

·         Set-CsMonitoringServer

·         Set-CsPstnGateway


And yes, now that we think about it, that does seem a little odd, doesn’t it: you can set the property values of a monitoring server, but you can’t get the property values of a monitoring server?


As it turns out, however, you can get the property values of a monitoring server, as well as the property values for most (if not all) of these so-called “write-only” cmdlets. For some reason, these property values are all retrieved using the Get-CsService cmdlet. You say you want to retrieve information about your monitoring servers? This command won’t do you any good:




That’s because that referenced cmdlet – Get-CsMonitoringServer—doesn’t actually exist. However, this command will work:


Get-CsService -MonitoringServer


In other words, Monitoring Server has its very own Get-CsService parameter; so, too does Conference Server, Director, Edge Server, and a bunch of other services and server roles. Why this one multi-purpose cmdlet (Get-CsService) rather than individual cmdlets like Get-CsMonitoringServer or Get-CsEdgeServer? We don’t know. That’s just the way Nature intended things to be.



Cmdlets That Have No New-Cs or Remove-Cs Cmdlets


Some of the rarer members of the Lync Server cmdlet family are the nouns that have Get-Cs and Set-Cs verbs but no New-Cs or Remove-Cs verbs. (You know, like Get-CsAccessEdgeConfiguration and Set-CsAccessEdgeServerConfiguration.) Which leads to an obvious question: if there’s no New-CsAccessEdgeConfiguration cmdlet then how are you supposed to create a new Access Edge configuration?


Actually, that’s the point: you’re not supposed to create a new Access Edge configuration. As you probably know, Lync Server enables you to configure policies and settings at different scopes. (If you don’t know that then you need to read the article Scopes and Filters.) At the top of the heap is the global scope; by default, any policy or setting configured at the global scope applies to everyone and everything in the organization. Period.


Well, unless you configure a corresponding policy at, say, the site scope; in that case, the site-scoped policy or setting takes priority over the global policy or setting. Likewise, a service-scoped policy trumps a site policy, and a per-user policy trumps everything else.


That’s interesting, but how did we say you can configure Access Edge settings at the site scope? Well, we didn’t; that’s because you can’t configure Access Edge settings at the site scope. Instead, all your Access Edge settings must be identical: the only scope where you can configure Access Edge settings is the global scope. Why? Because if you could configure these settings at the site then you couldn’t guarantee that the settings would be identical throughout the organization.


Which, if you think about it, makes sense.


So how does this explain the lack of a New-CsAccessEdgeConfiguration and a Remove-CsAccessEdgeConfiguration cmdlet? That’s easy: there’s no New-CsAccessEdgeConfiguration cmdlet because these settings can only be configured at the global scope, and Lync Server won’t let you create new configuration settings at the global scope. (It’s possible to create a few things, such as normalization rules, at the global scope, but never possible to create configuration settings at the global scope.) If you don’t believe us, try running this command and see what happens:


New-CsAddressBookConfiguration –Identity global


No need to tell us what happened; we already know what happened. You got an error message similar to this:


New-CsAddressBookConfiguration: AddressBookConfiguration with identity Global already exists.


Like we said, it can’t be done.


Along the same lines, there’s no Remove-CsAccessEdgeConfiguration cmdlet because you can’t remove global settings, either. Granted, you can – in most cases – run a command similar to this one:


Remove-CsAddressBookConfiguration –Identity global


However, that command won’t actually delete the global settings; it will simply take the global properties and reset each one to its default value. But with Access Edge configuration settings you can’t even do that much.


And if you’re thinking, “Wow, that reminds me of the Dusky-Headed Parakeet, which is found in the western Amazon Basin in Colombia, Peru, Bolivia, and Brazil and, though it prefers varzea forest and tall trees in swamps, also occurs in cleared areas and plantations,” well, we were thinking the exact same thing.



Solitary New-Cs Cmdlets


It stands to reason that, if you can create a new something using Windows PowerShell, then you can also use Windows PowerShell to return the values of that something. In other words, if you have a New-Cs cmdlet then you should probably have a corresponding Get-Cs cmdlet. And, for the most part, that’s true: cmdlets of a feather flock together.


Note. Although most people refer to a “flock of birds,” birds of a feather don’t necessarily flock together. Instead, some chatter, some peep, and some even murder:


·         A bellowing of bullfinches

·         A chatter of parakeets

·         A siege of bitterns

·         A peep of chickens

·         A siege of herons

·         A train of jackdaws

·         An exaltation of larks

·         An unkindness of ravens

·         A venue of vultures

·         A murder of crows


But the idea that for every New-Cs cmdlet there’s a corresponding Get-Cs cmdlet is just a general rule, and there are exceptions to that rule. Take New-CsRgsHoliday, for example. The New-CsRgsHoliday cmdlet creates holidays for use with the Response Group application. But even though there’s a New-CsRgsHoliday cmdlet, there isn’t a Get-CsRgsHoliday cmdlet. Any chance someone could explain that?


No? OK, then; we’ll give it a whirl.


Why is there a New-CsRgsHoliday cmdlet but no corresponding Get-CsRgsHoliday cmdlet? Because, in the current incarnation of Lync Server, holidays are not a standalone object: you can’t have a holiday that (like, say, a voice policy) simply exists. Instead, all holidays must be assigned to a holiday set; if you don’t have a holiday set then there’s nothing for you to do with your holiday.


In other words, if you’re going to create a new Response Group holiday you have no choice but to assign that holiday to a holiday set. Like so:


$x = New-CsRgsHoliday -StartDate “12/25/2010” -EndDate “12/25/2010” -Name “Christmas Day”

$y = Get-CsRgsHolidaySet -Identity “”  -Name “2010 Holidays”


Set-CsRgsHolidaySet -Instance $y


What happens if you don’t assign the holiday to a holiday set? Nothing happens – literally. Instead, the new holiday will simply disappear the moment you terminate your Windows PowerShell session or delete/reassign the object reference variable ($x). If you see a New-Cs cmdlet that has no corresponding Get-Cs cmdlet that means that the cmdlet is designed to create an object that must then be assigned to another object; that’s because the created object can’t exist on its own. (Much like the average 16-year-old.) There’s no Get-CsRgsHoliday cmdlet simply because there’s nothing to get. If you want to take a look at the Response Group holidays, you’ll have to look at each of your holiday sets.


And yes, in some ways that is a little weird. But that’s life for you, eh?



So What Now?


Well, now that you’ve memorized everything in this Field Guide, you should be ready to do some Lync Server cmdlet-watching on your own. For a few additional tips on spotting Lync Server cmdlets, take a look at the article Listing All the Microsoft Lync Server 2010 Cmdlets. We also put together a working list of the current Lync Server cmdlets and a brief description of what those cmdlets do.


And if you’d like to try your hand at actually using a Microsoft Lync Server cmdlet, well, in that case you might want to read the article Enabling a User for Microsoft Lync Server 2010 and Enterprise Voice: A Comprehensive Lync Server Walkthrough. Take our word for it: simply watching Lync Server cmdlets is nowhere near as much fun as actually using Lync Server cmdlets.


Hard as that might be to believe.


Skip to main content