Share via


Microsoft Lync Server 2010: PowerShell Changes from Beta to Beta Refresh

Microsoft Lync Server 2010: Windows PowerShell Changes from Beta to Beta Refresh

New Cmdlets

New/Newly-Renamed Parameters

New Service Identities

New Behavior When Removing Per-User Policies

New Uses for the Force Parameter

New Way to Create Static Routes

New Behavior for the New-CsRgs Cmdlets

New Behavior for the New-CsVoiceNormalizationRule Cmdlet

New Naming Behavior for Dial Plans

New Names: Get-CsPstnUsage and Set-CsPstnUsage

New Look for the RBAC Cmdlets

New Way to Unassign a Per-User Policy

New Priority Property Added to the Dial-In Conferencing Cmdlets

Newly-Updated Cmdlet Help

New Requirements for Simple URL Configurations

Newly-Departed: Disconnect-CsUser

New Requirement for the Cmdlets Using the InMemory Parameter

New Report Format: HTML

Is That Everything You Need to Know About Windows PowerShell and Beta Refresh?

Change is good, right? Well, let’s hope so, because there have been a lot of changes to the Microsoft Lync Server 2010 (formerly known as Microsoft Communications Server "14") implementation of Windows PowerShell since the beta version of the software was released a few months ago. If you’re lucky enough to have gotten a copy of the beta refresh version of Lync Server, then this article is for you: it provides an overview of some of the more important/more interesting changes that have been made to the Lync Server implementation of PowerShell. And what if you weren’t lucky enough to have gotten a copy of the beta refresh version? Well, take heart: you’re more than welcome to read the article anyway. And who knows? There’s always the chance that there will be a more widespread beta sometime in the future. Something to look forward to, eh? (Updated: Hey, we were right (for once). There's now a release candidate available for download.)

In the meantime, here’s a peek at some of the major changes that have taken place over the past few months. This article provides a detailed look at these changes. If you’d rather have a somewhat less detailed look at the changes, well, that’s what this other article is for.

New Cmdlets

As far as cmdlets go, there really haven’t been that many changes between beta and beta refresh. A few cmdlets have bit the dust: farewell, Install-CsClientUpdate and Get-CsConferenceAccessNumberList; we hardly knew ye. A few cmdlets have been renamed; for example, Get-CsUserClusterInfo is now known as Get-CsUserPoolInfo. And there are a few new cmdlets, most notably:

· The new Kerberos cmdlets. In Office Communications Server 2007 R2, Internet Information Service (IIS) ran under a standard user account. That was fine, except that many organizations don’t allow standard user accounts to have non-expiring passwords. In turn, that meant that, sooner or later, your IIS password is going to expire and, when it does, you’re going to run into problems. And the biggest problem is this: although it’s easy enough to assign the account a new password, it’s not always easy to determine that the problems you’re having are due to an expired password in the first place.

At any rate, the new Kerberos cmdlets help minimize this problem by enabling you to create a single account that all the IIS servers in a site can run under. For more information, type Get-Help New-CsKerberosAccount –Full | More at the Windows PowerShell prompt.

· The new audio conferencing provider cmdlets. An audio conferencing provider is a third-party company that provides organizations with conferencing services (including, in some cases, fancy stuff like live translation, transcription, and live per-conference operator-assistance). In the beta version of Lync Server you could assign a user an audio conferencing provider by using the Set-CsUser cmdlet.

Or so they told us, anyway. To be perfectly honest, we always ran into trouble when we tried working with the audio conferencing providers in the beta version of Lync Server. In the beta refresh version, however, working with audio conferencing providers is a snap. Take a peek at the help topics for New-CsUserAcp and Set-CsUserAcp for more information.

· The new presence policy cmdlets. These new cmdlets (e.g., Set-CsPresencePolicy) let you manage the maximum number of prompted subscribers and category subscriptions a user can have. If you aren’t sure what that means, well, join the crowd. But a reasonably good explanation can be found by typing Get-Help Set-CsPresencePolicy –Full | more at the Windows PowerShell prompt.

So do we have a complete list of the cmdlet changes from beta to beta refresh? Well, no, not exactly. But while we try to dig one up you can always take this approach: Before you install beta refresh (that is, while you’re still running the beta version of Lync Server) run the following command:

Get-Command * –Module OCS | Select-Object Name > C:\Beta.txt

That command is going to grab a collection of all the Lync Server cmdlets and store them in the file C:\Beta.txt. Make sure you keep a copy of that file in a safe place and then, after you install the beta refresh version, run this command:

Get-Command * –Module OCS | Select-Object Name > C:\BetaRefresh.txt

Compare the two lists and you’ll have a list of all the cmdlet changes that took place between beta and beta refresh.

And yes, now that you mention it, you can use Windows PowerShell to help you determine the differences between the two sets of cmdlets. Just run the following command:

Compare-Object –ReferenceObject (Get-Content C:\Beta.txt) –DifferenceObject (Get-Content C:\BetaRefresh.txt)

For more information, type Get-Help Compare-Object –Full | more at the Windows PowerShell prompt.

New/Newly-Renamed Parameters

Cmdlet names might not have changed much over the past few months, but there have been a bunch of parameter changes made since the beta version was released. We aren’t going to list all the parameter changes; that’s partly because we don’t actually have a master list of all the changes (there have been scores and scores of them) and partly because, by the time we finished typing up that list, we’d probably be on Service Pack 3 of Link Server. Suffice to say, there have been a bunch of new parameters added, a bunch of old parameters deleted, and a bunch of parameters given new names.

But while we won’t bother trying to run through every last parameter change, what we will do is include a couple notes of interest. To begin with, you might notice that two parameters in particular – Tenant and LocalStore – have largely disappeared. There’s a good reason for that: for the most part, those two parameters were meaningless. The Tenant parameter is meant for the "in-the-cloud" version of Lync Sercer (Lync Server Online) Because we’re dealing with the "not-in-the-cloud" version of the software we typically don’t have much use for the Tenant parameter. If you still have your beta copy of Lync Server lying around, you’ll see that about the only thing the Tenant property lets you do is retrieve an object by using the object GUID rather than the object Identity. Why would you want to use an object GUID rather than an object Identity? Beats us, which is one reason you won’t see the Tenant parameter much anymore. With the exception of a straggler or two, the Tenant parameter is gone.

As for LocalStore, well, that parameter tells a cmdlet to retrieve Lync Server data from the local replica rather than directly querying the Central Management database for the latest and most up-to-date version of that data. Believe it or not, there are times when this can be useful, primarily when you’re working on an Edge Server that doesn’t have access to the Central Management database or when replication seems to have failed for some reason. Because there are occasions when this parameter is useful you’ll still see LocalStore used with certain cmdlets (mostly the Get-Cs cmdlets). For cmdlets where LocalStore makes much less sense (which typically means that it makes no sense whatsoever) the parameter has been removed.

Note. That probably sounds pretty reasonable to all of you. As technical writers, however, we get very nervous any time people talk about getting rid of useless things that make no sense whatsoever.

Why? Uh, no reason ….

As far as all the many parameter changes go, well, most of those changes have been recorded in the appropriate help topic. However, there are a few help topics that are missing a new parameter or two, as well as the occasional help topic that insists that an old parameter still exists even though it really doesn’t. Those problems will all be corrected before Lync Server 2010 is released. In the meantime, you can always run a command similar to this one to see the real parameter set for a cmdlet:

Get-Command Set-CsAddressBookConfiguration –Syntax

And if you’re really hardcore about all this there’s one other thing you can do:

1. Run a script that retrieves all the parameters for all the beta cmdlets.

2. Install the beta refresh version of Lync Server.

3. Re-run the script to retrieve all the parameters for all the beta refresh cmdlets.

4. Compare the two files (beta parameters vs. beta refresh parameters).

To be honest, that seems like a lot more trouble than it’s worth, but here’s a script that retrieves all the parameters for all the Lync Server cmdlets, and then saves that information in a text file:

$x = Get-Command * -Module OCS -CommandType cmdlet

Out-File C:\Parameters.txt

$newline = "`n"

foreach($i in $x)

    {

         $i.Name | Out-File C:\Parameters.txt -Append

         $y = ((Get-Command $i.Name).ParameterSets[0].Parameters |
Select-Object Name | Sort-Object)

         foreach ($z in $y) {$z.Name | Out-File C:\Parameters.txt -Append}

         $newline | Out-File C:\Parameters.txt -Append

    }

Give it a try and see what happens.

New Service Identities

Back in the old days, services had Identities that looked something like this:

service:Redmond-Registrar-1

What did an Identity like that one mean? Well, the service: prefix indicated that we were dealing with a service. Redmond represented the site where the service was located, Registrar indicated the type of service, and 1 – well, 1 was just a number Lync Server assigned to the service at the time the service was installed. So what if you had multiple Registrars in the Redmond site? Well, then you’d have services with Identities similar to these:

service:Redmond-Registrar-1

service:Redmond-Registrar-2

service:Redmond-Registrar-3

service:Redmond-Registrar-4

And how would you actually know which Registrar was Registrar 2 and which Registrar was Registrar 3? Well, let’s see: divide by the square of the hypotenuse, carry the 1, bring down the 7 – OK, fine, we admit it: we have no idea how you’d know which Registrar was Registrar 2 and which Registrar was Registrar 3.

But that’s OK, because services no longer have such cryptic Identities. Instead, beta refresh services have Identities similar to this:

Registrar:redmond-cs-001.litwareinc.com

How do you interpret an Identity like that one? Well, let’s see: first of all, we have the Registrar service running on the pool redmond-cs-001.litwareinc.com. And – well, that’s really all there is to it, isn’t there?

Wow. Apparently change is good.

And what if you have multiple Registrars in a site? Then you’ll have multiple services with Identities similar to these:

Registrar:redmond-cs-001.litwareinc.com

Registrar:redmond-cs-002.litwareinc.com

Registrar:redmond-cs-003.litwareinc.com

Registrar:redmond-cs-004.litwareinc.com

Four pools – redmond-cs-001.litwareinc.com; redmond-cs-002.litwareinc.com; redmond-cs-003.litwareinc.com; redmond-cs-004.litwareinc.com – and four Registrars. It doesn’t get any easier than that.

Incidentally, there’s at least one more major change to be aware of when it comes to service Identities: a number of the service roles have been renamed. For example, the ApplicationStore role is now known as the ApplicationDatabase role; the UserServices role is now known as the UserServer role; etc. How are you supposed to keep track of all these new service Identities and server roles? The best way we know to do that is to turn to our old friend the Get-CsService cmdlet. For example, if you’d like to peruse a list of all your service Identities you can use a command like this one:

Get-CsService | Select-Object Identity

Or maybe you’d like to see a sorted list of all the service roles. This command will do the trick, and will weed out any duplicate role names to boot:

Get-CsService | Select-Object Role -Unique

And what if you just can’t stand to say goodbye to the old service Identities? Well, if that’s the case we have some good news for you: the old-fashioned service Identities still exist; they’re just stored in the ServiceID property instead of the Identity property. As long as you’re using the Get-CsService cmdlet that means you can use a command like this one to find the service Redmond-Registrar-1:

Get-CsService | Where-Object {$_.ServiceId –eq "Redmond-Registrar-1"}

Note. Yes, now that you asked, you could use a wildcard here and there to get the preceding command to return all the services running in the Redmond site. But a much better, and much simpler, way to do that is to use the SiteId property:

Get-CsService | Where-Object {$_.SiteId –eq "site:Redmond"}

What About the Service: Prefix?

As you might have noticed, we haven’t used the service: prefix when specifying a service Identity. No doubt your first thought was, "Perfect. Now I don’t have to waste my time typing service: every time I specify a service Identity." And that’s true: you don’t. And more often than not, that’s a good thing.

But consider this scenario: you want to return information about all the client version policies configured at the service scope. How are you supposed to do that when nothing in the Identity actually specifies that this is a service-scoped policy as opposed to, say, a site-scoped policy?

Well, what you have to do in that case is – hey, wait a second: who said there’s nothing in the Identity that actually specifies that this is a service-scoped policy as opposed to, say, a site-scoped policy? As it turns out, the service: prefix is still officially part of the service Identity; if you want to, you can refer to a service using syntax like this:

Get-CsService –Identity "service:Registrar:atl-cs-001.litwareinc.com"

The service: prefix is still there; you just don’t need to use it because Lync Server can look at an Identity like Registrar:atl-cs-001.litwareinc.com and figure out for itself that we’re dealing with a service here.

So does that mean that service: is pretty much like an appendix: a completely useless hunk of junk that no longer serves any useful function whatsoever?

Note. Useless things like the appendix are also referred to as “vestigial structures.” Or, as we hinted at before, as “technical writers.”

Actually, there is at least one use for the service: prefix: you can use it to filter on items that were configured at the service scope. Need information about all the client version policies configured at the service scope? No problem:

Get-CsClientVersionPolicy –Filter "service:*"

New Behavior When Removing Per-User Policies

Let’s suppose that, back in the beta version of Lync Server, you created a new per-user conferencing policy named RedmondConferencingPolicy. Let’s further suppose that you assigned this new policy to a bunch of users. Now, having had second thoughts about this, you’ve decided to get rid of the conferencing policy RedmondConferencingPolicy. With that in mind, you ran the following command:

Remove-CsConferencingPolicy –Identity "RedmondConferencingPolicy"

So what happened when you ran that command? You got it: the conferencing policy RedmondConferencingPolicy was removed. Which should come as no big surprise: what else would you a cmdlet named Remove-CsConferencingPolicy do?

The only problem there was the fact that Remove-CsConferencingPolicy – or any of the cmdlets used to remove per-user policies – would remove RedmondConferencingPolicy even though the policy was currently assigned to a bunch of users. Is that bad? Well, not necessarily; after all, if a per-user conferencing policy assigned to a user no longer exists, the user will simply fall under the jurisdiction of the site-scoped conferencing policy. (Or, if their site doesn’t have a conferencing policy, then they’ll fall under the jurisdiction of the global conferencing policy.) It’s not a fatal error by any means.

On the other hand, though, the fact that these users were assigned a per-user policy in the first place suggests that maybe you didn’t want them managed by the site/global policy. It’s not a major problem, but it would have been nice if Remove-CsConferencingPolicy had let you know that the policy you were about to remove was still assigned to one or more users.

So what’s different in beta refresh? Let’s assume the same scenario: you’ve created a per-user policy, you’ve assigned that policy to a bunch of users, and now you want to remove that policy. To do so, you use the same command you used in the beta version of Lync Server:

Remove-CsConferencingPolicy –Identity "RedmondConferencingPolicy"

So what’s the difference between beta and beta refresh? Here’s the difference: when you try to remove a per-user policy that’s still assigned to at least one user the policy isn’t automatically, and silently, removed. Instead, you get the following prompt:

The policy "Tag:RedmondConferencingPolicy" 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”):

