• Haiku #44

    Please hold: your call is –

    Hey, wait: didn't we just do

    This one yesterday?

     

    All of us here at the Lync Server PowerShell blog have been greatly influenced by television, not so much because of the quality of the product (after all, this is the medium that brought us The Bachelor) but because the TV industry has mastered the art of doing less and less work each and every year. (We like that idea.) For example, the summer months used to be known as the "summer rerun season," because that was the only time of year when reruns were shown; from September to June you saw new, original episodes of your favorite shows. Nowadays, the typical TV series shows 20-22 episodes per season, meaning that most of the shows you see during the course of the season are reruns. You work for 20 weeks, and get paid for the whole year.

     

    See why we like TV so much?

     

    But it gets even better. Sometimes you'll see a new episode this week and then, next week, you'll see the very same episode all over again. A rerun after just one week? Of course not. That's not a rerun, that's an "encore presentation." And because an encore is an additional performance put on because of audience demand, that can only mean that people want to see the exact same thing over and over and over again. Which, in turn, means that TV is fully justified in showing you the same thing you just saw a week ago.

     

    That also means that you should consider this an encore presentation of yesterday's haiku. Hey, we just have to give the people what they want, right?

     

    OK, it's not quite that bad. After all, this isn't actually a reprint of yesterday's haiku; instead, we're just covering similar ground. Yesterday we talked about the Set-CsCpsCallParkMusicOnHold cmdlet, which enables you to assign an audio file to be played any time a call is parked. (See yesterday's haiku for more details.) As it turns out, though, there are other Microsoft Lync Server 2010 components that can play audio files, including the Announcement service and the Response Group application. However, these components use a different set of cmdlets to import and configure those audio files. Seeing as how we have yet to come down from that emotional high we got from discussing Set-CsCpsCallParkMusicOnHold, we thought we'd just keep going today and talk about the Import-CsRgsAudioFile cmdlet.

     

    Import-CsRgsAudioFile is the cmdlet used to import and assign audio files used with the Response Group application. As we saw yesterday, the Call Park application handles audio files using a two-step process:

     

    1.    The audio file is imported by using the Get-Content cmdlet.

    2.    The imported audio file is assigned to the Call Park application by using the Set-CsCpsCallParkMusicOnHold cmdlet.

     

    The Response Group application also uses a two-step process when working with audio files, but the two steps are slightly different:

     

    1.    The audio file is imported by using the Import-CsRgsAudioFile cmdlet.

    2.    The imported audio file is assigned to the Response Group application by using … well, it depends on what you actually want to do with that file. But we'll show you a couple of examples before we go.

     

    First, though, we should show you how the Import-CsRgsAudioFile works. It works like this:

     

    $audioFile = Import-CsRgsAudioFile -Identity "service:ApplicationServer:atl-cs-001.litwareinc.com" -FileName "WhileYouWait.wav" -Content (Get-Content C:\Media\WhileYouWait.wav -Encoding byte -ReadCount 0)

     

    As you can see, it's similar to what we saw yesterday, only different.

     

    Note. Sort of like the new Hawaii 5-0 show, which uses the same character names and locations and the old Hawaii 5-0 show (which went off the air in 1980), but otherwise doesn't resemble the old show in the least. So why didn't they just create a new detective show rather than resurrecting (sort of) the old one? That's TV for you.

     

    Incidentally, when we stop doing the daily Lync Server PowerShell haiku (perish the thought!) we intend to immediately start doing a brand-new Lync Server PowerShell haiku, except that it won't have anything to do with Lync Server PowerShell and won't include any haikus. That's the way TV would do it.

     

    Now, where were we? Oh right: it's similar to what we saw yesterday, only different. In this command, we call Import-CsRgsAudioFile and specify the following parameters:

     

    ·         Identity – The Identity of the Application Server that hosts the Response Group application.

    ·         FileName – The actual file name and file extension (e.g., WhileYouWait.wav) of the file being imported.

    ·         Content – A call to the Get-Content cmdlet, which we use to actually import the file. This part of the command looks exactly like what we saw yesterday. In fact, it's the same as step 1 we saw yesterday only embedded within a call to Import-CsRgsAudioFile.

     

    Confusing? Well, yes, a little bit. But that's the way the system works. We can't just call Get-Content and import the audio file into a variable, the way we did yesterday. Instead, we have to call Import-CsRgsAudioFile and then, as part of that call, use Get-Content to import the audio file into a variable. Strange, but true!

     

    Note. Here's another difference: With the Call Park application you can only use .WMA files. The Response Group application is a little more flexible: it accepts either .WMA or .WAV files.

     

    So what do you do with this file after it's been imported? Well, that depends: when it comes to the Response Group application, there are a number of different things you can do with an audio file. For example, you can configure the default music on hold for an instance of the Response Group application:

     

    $audioFile = Import-CsRgsAudioFile -Identity "service:ApplicationServer:atl-cs-001.litwareinc.com" -FileName "WhileYouWait.wav" -Content (Get-Content C:\Media\WhileYouWait.wav -Encoding byte -ReadCount 0)
     
    Set-CsRgsConfiguration -Identity "service:ApplicationServer:atl-cs-001.litwareinc.com" -DefaultMusicOnHoldFile $audioFile

     

    This is pretty easy: you simply call the Set-CsRgsConfiguration cmdlet, and assign the imported file (the variable $audioFile) to the DefaultMusicOnHoldFile parameter.

     

    Here's another example:

     

    $audioFile = Import-CsRgsAudioFile -Identity "service:ApplicationServer:atl-cs-001.litwareinc.com" -FileName "WhileYouWait.wav" -Content (Get-Content C:\Media\WhileYouWait.wav -Encoding byte -ReadCount 0)

     

    $workflow = Get-CsRgsWorkflow -Identity Service:ApplicationServer:atl-cs-001.litwareinc.com -Name "Help Desk"

     

    $workflow.CustomMusicOnHoldFile = $audioFile

    Set-CsRgsWorkflow -Instance $workflow

     

    You're right: that one's not so clean and neat, is it? In this one, we're configuring custom music on hold for an individual workflow. To do that, we start out by importing our audio file; no problem there. However, at this point we can't just call Set-CsRgsWorkflow to assign the audio file as the music on hold file; the CsRgsWorkflow cmdlets don't work that way. Instead, we need to use this line of code to create an object reference to the workflow of interest (Help Desk):

     

    $workflow = Get-CsRgsWorkflow -Identity Service:ApplicationServer:atl-cs-001.litwareinc.com -Name "Help Desk"

     

    After that, we can assign $audioFile to the object reference, and then use Set-CsRgsWorkflow to save those changes to the actual Help Desk workflow:

     

    $workflow.CustomMusicOnHoldFile = $audioFile

    Set-CsRgsWorkflow -Instance $workflow

     

    In other words, we have to make all our changes on a copy of the workflow object, then write those changes back to the real workflow object. Why? That's just the way the Response Group cmdlets work.

     

    Now, we're the first to admit that a command like this one is a bit gnarly looking, to say the least:

     

    $audioFile = Import-CsRgsAudioFile -Identity "service:ApplicationServer:atl-cs-001.litwareinc.com" -FileName "WhileYouWait.wav" -Content (Get-Content C:\Media\WhileYouWait.wav -Encoding byte -ReadCount 0)

     

    If you don't like gnarly looking commands, you can also import the file using this command:

     

    $audioFile = Get-Content -ReadCount 0 -Encoding Byte C:\MediaFiles\WhileYouWait.wav | Import-CsRgsAudioFile -Identity Service:ApplicationServer:atl-cs-001.litwareinc.com -FileName "WhileYouWait.wav"

     

    What's the difference here? Well, the difference is that, instead of using the call to Get-Content as the value for the Content parameter, we're calling Get-Content first, thus retrieving the audio file. We then pipe that audio file object to Import-CsRgsAudioFile. The net result is the same: we end up with an audio file object ($audioFile) that can be used with the Response Group application. It's just a slightly different way of doing things, a way that might be a little cleaner and a little easier to follow.

     

    But that's entirely up to you.

     

    We should also note that you always have to import the audio file, even if you used that same exact file elsewhere. For example, pleased with the way WhileYouWait.wav is working as custom music on hold for the Help desk workflow, you might think, "Hey, I'd like to use that as the custom music on hold for my Customer Support workflow as well." That's fine; just remember that you'll have to go through the entire process, including importing the file that you've already imported:

     

    $audioFile = Import-CsRgsAudioFile -Identity "service:ApplicationServer:atl-cs-001.litwareinc.com" -FileName "WhileYouWait.wav" -Content (Get-Content C:\Media\WhileYouWait.wav -Encoding byte -ReadCount 0)

     

    $workflow = Get-CsRgsWorkflow -Identity Service:ApplicationServer:atl-cs-001.litwareinc.com -Name "Customer Support"

     

    $workflow.CustomMusicOnHoldFile = $audioFile

    Set-CsRgsWorkflow -Instance $workflow

     

    We'd tell you that this is just the way that the Response Group cmdlets work, but you've probably figured that out on your own.

     

    So is that it for importing audio files? You bet it is. Well, except for the Import-CsAnnouncementFile cmdlet. But we probably won't talk about that cmdlet, at least not for a while. Even TV won't show "encore presentations" on back-to-back days.

     

    Well, usually.

     

  • New: Policies Article and Response Group Script

    Today is Thursday, and it's a very special day. Why is it special? Well, if you were a glass-half-full kind of person you wouldn't need to ask -- every day is special. But for the rest of us we need a better reason than that. So today we have one. As a matter of fact, we have several.

     

    First: The sun is shining here in Redmond. In February. On a Thursday. Pretty amazing. (Yes, it would be more amazing if it were shining on a Saturday, but we’re happy to see it at all.)

     

    Second: We have a new article for you today: Getting Rid of Policies You Thought You Already Got Rid Of. (Catchy title, isn’t it? We worked hard on that.) Removing policies can be a little tricky, especially policies that have already been assigned to users. This article tells you everything you need to know about removing user policies.

     

    Third: We have a new script for you: Prepare for Response Group Restore. When you backup your Response Group configuration then attempt to restore it, you’ll receive errors if the Active Directory contacts are still in place. This script shows you those contacts and, if you want, will delete them for you before you restore your configuration.

     

    Oh, and just in case you missed it, Wednesday was pretty spectacular too. We announced our new series by Christopher Wallick, Snippets from the Shell. Admittedly it’s not quite a series yet, since we’ve only just started, but there will be more soon, so check back.

     

    Wow, makes you wonder what Friday will bring, doesn’t it? Or, maybe Monday….

     

  • Haiku #45

    Parlez-vous français?

    Se habla español? Hmmm …

    Well, do you speak SIP?

     

    A few years ago, the author of today's haiku took his mother, his aunt, his sister, and a few assorted groupies and hanger-ons on a vacation to London and Paris.

     

    Note. Do people at Microsoft really make enough money to take all those people on a European vacation? Now that the bills have finally finished rolling in, the author of today's haiku can answer that question: not even close.

     

    After spending a few fun-filled days in London, it was time to head to Paris. Everyone in the group was excited about going to Paris, but apprehensive as well: after all, people in Paris don't speak English. How can you survive in a country where you don't speak the language?

     

    As it turned out, surviving the first day was easy: no matter where they went that first day in seemed like everyone spoke English. On day 2, however, they wandered into a little French restaurant where no one spoke English: not the waitress, not the cook, not even the other patrons. French only.

     

    Note. This particular restaurant also sold only one thing: crepes. Based on that menu alone, it might very well be the best restaurant in the entire world.

     

    And if you've tried their crepes smothered in dark chocolate sauce and whipped cream then you'll know why we feel confident in proclaiming it the best restaurant in the entire world.

     

    At any rate, there was some initial consternation in the group, but not to worry: the author of today's haiku had tried to learn a little French before embarking on the trip (which consisted mainly of learning how to pronounce the phrase "I'm sorry, but I don't speak French"). Somehow or another, though, he managed to get everyone through the meal. Everyone told him what they wanted, he would translate that into pseudo-French for the waitress, then try to translate anything the waitress said back into English. It all seemed to go pretty well, and everyone left the restaurant happy. (Except for the author, who really could have used another one of those crepes.) And, of course, everyone congratulated the author on being able to switch back and forth between French and English, although to this day he still worries that his conversations with the waitress actually sounded like this:

     

    WAITRESS: Are you enjoying your lunch?

    AUTHOR: Yes, everything is delicious. The trombones are porcupine!

    WAITRESS: OK …. Well, let me know if you need anything.

    WAITRESS: Yes, we will; thank you. And trombone to you, too.

     

    The point of all this is that we don't all speak the same language; because of that, it's useful to have someone who can translate from one language to another. That's true when you go to Paris for a vacation. And it's also true when you set up Mediation Servers and PSTN gateways.

     

    Why is it true when you set up Mediation Servers and PSTN gateways? Well, without going into a lot of detail, when you try to make a call from your internal Enterprise Voice network to the external PSTN network, that call passes through a PSTN gateway. Suppose that call fails. In that case, the PSTN gateway reports an ISDN User Part (ISUP) cause code. For example, maybe the gateway issues the ISUP cause code 4915 meaning, "The call could not be completed because the gateway is currently on fire." (Note: As far as we know, that's not a real ISUP cause code.)

     

    So what's wrong with that? Nothing; that's what gateways are supposed to do when a call fails. However, Lync Server doesn't understand ISUP cause codes; instead, Lync Server works with SIP response codes. Consequently, when a Mediation Server trunking peer receives an ISUP cause code, it converts that code to a SIP response code; that SIP response code is then sent to the Mediation Server itself. From there, Lync Server uses these response codes to make its outbound routing decisions. For example, a malfunctioning gateway might automatically be assigned a "less-preferred" status; this minimizes the use of the malfunctioning gateway, and thus maximizes the chance of a call being successfully completed.

     

    So what's wrong with that? Nothing, as long as the gateway uses the same ISUP cause code to SIP response code mapping that Lync Server uses. But take our hypothetical example. The gateway just sent cause code 4915, which says, "Help, I'm on fire!" But suppose that Lync Server converts cause code 4915 to a SIP response code (say, 7811) that says, "No problems here. And I'm definitely not on fire." In this case, cause code 4915 should have been translated to another pretend SIP response code 2424. Because it wasn't, Lync Server assumes that the gateway is working properly and continues to route calls in that direction, calls that are doomed to fail.

     

    That's what we said: trombone!

     

    Obviously what's needed here is a translator: we need to take the cause code 4915 reported by the gateway and convert it to its SIP response code equivalent (2424). That's where the CsSipResponseCodeTranslationRule cmdlets (Get-CsSipResponseCodeTranslationRule, New-CsSipResponseCodeTranslationRule, Remove-CsSipResponseCodeTranslationRule, and Set-CsSipResponseCodeTranslationRule ) come in.

     

    As the name implies (sort of), the CsSipResponseCodeTranslationRule cmdlets enable you to create translation rules: rules that can take a cause code like 4915 and convert it to the corresponding SIP response code (2424). These rules can be configured at the global scope, the site scope, or the service scope (that is, on the PSTN gateway itself). Is that useful? You bet it is. For example, suppose you have one gateway that doesn't support the Lync Server SIP response codes. In that case, you can configure translation rules for that gateway only. Or suppose none of the gateways in your Dublin site support the Lync Server SIP response codes. That's fine: set up a series of translation rules for the Dublin site. Etc., etc.

     

    So how hard is it to create one of these translation rules? As you can see, it's not hard at all:

     

    New-CsSipResponseCodeTranslationRule -Identity "PstnGateway:192.168.0.240/Rule503" -ReceivedISUPCauseCode 34 -TranslatedResponseCode 503

     

    In this command, we're creating a translation rule for the PSTN gateway 192.168.0.240; this rule is given the Name Rule503.

     

    Note. The rule's Identity consists of the scope where the rule is to be applied plus the rule name. What if we wanted to assign Rule503 to the Dublin site? Then our command might look like this:

     

    New-CsSipResponseCodeTranslationRule -Identity "site:Dublin/Rule503" -ReceivedISUPCauseCode 34 -TranslatedResponseCode 503

     

     

    In this case, we know that the gateway reports an ISUP cause code of 34 that, to the gateway, means "No circuit/channel is available." That cause code should be converted to the SIP response code 503, which would tell Lync Server to bypass the gateway (which is unavailable anyway) and find another way to route calls. By default, though, cause code 34 is not converted to response code 503. Therefore, we need to "manually" tell Lync Server that any time a gateway in the Dublin site reports a cause code of 34 then that value should be converted to SIP response code 503.

     

    Make sense? It's like this: if you go to a French restaurant and your mom wants an apple crepe, you need to translate the English word apple into its French equivalent: pomme. It's the exact same thing when you're working with PSTN gateways.

     

    Except that nobody ends up getting crepes.

     

    And, of course, you can use the other CsSipResponseCodeTranslationRule cmdlets to manage these translation rules. Want to see all the rules created for the Dublin site? No problem:

     

    Get-CsSipResponseCodeTranslationRule –Identity "site:Dublin"

     

    Or maybe you've installed new gateways and no longer need translation rules in the Dublin site. Again, no problem:

     

    Remove-CsSipResponseCodeTranslationRule –Identity "site:Dublin"

     

    Etc, etc.

     

    That's all we have for today. It's Friday; have a nice trombone everyone.

     

     

  • One of These Things is Not Like the Others: Challenge 5

    One of These Things is Not Like the Others: Challenge 5

     

    No doubt you've spent a lot of time wondering how we go about picking the weekly Lync Server 2010 PowerShell Challenge. Because of that, we thought we'd give you a little insight into the process. Awhile back we came up with about 20 or so questions we thought might make reasonably good challenges. Each week we carefully analyze the Lync Server discussion forums; convene several focus groups to talk about the most pressing Lync Server issues of the day, and then run a number of simulated challenges through a mainframe computer; using a patented algorithm that helps us select the most relevant challenge for that particular date and time. And then, when that's all done, Jean Ross says, "Just go with the third question in the list," and we end up going with the third question in the list.

     

    So here it, the third question in the list: Which one of these Microsoft Lync Server 2010 cmdlet parameters is not like the others?

     

    Set-CsImFilterConfiguration.Prefixes

    Set-CsVoicePolicy.PstnUsages

    Set-CsSimpleUrlConfiguration.SimpleUrl

    Set-CsSite.DisplayName

     

     

     

    Challenge 5 Hint

    Challenge 5 Answer

     

    Challenge Home

     

     

  • One of These Things is Not Like the Others: Challenge 4 Answer

    One of These Things is Not Like the Others: Challenge 4

     

    A tip of the cap this week to ewright19: we barely had time to post the challenge before she had sent in her answer. Is it legal to submit an answer to the challenge just minutes after it's been posted? You bet it is. In fact, we encourage people to send their answers in before we post the challenge. If everyone would send their answers in now, we wouldn't have to bother trying to come up with a new question this week. That would make our lives much, much easier.

     

    Which, we assume, is something very important to all of you.

     

    So what question was ewright19 so quick to answer? This one: which of the following Microsoft Lync Server 2010 PowerShell cmdlets is not like the others?

     

    Move-CsLegacyUser

    Move-CsUser

    Merge-CsLegacyTopology

    Move-CsRgsConfiguration

     

    The answer that most people gave is the same answer we had in mind: Move-CsUser. Why? Well, in the words of Aleksandar N.:

     

    Other three cmdlets migrate things from an earlier version of Office Communications Server to Lync Server 2010. Move-CsUser is designed to move users from one Lync Server to another Lync Server pool, or to move a user from a Lync Server pool to an Office Communications Server pool.

     

    So is he right? Are you kidding: Aleksandar is always right! The Move-CsLegacyUser cmdlet provides a way for you to move one or more Office Communications Server (or Office Communications Server 2007 R2) user accounts to Lync Server. (It's a pretty cool cmdlet, by the way. For example, it lets you decide whether you want to just move the user account itself, or whether you'd also like to migrate things like the user's dial plan, voice policy, conferencing policy, etc.) Merge-CsLegacyTopology migrates such things as the trusted service entries and topology information for domains, user services, Registrars, Mediation Servers, and Edge Servers from Office Communications Server to Lync Server. (That's important for actually switching from Office Communications Server to Lync Server. However, it's also useful if you want to run both Office Communications Server and Lync Server, the "coexistence" scenario.) And then there's Move-CsRgsConfiguration, everyone's favorite cmdlet for migrating your Office Communications Server Response Group settings to Lync Server.

     

    So who's the odd man out (or, more correctly, the odd cmdlet out) in this challenge? It pretty much has to be Move-CsUser. As we've seen, the other three cmdlets can be used to move people from Office Communications Server to Lync Server. By contrast, Move-CsUser provides a way for you to move a user from Lync Server back to Office Communications Server. If you're in a coexistence scenario and, somehow or another, you migrated a user account that shouldn't have been migrated yet, well, Move-CsUser provides a way for you to return that user to Office Communications Server.

     

    And, of course, the cmdlet can also be used to move users from one Lync Server pool to another.

     

    With one exception, everyone who submitted an answer for Challenge 4 came up with Move-CsUser. The one exception was Johann D., who pointed out that Move-CsRgsConfiguration is the only one of the four cmdlets that does not support the WhatIf and Confirm parameters. To tell you the truth, we didn't even realize that, but he's right.

     

    And yes, it is hard to believe something could have slipped past our eagle eyes, isn't it?

     

    That's it for Challenge 4. By the time you read this, Challenge 5 will already be up and running.

     

    And, no doubt, ewright19 will have already submitted her answer for it.

     

     

    Challenge Home