This prompt is going to remain onscreen until you respond to it. And unless you answer yes (by pressing the Y key) the policy isn’t going to be deleted.

Period.

A couple of comments about this behavior. First, we should note that the prompt itself is perhaps a little over-zealous: you don’t have to assign these users a new policy. You can assign them a new policy if you want to, but if you don’t that simply means that these users will fall under the jurisdiction of the site-scoped conferencing policy or the global conferencing policy.

Note. What if you did want to assign all these users a different conferencing policy? Here’s a simple little command that grabs all the users who’ve been assigned the conferencing policy RedmondConferencingPolicy and assigns them a new conferencing policy:

Get-CsUser –Filter {ConferencingPolicy –eq "RedmondConferencingPolicy"} | Grant-CsConferencingPolicy –PolicyName "RevisedConferencingPolicy"

Second, what if you don’t care that the policy is currently assigned to one or more users; what if you just want to remove the policy, and without having to respond to a prompt telling you that the policy is currently assigned to one or more users? That’s fine; that’s what the new Force parameter is for. To replicate the way the policy removal cmdlets worked in the beta version of Lync Server just add the Force parameter when removing the policy:

Remove-CsConferencingPolicy –Identity "RedmondConferencingPolicy" -Force

Do that and RedmondConferencingPolicy will be instantly, and silently, removed. No questions asked.

What Difference Does It Make If I Don’t Unassign a Policy Before Removing It?

As we explained above, if you delete a per-user policy that’s currently assigned to one or more users nothing bad will happen to those users; they’ll simply be managed by the site conferencing policy or the global conferencing policy. However, there is one side-effect of removing a per-user policy that’s currently assigned to a user. Suppose RedmondConferencingPolicy is assigned to Ken Myer and we remove that policy. Let’s now run the following command to see which conferencing policy is assigned to Ken:

Get-CsUser "Ken Myer" | Select-Object DisplayName, ConferencingPolicy

Because we just removed the per-user policy assigned to Ken Myer you’d expect that he wouldn’t have any conferencing policy assigned to him. And that’s true: he doesn’t have any conferencing policy assigned to him. But here’s what you see onscreen:

WARNING: Policy with identity "14" has been removed.

DisplayName ConferencingPolicy

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

Ken Myer 14

What’s going on here? Well, for better or worse, when you remove a per-user policy the Remove-Cs cmdlet does not go through and update the Active Directory user accounts for any user assigned that policy. As far as Active Directory is concerned, Ken Myer is still assigned the policy RedmondConferencingPolicy. Of course, that policy no longer exists. When we call the Get-CsUser cmdlet, it checks Active Directory to see which policies have been assigned to the user; these policies are stored by the identification number automatically assigned to them when the policy was created. In this case, RedmondConferencingPolicy was assigned the ID number 14 when it was created. Get-CsUser dutifully grabbed that ID number and then consulted Lync Server to see which conferencing policy has been assigned ID number 14. When it couldn’t find policy 14 it dutifully reported that the policy in question has been removed. However, and perhaps a bit unfortunately, it also reports that Ken has been assigned policy 14.

Before we go any further we should note that this isn’t going to create any problems for Ken Myer. Suppose Ken decides to schedule an online conference. Before he can do so, Lync Server needs to check his conferencing policy in order to know what things he can and cannot do when scheduling a conference. (For example, what’s the maximum number of people he can invite to this get-together?) What if Lync Server can’t find the policy that’s allegedly been assigned to Ken? That’s fine; if Lync Server can’t find the specified per-user policy then it will automatically look to see if there’s a conferencing policy assigned to Ken’s site. If there isn’t, then it will automatically use the global conferencing policy. No harm, no foul.

So then what’s the problem? Well, the problem is that you could get somewhat-screwy results if you try to run a command like this one:

Get-CsUser –Filter {ConferencingPolicy –eq $Null}

This command is supposed to return a collection of all the users who have not been assigned a per-user conferencing policy. Ken Myer hasn’t been assigned a per-user conferencing policy so he’ll show up as part of this collection, right? Right.

Um, by which we mean this: wrong. It’s true that Ken has not been assigned a per-user conferencing policy, at least not a conferencing policy that actually exists. But remember, Active Directory still thinks that Ken has been assigned conferencing policy 14. It’s not a real policy, but it doesn’t matter: the system is going to insist that Ken Myer has been assigned a per-user conferencing policy.

So what’s the solution to this potential problem? Well, the best way to avoid this issue is to unassign a policy before you remove it. That’s what these two commands will do:

Get-CsUser –Filter {ConferencingPolicy –eq "RedmondConferencingPolicy"} | Grant-CsConferencingPolicy –PolicyName $Null

Remove-CsConferencingPolicy –Identity "RedmondConferencingPolicy"

The first command simply grabs all the users assigned the policy RedmondConferencingPolicy and then unassigns that policy; that means that these users will no longer be assigned a per-user conferencing policy. The second command then deletes the policy RedmondConferencingPolicy. What happens if we do this and then look at Ken Myer’s user account? This is what happens:

DisplayName ConferencingPolicy

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

Ken Myer

Which is a little more like it.

New Uses for the Force Parameter

I you read the section of this article titled New Behavior When Removing Per-User Policies then you now know exactly what the Force parameter is for: it prevents a confirmation prompt from appearing any time you try to delete a per-user policy that’s currently assigned to one or more users. Pretty simple, huh?

Except for one thing: why, then, does a cmdlet like Disable-CsAdDomain have a Force parameter? And another thing: why, then, does a cmdlet like New-CsPinPolicy have a Force parameter? And another thing: why does –

Well, you get the idea. As it turns out, the Force parameter is now tacked on to a ton of different Lync Server cmdlets. But it’s not always the same Force parameter; instead, there are at least three flavors of Force:

· Remove a per-user policy even if it’s currently assigned to one or more users. This one we’ve already talked about.

· Remove something even if it’s still being used elsewhere. For example, by default the Disable-CsAdDomain cmdlet will not roll back Active Directory domain settings if it detects that there’s still a Lync Server front end server, Conferencing server, or Web server running in the domain. But if you include the Force parameter? You got it: domain settings will be removed even if you still have, say, a Lync Server front end machine running in the domain.

· Suppress the display of any non-fatal errors that might pop up when you run a cmdlet. This is probably the most common use of the Force parameter. From time-to-time you might run a command and get assorted error messages that essentially say, “Well, there was a little problem. The command still ran, but we thought you’d like to know about this little issue.” If you’d prefer not to know about that little issue then simply add the Force parameter to the command.

So how do you know which cmdlets have a Force parameter, and how do you know what that Force parameter actually does? Well, the best way is to check the help. (Granted, the help isn’t 100 percent up-to-date for beta refresh, but it’s still the best way to go.) If you want to know which Lync Server cmdlets use the Force parameter (or, at least, which cmdlets have the Force parameter documented in their help topic) just run this command:

Get-Help "*-Cs*" –Parameter Force

Oh: and here’s another way to determine which cmdlets use a specified parameter.

New Way to Create Static Routes

If you tried to create a static route in the beta version of Lync Server there’s a pretty good chance that you gave up long before the route was actually created. It’s not that creating a static route was necessarily hard; it’s just that creating a static route required the use of several million cmdlets and several million child objects. (Plus the cmdlets had names like New-CsSipProxyTransport, names that didn’t sound like they had anything to do with creating static routes.) For example, here’s one way to create a static route in the beta version of Communications Server:

$cert = New-CsSipProxyUseDefaultCert

$tls = New-CsSipProxyTLS -Certificate $cert `
-Fqdn atl-proxy-001.litwareinc.com

$transport = New-CsSipProxyTransport -TransportChoice $tls -Port 8-25

$route = New-CsSipProxyRoute -Transport $transport `
–MatchUri "sip:*@litwareinc.com"

By our count, that’s four cmdlets – New CsSipProxyUseDefaultCert; New-CsSipProxyTLS; New-CsSipProxyTransport; and New-CsSipProxyRoute – needed to create a single static route.

That’s what we said: wow.

Fortunately, things are a little easier in the beta refresh version. You say you need one new static route? That’s fine; all you need is one command and one cmdlet:

$x = New-CsStaticRoute –TLSRoute –Destination "atl-proxy-001.litwareinc.com" –Port 8025 –MatchUri "sip:*@litwareinc.com" –UseDefaultCert $True

The moral of the story? If you need to create a static route in the beta refresh version of Lync Server then use the new cmdlet New-CsStaticRoute. You can thank us later.

Well, OK: you can thank the team that created the New-CsStaticRoute cmdlet.

New Behavior for the New-CsRgs Cmdlets

In the beta version of Lync Server the New-CsRgs cmdlets (cmdlets that created new Response Group objects) exhibited an interesting behavior: they didn’t actually create any new Response Group objects. Or, to be fair, they didn’t directly create any new Response Group objects. Instead, the New-CsRgs cmdlets would create an object that existed only in memory; you’d then have to use a corresponding Set-CsRgs cmdlet to actually create something. For example, to create a new Response Group agent group you’d have to, at a minimum, use a pair of commands like this (note that we’re cheating a little and using the new service Identity rather than the old-fashioned service Identity):

$x = New-CsRgsAgentGroup –Parent ApplicationServer:atl-cs-001.litwareinc.com –Name "Help Desk"

Set-CsRgsAgentGroup –Instance $x

That worked, but – speaking for ourselves – it also seemed like too much trouble. Sure, we’d be happy to create a Response Group agent group if it only took one command. But two commands ….

Well, with the beta refresh version of Lync Server we no longer have to worry about that; now we can create a Response Group agent group with just one command:

New-CsRgsAgentGroup –Parent ApplicationServer:atl-cs-001.litwareinc.com –Name "Help Desk"

Whew!

Incidentally, we should clarify that this works only for Response Group objects that can stand on their own. What does that mean? Well, take holidays, to name one. In the Response Group object model a holiday can exist only as part of a holiday set; there is no Get-CsRgsHoliday cmdlet because there are no holidays for that cmdlet to retrieve. For objects like holidays you still need to create the item in memory and then add it to the appropriate parent object. For example:

$x = New-CsRgsHoliday -StartDate "1/1/2011 12:00 AM" `
-EndDate "1/2/2011 12:00 AM" -Name "New Year's Day"

New-CsRgsHolidaySet -Parent "ApplicationServer:atl-cs-001.litwareinc.com" `
-Name "2011 Holidays" -Holidays($x)

New Behavior for the New-CsVoiceNormalizationRule Cmdlet

Here’s an interesting one. Voice normalization rules have to be associated with a dial plan; voice normalization rules can’t exist on their own. Got that? OK. Well, suppose you ran the following command in the beta version of Lync Server, and suppose no dial plan had been configured for the Redmond site:

New-CsVoiceNormalizationRule –Identity "site:Redmond/TestRule"

Is that command going to fail? Nope. In the beta version of Lync Server, if a dial plan didn’t exist then the New-CsVoiceNormalizationRule would just go ahead and create it. After you ran the preceding command you’d end up with two things:

· A dial plan for the Redmond site (with the Identity site:Redmond).

· A voice normalization rule for that new dial plan (with the Identity site:Redmond/TestRule).

Needless to say, that’s not how things work in the beta refresh version of Lync Server. (If that was how things worked then this would be a pretty pointless topic considering the fact that this article is all about things that have changed in the beta refresh version.) Suppose you haven’t configured a dial plan for the Redmond site and, in the beta refresh version, you try running this command:

New-CsVoiceNormalizationRule –Identity "site:Redmond/TestRule"

Is that going to work? Not exactly. Instead, you’re going to get an error message like this one:

New-CsVoiceNormalizationRule : Invalid identity "site:Redmond/TestRule": "Cannot add a normalization rule to missing dial plan "Site:Redmond". You must create the dial plan first."

As you can see, there are two important lessons to be learned here: 1) the New-CsVoiceNormalizationRule will no longer create a dial plan if the referenced dial plan does not exist; and, 2) we really do like to use double quote marks in our error messages, don’t we?

New Naming Behavior for Dial Plans

While we’re on the topic of dial plans, there are a couple of changes that have been made to the dial plan cmdlets. The first is a simple parameter rename: in beta you gave the dial plan a name by putting a value in the Name parameter. Now you give the dial plan a name by putting a value in the SimpleName parameter:

Set-CsDialPlan –Identity site:Redmond –SimpleName "Redmond Dial Plan"

We said we weren’t going to go through all the parameter renames, and we’re not. But there’s a reason we’re mentioning this one. The reason is that the behavior having to do with this parameter has also changed. In the beta release, you could give the Name property any string value you wanted. Each time you created a new dial plan you could leave the Name parameter blank and the dial plan would get a default name of DefaultProfile.

That doesn’t work anymore. The SimpleName property of a dial plan must be globally unique. That means it doesn’t matter what the scope or the Identity are, the SimpleName must be unique across all dial plans. For example, if you have a per-user dial plan with the Identity RedmondDialPlan and the SimpleName DialPlan1, you can’t also have a dial plan with the Identity site:Redmond (or any other Identity) and the SimpleName DialPlan1.

One thing that hasn’t changed is that you’re still not required to enter a SimpleName, a default will be provided. However, the default for a dial plan at the site scope will be the name of the site. (For example, a dial plan with the Identity site:Redmond will, by default, have a SimpleName of Redmond.) The default for a dial plan at the per-user scope will be the Identity of the dial plan (a dial plan with the Identity RedmondDialPlan will by default have a SimpleName of RedmondDialPlan).

New Names: Get-CsPstnUsage and Set-CsPstnUsage

Remember the CsPhoneUsage cmdlets? You know, Get-CsPhoneUsage and Set-CsPhoneUsage? Well, if you don’t, that’s actually a good thing: those cmdlets no longer exist. Instead, the CsPhoneUsage cmdlets are now the CsPstnUsage cmdlets: Get-CsPstnUsage and Set-CsPstnUsage. These changes simply bring the cmdlets in line with the Lync Server Control Panel, which refers to PSTN usages rather than phone usages.

Note. In case you’re wondering, PSTN usages are string values that link a voice policy to a voice route. Voice routes and voice policies each have a property named PstnUsages. How do you know if a given voice policy uses a given voice route? Just check the value of the PstnUsages property. If they have at least one value in common (e.g., Long Distance) that means that the voice policy and the route go together.

Incidentally, there’s another change involving phone usage – uh, PSTN usages. In the past, you could make up any old PSTN usage, on the fly, and add it to a voice policy. That’s no longer the case. With beta refresh, any PSTN usage added to a voice policy must be a real, live PSTN usage; in other words, it must appear in the collection of PSTN usages returned when you run this command:

Get-CsPstnUsage

So what happens if you actually need a PSTN usage that doesn’t appear in the official list of PSTN usages? That’s OK; you just need to create it first by using the Set-PstnUsage cmdlet. For example:

Set-CsPstnUsage –Identity global –Usage @{Add="Redmond Usage"}

After you’ve done that you can then add Redmond Usage to a voice policy or voice route.

New Look for the RBAC Cmdlets

RBAC (Role Based Access Control) has been introduced in Lync Server as a way to help delegate administrative control of the software; for example, rather than making a user a full-fledged, and all-powerful, Administrator you can give that user the right just to manage user accounts or just to manage archiving activities. In addition, you can also limit the scope of these administrative rights: for example, you might give someone the right to manage users, but only users in the Redmond site or in the Finance OU. Is RBAC better for delegating administrative rights than using ACLs, SACLs, and DACLs to carry out this same task? Well, to be honest, if you’ve ever tried to delegate administrative rights using ACLs, SACLs, and DACLs you probably wouldn’t be asking this question.

In other words: yes.

We mention all this simply because there have been a couple of major changes to RBAC since the beta version of Lync Server was released. First, the RBAC roles have been modified: the beta refresh version does not use the same RBAC roles as the beta version, and the cmdlets assigned to some of those roles have changed as well. If you’d like to see an up-to-date list of RBAC roles just run the following command:

Get-CsAdminRole | Select-Object Identity

And if you’d like to see a list of the cmdlets that have been assigned to a role (for example, the cmdlets assigned to the CsServerAdministrator role) then just run a command like this one:

Get-CsAdminRole –Identity "CsServerAdministrator" | Select-Object –ExpandProperty Cmdlets

Yes, that is pretty easy, isn’t it?

The second major change involves custom roles. You can still create custom roles in the beta refresh version of Lync Server; for example, you might create a custom Server Administrator role (based on the CsServerAdministrator role) and then give that custom role management rights only to a specified site or a specified OU. Nothing has changed there. However, the one thing that has changed is that you can no longer add new cmdlets to a custom role nor can you remove any of the cmdlets assigned to a custom role.

In other words, whatever cmdlets are assigned to the role when the role is created are the cmdlets that will always be assigned to the role. Is that a big deal? No, not really. Just something to be aware of.

New Way to Unassign a Per-User Policy

So you say you assigned Ken Myer a conferencing policy named RedmondConferencingPolicy, and now you want to unassign that policy? Okey-doke. In the beta release of Lync Server that was easy enough; you just used the Grant-CsConferencingPolicy cmdlet without specifying a policy name. You know, like this:

Grant-CsConferencingPolicy –Identity "Ken Myer"

Well, we said it was easy. We never said it was very intuitive.

If you’re thinking, “I bet that’s not the way they do it with the beta refresh version of Communications Server,” well, give yourself a gold star: that’s not the way we do it in the beta refresh version of Lync Server. In fact, if you try to unassign a per-user policy the old-fashioned way (by leaving off the –PolicyName parameter) here’s what you’ll get back:

Grant-CsClientPolicy : Please specify PolicyName parameter.

So how do you unassign a per-user policy in the beta refresh version of Lync Server? Like this:

Grant-CsConferencingPolicy –Identity "Ken Myer" –PolicyName $Null

In other words, you use the –PolicyName parameter, but set the parameter value to $Null; in effect, you’re assigning no policy as the per-user policy. It’s a little more intuitive than the old way, and, if nothing else, it at least looks like a complete command. Which, all things considered, is preferable to a command that doesn’t look like a complete command.

New Priority Property Added to the Dial-In Conferencing Cmdlets

You can’t really call it a problem, but one minor issue with dial-in conferencing for the beta version of Lync Server was this: when you created new dial-in conferencing access numbers you couldn’t control the order in which these numbers appeared on the Dial-In Conferencing Settings and PIN Management Web page. Instead, these numbers just showed up in the order they were created:

Like we said, that’s not really a problem. Still, suppose that 1-425-555-1298 is the number you’d prefer your users to use for dial-in conferencing, and 1-425-555-1299 is really sort of the backup number. If that’s the case, then it would definitely be better if 1-425-555-1298 appeared before 1-425-555-1299.

In the beta version of Lync Server there wasn’t much you could do about that. That’s not true in the beta refresh version, however. Now, thanks to the Priority and ReorderedRegion parameters, you can run a command like this one:

Get-CsDialConferencingAccessNumber | Where-Object {$_.DisplayNumber –eq "1-425-555-1298"} | Set-CsDialinConferencingAccessNumber –Priority 0 –ReorderedRegion "Bellevue"

And what’s the point of that command? Well, to begin with, we use the Get-CsDialInConferencingAccessNumber and the Where-Object cmdlets to retrieve the dial-in conferencing access number that has a DisplayNumber equal to 1-425-555-1298. We then pipe that number to Set-CsDialInConferencingAccessNumber and ask that cmdlet to do two things: set the Priority to 0 and the ReorderedRegion to Bellevue. Why do we do that? Well, the Priority property determines a number’s position on the list of dial-in numbers: the lower the number the higher you appear on the list. Computers being computers, the first number on the list has a Priority of 0, the second number on the list has a Priority of 1, and so on. How do we get 1-425-555-1298 to be the first number on the list? You got it: we set its Priority property to 0.

But that’s not all: we also need to specify the region where this change will take effect. (Dial-in numbers can be associated with multiple regions, and each region has its own list of dial-in conferencing numbers.) That’s the purpose of the ReorderedRegion parameter: it lets us tell Set-CsDialInConferencingAccessNumber that we want to make 1-425-555-1298 the first number listed for the Bellevue region.

The net effect of running this command? This (notice that our two dial-in conferencing numbers have swapped positions on the list):

Cool, huh?

Newly-Updated Cmdlet Help

When the beta version of Lync Server was released there was help available for most of the cmdlets but, alas, there was not help available for all of the cmdlets. But, hey, rather than dwell on the past let’s celebrate the present: in the beta refresh version help is available for all the cmdlets. In addition, that help has been cleaned up a bit: at least some of the typos have been fixed, some of the goofy parameter descriptions have been modified, etc., etc.

Note. OK, a quick confession: there might actually be a cmdlet or two that doesn’t have any help; that’s because there were a couple of cmdlets added to the product at the last moment. But, for now, we’ll just pretend those cmdlets don’t exist.

That’s the good news. The bad news? Due to some technical issues that haven’t fully been resolved yet (but will definitely be fixed by the time the product is released) some of these help topics don’t actually show up when you type the Get-Help command. The vast majority of the help topics work just fine, but every now and then you’ll type a command (like Get-Help Set-CsSipDomain) and you won’t get very much help at all. There actually is help available for Set-CsSipDomain; it just doesn’t show up.

So is there a way to work around this problem? Yes. If you got the beta refresh version of Lync Server through the TAP program then just make sure you download all the documentation that accompanies the beta refresh release. In that documentation you’ll find a help file named RTCCmdlets.chm and another named RGSCmdlets.chm. RTCCmdlets.chm contains all the help for the Communications Server cmdlets, except (for reasons we still don’t fully understand) the Response Group cmdlets. Help for those cmdlets can be found in RGSCmdlets.chm. As far as we know, all the help topics in those two files appear just the way they’re supposed to appear.

New Requirements for Simple URL Configurations

Remember Microsoft Office Communications Server 2007 R2? Well, back in those days, meeting URLs (to name one type of URL) tended to look something like this:

https://imdf.litwareinc.com/Join?uri=sip%3Akenmyer%40litwareinc.com%3Bgruu%3Bopaque%3Dapp%3Aconf%3Afocus%3Aid%3A125f95a0b0184dcea706f1a0191202a8\&key=EcznhLh5K5t

Nice, huh? And especially nice when you needed to relay that URL to someone else. By contrast, in Lync Server 2010 a meeting URL might look like this:

https://meet.litwareinc.com/071200

True, it’s nowhere near as fearsome and intimidating. But, come to think of it, that’s the point.

The reason you can provide simple URLs in Lync Server is because of a brand-new feature: simple URLs. We won’t bother explaining the ins and outs of simple URLs in this article; suffice to say that you can use the CsSimpleUrlConfiguration cmdlets to create simple URLs for the following components:

· Meet – Used for online meetings.

· Admin – Used to point administrators towards the Lync Server Control Panel.

· Dialin – Used for dial-in conferencing.

Simple URLs are collected in simple URL configuration settings, settings that can be applied at the site scope as well as the global scope. You could use the New-CsSimpleUrlConfiguration cmdlet to create simple URL configuration settings in the beta version of Lync Server; the only stipulation was that your new settings had to specify a URL for meetings (the Meet component). The stipulations have changed in the beta refresh version of Lync Server. You can still create your own simple URL settings at the site scope; however, that new collection of simple URL settings must meet the following criteria:

· You must have an active meeting URL.

· You must have an active dial-in URL.

· The domain property for the initial dial-in URL must be set to this: *. (Strange, but true!)

In other words, the only way to create a new collection of simple URL configuration settings is to use a series of commands similar to these:

$simpleUrlEntry1 = New-CsSimpleUrlEntry -Url "https://dialin.litwareinc.com"

$simpleUrlEntry2 = New-CsSimpleUrlEntry -Url "https://meet.litwareinc.com"

$simpleURL1 = New-CsSimpleUrl -Component "dialin" -Domain "*" -SimpleUrlEntry $simpleUrlEntry1 -ActiveUrl "https://dialin.litwareinc.com"

$simpleURL2 = New-CsSimpleUrl -Component "meet" -Domain "litwareinc.com" -SimpleUrlEntry $simpleUrlEntry2 -ActiveUrl "https://meet.litwareinc.com"

New-CsSimpleUrlConfiguration -Identity site:Redmond -SimpleUrl @{Add=$simpleUrl1, $simpleUrl2}

As it turns out, these changes were made right before the beta refresh version shipped. Why do you care about that? Well, unfortunately, the changes were also made before the help could be updated; as a result, the help for New-CsSimpleUrlConfiguration isn’t really all that helpful. If you want to create a new collection of simple URL settings, you can use the existing help topic for an explanation of the different parameters. However, you should use the preceding set of commands as an example of how to create a collection of simple URL configuration settings that actually work.

Unless, of course, you’d rather run a command that fails miserably; in that case, use the example in the help topic. Speaking strictly for ourselves, we’re going to use the preceding set of commands. After all, we typically don’t need any examples on how to fail miserably; we’re quite capable of doing that all on our very own.

Newly-Departed: Disconnect-CsUser

OK, to tell you the truth, we can’t remember for sure whether the Disconnect-CsUser cmdlet appeared in the beta version of Lync Server or not; just to be on the safe side, however, we thought we should make it clear that Disconnect-CsUser is definitely not in the beta refresh version. Disconnect-CsUser: gone, and probably forgotten as well.

In case you’re wondering, Disconnect-CsUser provided a way to disable a user account without fully disabling a user account. If you run the Disable-CsUser cmdlet against a user account all the Lync Server attributes applied to that account are wiped clean: the user will no longer have a conferencing policy or a dial plan; will no longer be enabled (or not enabled) for Enterprise Voice; will no longer be assigned to a Registrar pool; etc., etc. When you ran the Disconnect-CsUser cmdlet against a user account the only thing that happened is that the Registrar pool attribute was deleted. The user still had his or her conferencing policy and dial plan; the user was still enabled (or not enabled) for Enterprise Voice; the user still had the same line URI; and so. However, because the user was no longer assigned to a Registrar pool he or she could no longer log on to Communications Server. To re-enable the account, and to keep all the old attribute values intact, all you had to do was use the Move-CsUser cmdlet to move the disconnected user to a new Registrar pool.

What’s wrong with that? Well, nothing really. It’s just that we had the Disable-CsUser cmdlet and the Disconnect-CsUser cmdlet; on top of that, you can also disable user accounts using the Set-CsUser cmdlet. It was a bit confusing, to say the least, to try and figure out which cmdlet to use, and when. In order to lessen this confusion, Disconnect-CsUser has been axed, leaving us with two ways to disable a user account:

· If you want to permanently disable a user account (that is, if you want to wipe out all the Lync Server attributes associated with that account) then run the Disable-CsUser cmdlet. If you later decide to re-enable this account, you’ll have to do so using the Enable-CsUser cmdlet; in addition, you’ll have to re-assign per-user policies to this user; assign them to a Registrar pool; provide them with a new SIP address and line URI; etc., etc.

· If you want to temporarily disable a user account (leaving all the policy assignments and other Lync Server attributes as-is) then run the Set-CsUser cmdlet and set the CsEnabled property to False:

Set-CsUser –Identity "Ken Myer" –CsEnabled $False

When you run this command, Ken Myer will no longer be able to log on to Lync Server. However, all of his Lync Server attribute values (well, all of them except CsEnabled) remain untouched: he still maintains the same SIP address, the same line URI, the same dial plan, the same conferencing policy, the same Registrar pool, etc. To re-enable Ken for Lync Server just flip the switch and set CsEnabled back to True:

Set-CsUser –Identity "Ken Myer" –CsEnabled $True

Child’s play.

New Requirement for the Cmdlets Using the InMemory Parameter

Here’s another change that might actually have been made before beta but, since we can’t remember one way or the other, we thought we should note it.

Note. You might be thinking, "Man, these guys seem so clueless; didn’t they know anything about the beta refresh release?" If that’s what you’re thinking, well, you’re right: we didn’t know anything about the beta refresh release, at least not at the time the beta release came out. As a result, we didn’t really do a particularly fantastic job of tracking changes from beta to beta refresh, at least not down to the nitty-gritty level. Will we do better for the time interval between beta refresh and the next release of the product? Well, we couldn’t really do much worse, could we?

Now, where were we? Oh, right: the InMemory parameter. Well, as you probably know, the InMemory parameter provides a way for you to create a new object that, initially, exists only in memory. For example, the following command creates a new client policy that doesn’t actually get applied to the Redmond site; instead, it simply gets stored in the variable $x:

$x = New-CsClientPolicy –Identity "site:Redmond" –InMemory

So how do you turn that virtual policy into a real policy, a policy applied to the Redmond site? Well, back in the old days, you’d run a command similar to this:

Set-CsClientPolicy $x

That won’t cut it in the beta refresh release, however. Instead, any time you try to turn an in-memory-only object into a real object you need to include the Instance parameter, like so:

Set-CsClientPolicy –Instance $x

Of course, you might have already known that. But if you didn’t, well, now you do know that.

New Report Format: HTML

This is a definitely a change for the better. Many of the Lync Server cmdlets generate a report that lets you know exactly what did (or did not) happen each time the cmdlet runs. In the beta version, that report was saved in XML format. There are a lot of great uses for XML but, to be perfectly honest, reporting isn’t really one of them. No one (or at least no one we know) likes weeding through a document similar to this in order to try to figure out what happened when you ran a cmdlet:

xmlns="urn:schema:Microsoft.Rtc.Management.Deploy.LegacyUserInput.2008" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">

- <EdgeClusters>

- <EdgeCluster AP="true" MR="true" DP="true" Version="OCS2007R2" FederationEnabled="true">

  <LoadBalancer InternalFqdn="w13ap.litwareinc.com" ExternalDPFqdn="w13ap.litwareinc.com" ExternalMRFqdn="w13ap.litwareinc.com" ExternalAPFqdn="w13ap.litwareinc.com" />

  <Machine InternalFqdn="w13ap.litwareinc.com" />

  <DirectorOrEdgeNextHop Fqdn="server1.litwareinc.com" IsDirector="true" />

  <Ports InternalAPPort="5061" InternalDPPort="8057" ExternalDPPort="443" />

  </EdgeCluster>

  </EdgeClusters>

- <RegistrarClusterPorts>

  <RegistrarClusterPort TransportType="mtls" Port="5061" />

  </RegistrarClusterPorts>

With beta refresh, however, reports are now saved in HTML format. That means you get reports that look like this:

You know, now that you mention it, that is a little nicer, isn’t it?

Is That Everything You Need to Know About Windows PowerShell and Beta Refresh?

Well, not necessarily; instead, it’s just everything we could think of, off the top of our heads. But that’s all right; if you have questions or if you run into problems using the beta refresh software just drop us a line: cspshell@microsoft.com. Operators are standing by!