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

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

     

    Here's a quick question for you: what are the nine sweetest words in the English language? As you probably guessed – what's that? Well, now that you mention it, those nine words are pretty sweet, aren't they? Definitely better than the nine words we were thinking. For that matter, so are those nine words. And those. And –

     

    OK, so maybe we didn't exactly come up with the nine sweetest words when we sat down to write this article. But the nine we came up with are still pretty good:

     

    It's time for a new Lync Server PowerShell challenge.

     

    Note. And yes, those nine words would be even sweeter if we replaced Lync Server with double chocolate, wouldn't they?

     

    At any rate, it really is time for a new Lync Server One of These Things is Not Like the Other weekly challenge. (Seems like just a week ago that we had the last weekly challenge, doesn't it?) This week's challenge is a little tricky, but we have faith in you; we're convinced that if anyone can tell us which of these Lync Server PowerShell commands is not like the others, well, it's you, our faithful readers:

     

    Get-CsUser –Identity "sip:kenmyer@litwareinc.com"

    Get-CsUser –Identity "kenmyer@litwareinc.com"

    Get-CsUser –Identity "Ken Myer*"

    Get-CsUser -Identity "litwareinc\kenmyer"

     

     

     

    Challenge 11 Hint

    Challenge 11 Answer

     

    Challenge Home

     

     

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

    You know, the mark of a truly great Lync Server PowerShell challenge is this: everyone who submits an answer gets it right, but everyone who submits an answer also has a different reason for why that's the right answer.

     

    Note. Doesn't that sound like a really mediocre sort of challenge? Well, maybe. On the other hand, we invented the Lync Server PowerShell challenge, so we get to decide what's a great challenge and what's a mediocre challenge. And we've decided that last week's Lync Server PowerShell challenge was a great one.

     

    So there.

     

    As you might recall, last week we presented you with the following set of Lync Server PowerShell parameters and asked you which parameter was not like the others:

     

    Set-CsUCPhoneConfiguration.PhoneLockTimeout

    Set-CsConferencingConfiguration.ContentGracePeriod

    Set-CsAddressBookConfiguration.SynchronizePollingInterval

    New-CSRgsTimeRange.CloseTime

     

    When we put this question together, we decided that New-CsRgsTimeRange.CloseTime was the odd man (parameter) out. Why? Well, all four parameters have something to do with time. Three of those parameters (Set-CsUCPhoneConfiguration.PhoneLockTimeout, Set-CsConferencingConfiguration.ContentGracePeriod, and Set-CsAddressBookConfiguration.SynchronizePollingInterval) are used to set time intervals. For example, if I want Lync Server Phone Edition phones to automatically lock themselves after 10 minutes of inactivity I could use a command similar to this one:

     

    Set-CsUCPhoneConfiguration –Identity global -PhoneLockTimeout "00:10:00"

     

    New-CsRgsTimeRange.CloseTime is different, however. This parameter doesn't set a time interval (such as 10 minutes, 30 minutes, 2 hours and 15 minutes). Instead, this parameter is used to specify an actual time of day, in this case the time of day when a Response Group workflow is no longer open for business. (That is, when all the agents have gone home and there is no one left to answer the phone.) For example, this command sets the closing time for a set of business hours to 1:30 pm (13:30 on a 24-hour clock):

     

    $sundayHours = New-CsRgsTimeRange -Name "Sunday hours" -OpenTime "08:30" -CloseTime "13:30"

     

    Everyone who submitted an answer to last week's challenge also selected New-CsRgsTimeRange.CloseTime; they just didn't always select that parameter for the same reason we did. For example, many people pointed out that CloseTime is the only required parameter in the list; the other three parameters are optional.

     

    Note. Did we realize that when we posted this question? Let's put it this way: we think that the mark of a truly great challenge is one where the challenge organizers have no idea what they're talking about.

     

    Several other people also pointed out that New-CsRgsTimeRange.CloseTime creates an in-memory-only object and can't be used to directly modify a Lync Server setting; that's not the case with the other three parameters, but is another case that we overlooked. Good job, guys.

     

    With any luck, we have another great challenge awaiting you this week; check it out and see. Oh, and a special note this week to Makovec: we would love to fly to Europe and tell the SCCM team that they need to do a better job with their PowerShell support. No doubt the SCCM team will be very excited to have a couple of Lync Server PowerShell blog writers come in and tell them that they're doing everything all wrong.

     

    Thanks to everyone who entered last week's challenge; we'll see you again next week.

     

    Challenge Home

     

  • Haiku #75

    Need a Lync Server

    Reset button? Try CS

    Configuration.

     

    Before we do anything else, we'd like to offer everyone an apology for yesterday's haiku. Apparently some unscrupulous hackers managed to breach security and leave weird, incomprehensible notes like this one, notes that suggest that the author of yesterday's haiku (who is also the author of today's haiku) not only doesn't know what he's talking about, but that he's easily duped as well:

     

    Note from Jean. The actual conversation was more along the lines of "New-CsVoiceRegex is an interesting cmdlet, you should write a haiku about that one." But if the author of today’s haiku, a.k.a. Greg Stemp, wants to take that as a challenge, that’s okay. We got the haiku didn’t we?

     

    Easily duped?!? Easily duped?!? The author of today's haiku plans to write a blistering rebuttal to that insult … just as soon as he finishes whitewashing the fence.

     

    At any rate, we do apologize for these unwanted and unwarranted intrusions into the daily haiku. We hope this does not cause any problems for either one of our devoted readers.

     

    Note. And yes, now that you mention it, hacking the daily haiku is sort of like someone scrawling comments into the margins of a Gutenberg Bible, isn't it?

     

    Sort of.

     

    It's actually a bit ironic that we got hacked, because we thought we had the ideal security system: by writing a daily haiku about Lync Server PowerShell, we figured no one would even read the thing, let alone hack into it. Unfortunately, we were wrong. But don't worry: we'll get to the bottom of this. In fact, we've assigned our best people to the task of tracking down the hacker and bringing him (or her) to justice.

     

    Or at least that's what we would do if we actually had any best people.

     

    As you might expect, the past couple days have been a bit traumatic for those of us here at the Lync Server PowerShell blog. But that's OK; we can handle that. After all, when we're feeling a little stressed out and a little overwhelmed, we do what most people do when they're feeling a little stressed out and a little overwhelmed: we console ourselves by running the Export-CsConfiguration and the Import-CsConfiguration cmdlets.

     

    Note. And then we down a couple bottles of vodka. But it's always cmdlets first, vodka second.

     

    So what's so interesting, and so comforting, about the Export-CsConfiguration and Import-CsConfiguration cmdlets? Well, for one thing, these cmdlets enable you to backup and restore a your Lync Server deployment: when you run Export-CsConfiguration, the cmdlet creates a .ZIP file containing backup data for your Lync Server topology, configuration settings, and policy data. Why do you need that backup data? Well, suppose the computer running your Central Management store blows up. (Or perhaps gets hacked into. Hey, if it can happen to us it can happen to anyone!) In that case, the best (and really the only) way to restore the system, and to get the Central Management store up and running on a new computer, is to use the Move-CsManagementServer cmdlet and the .ZIP file that was created by running Export-CsConfiguration.

     

    Note. If you're trying to plan ahead for potential problems like the Central Management store blowing up (and it's really a good idea to plan ahead for things like that, just in case) you might want to routinely backup your system using Export-CsConfiguration. If you're using Enhanced 9-1-1 (E9-1-1) then you might want to also routinely back up that system by using the Export-CsLisConfiguration cmdlet. Export-CsConfiguration does not back up your E9-1-1 location and configuration data; Export-CsLisConfiguration does.

     

    Of course, by now you're probably wondering how you actually use Export-CsConfiguration. (Well, unless you're still wondering how, and why, someone could hack the daily Lync Server PowerShell haiku.) As it turns out, that's one of the easier cmdlets you could ever choose to run:

     

    Export-CsConfiguration -FileName "C:\Config.zip"

     

    That's it: you just call Export-CsConfiguration and include the FileName parameter followed by the full path to the .ZIP file being created.

     

    Note. Hmmm, maybe we could drink the vodka first after all ….

     

    Now, what about the Import-CsConfiguration cmdlet? Well, Import-CsConfiguration actually has two uses. First, the cmdlet can be used to restore an exported version of the Central Management store. For example, suppose you export the configuration settings, you make a bunch of changes to Lync Server, and then you decide you don't like the changes that you made after all. If you wanted to, you could try to manually undo everything you just did. Alternatively, you could use a command like this to restore a previously-exported copy of your Lync Server settings:

     

    Import-CsConfiguration -FileName "C:\Config.zip"

     

    Note. We should probably point out that this is an all-or-nothing process: you can't restore just the settings for this particular component or just the external access policies that you created. Your entire Lync Server topology and all your Lync Server configuration settings and policy data are backed up, and all of those items are restored.

     

    And no, there isn't an official way to backup and restore individual policies or settings. But we do have an unofficial way to do that.

     

    Import-CsConfiguration is also useful when you're setting up an Edge server, a computer located outside your perimeter network. To help get your Lync Server settings copied to the Edge server, and to help get that computer integrated into the replication system, use Export-CsConfiguration to export your settings to a .ZIP file. Copy that .ZIP file to the Edge server, then use Import-CsConfiguration to import all those settings to the local store on that Edge server. (The local store is the locally-stored copy of the Lync Server settings.) After that's done, the Edge server will automatically begin replicating data with the rest of your servers. To import Lync Server settings to the local store (as opposed to the Central Management store), just tack the LocalStore parameter onto your command, like so:

     

    Import-CsConfiguration -FileName "C:\Config.zip" -LocalStore

     

    Incidentally, one way to test the use of these cmdlets is to do this (which is actually how we tested the use of these cmdlets):

     

    1.    Export the data to a .ZIP file using Export-CsConfiguration.

    2.    Create a new something. We created a new external access policy named TestPolicy.

    3.    Immediately import that .ZIP file using Import-CsConfiguration.

    4.    Check to see if the external access policy TestPolicy still exists; it shouldn't. Why not? Because TestPolicy wasn't included in the exported and imported data.

     

    Something to think about anyway.

     

    That's all we have time for today. But guess what? We've spent a few minutes with Export-CsConfiguration and Import-CsConfiguration and we're already feeling much, much better.

     

    Although we suppose that the two bottles of vodka didn't hurt, either.

     

    See you on Monday.

     

  • Customer Question and Answer

    Several weeks ago the Lync Server PowerShell blog authors presented an instructor-led lab to some of our internal Microsoft customers at the TechReady 12 conference. It turned out that people had quite a few questions about the lab we were walking them through. It occurred to us that many people who are doing this for real might also be interested in those questions, and, more importantly, the answers to those questions. So, actually thinking ahead for once, we kept a list of the questions people were asking us. When we got back to work we wrote a series of articles answering those questions.

     

    Take a look at the full TechReady 12 Q & A to see a list of all the questions with links to the articles that answer those questions.

     

    And be sure to let us know if you have other questions that didn’t get asked during this 90-minute session.

     

    http://blogs.technet.com/b/csps/archive/2011/03/21/tr12faq.aspx

  • Haiku #74

    ^ 1 \d{5} \d + ?

    Is that Klingon or something?

    No, just VoiceRegex.

     

    Today's haiku is the direct result of a challenge issued by the legendary Lync Server PowerShell writer Jean Ross. (Many people consider Jean to be the second-greatest Lync Server PowerShell writer in history.) Yesterday Jean and the author of today's haiku were discussing some of the more obscure cmdlets when New-CsVoiceRegex was mentioned. "New-CsVoiceRegex?" she said. "I'd like to see you write a haiku about that." Needless to say, that sounded like a challenge.

     

    Note. So is the author of today's haiku the type of person who would ever back down from a challenge? You bet he is; he does it all the time. But when he got to work this morning he realized he still had a haiku to write, and so he decided that New-CsVoiceRegex would be as good as anything else.

     

    So there, Jean Ross: take that!

     

    Note from Jean. The actual conversation was more along the lines of “New-CsVoiceRegex is an interesting cmdlet, you should write a haiku about that one.” But if the author of today’s haiku, a.k.a. Greg Stemp, wants to take that as a challenge, that’s okay. We got the haiku didn’t we?

     

    As you might have guessed, the Regex part of New-CsVoiceRegex stands for, well, regex, programming jargon for regular expressions. Regular expressions, which have been around since the 1950s, are used for pattern matching. For example, have you ever typed a command like this from the command prompt:

     

    dir *.ps1

     

    If you have (and of course you have), then you're already familiar with pattern matching. With the command dir *.ps1 you're telling the operating system that you aren't looking for a particular file; instead, you're looking for all the files that meet the specified pattern. The syntax *.ps1 means you're looking for all the files that have any file name (that's what the asterisk is for: it means "anything") and then ends with the file extension .ps1. For example, these files meet that pattern and will be returned by the command:

     

    File1.ps1

    My_script.ps1

    The script that I wrote to return user account information.ps1

    X.ps1

     

    By comparison, these files don't meet the pattern and won't be returned by the command:

     

    File1.ps

    My_script.ps195

    Ps1.txt

    Readme.doc

     

    Regular expressions are really just a fancier way to do pattern matching. For example, suppose we have a variable named $lineUris that contains all the line URIs for all our users.

     

    Note. How could you get all your line URIs into a variable in the first place? Well, that doesn't really matter for now. But you could always try a command like this one:

     

    $lineUris = Get-CsUser | Select-Object LineUri | Where-Object {$_.LineUri –ne ""}

     

    Now that we have these numbers we'd like to know whether we've assigned any line URI where the last five digits fall in the range 30000 through 34999. In other words, has anyone been assigned a line URI like TEL:+120655530010 or TEL:+120655532329?

     

    So how can we answer a question like that? Well, thanks to regular expressions and pattern matching, that's actually pretty easy. This command should do the trick:

     

    $lineUris | Where-Object {$_.LineUri -match "[30000-34999]$"}

     

    We won't go into a detailed explanation of regular expression syntax today (you'll thank us for that later) but "[30000-34999]$" basically says we're looking for any line URI whose last five digits fall into the range 30000 through 34999. We use [30000-34999] to specify the numeric range, and we use the dollar sign character ($) to indicate that the digits in question must occur at the end of the string.

     

    Note. Why? Because we don't want to match a phone number like TEL:+13455551298.

     

    As you can see, there are least two things that are true about regular expressions: 1) they're very powerful; and, 2) they can get pretty complicated. For example, here's an actual regular expression used for some sort of phone number validation:

     

    ^(1\s*[-\/\.]?)?(\((\d{3})\)|(\d{3}))\s*[-\/\.]?\s*(\d{3})\s*[-\/\.]?\s*(\d{4})\s*(([xX]|[eE][xX][tT])\.?\s*(\d+))*$

     

    And yes, that's what we were going to say. But they won't let us publish words like that in the Lync Server PowerShell blog.

     

    Speaking of Lync Server, what do regular expressions have to do with you, the Lync Server administrator? Well, as we've already seen with the line URI example, regular expressions can be a handy tool for data mining. In addition to that, however, Lync Server also uses regular expressions to "normalize" phone numbers. (That is, to take a phone number typed in by a user – e.g., 5551298 – and convert it to a format – for example, +12065550712 – that Lync Server can work with.) As a Lync Server administrator, you're going to have to write voice normalization rules to translate the phone numbers typed in by your users.

     

    Note. You're right: we should have asked you to sit down before we sprung that on you. Sorry.

     

    This, at long last, is where New-CsVoiceRegex comes into play. The New-CsVoiceRegex cmdlet helps you to write regular expressions that can be used in a voice normalization rule. Admittedly, you can't write super-complicated regexes using New-CsVoiceRegex; that's not what it's designed for. But it can help you identify (and match) the more common phone numbers formats that your users are likely to type in.

     

    How can it do that? Well, to begin with, voice normalization requires you to do two things: you need to figure out the kind of phone number you're working with, and you need to transform that phone number into a number that Lync Server can work with. Let's run through a quick example of how New-CsVoiceRegex can help you with this task.

     

    Let's assume your users typically make internal calls by simply dialing someone's extension; for example, if Ken Myer has the phone number 1-206-555-1219 someone calling Ken Myer will probably just enter this number:

     

    51219

     

    How do you know if someone is trying to dial an internal number? Well, you never know that for sure. But it's a pretty good guess that if someone dials a 5-digit number, and that 5 digit number begins with a 5, then they're trying to dial an internal number.

     

    So how can you create a regular expression that can identify internal phone numbers? Here's one way:

     

    $regex = New-CsVoiceRegex –ExactLength 5 –StartsWith 5

     

    All we've done here is call the New-CsVoiceRegex cmdlet and included two parameters: ExactLength, which specifies the exact number of digits we're looking for (5), and StartsWith, which indicates the value of the first digit we're looking for (also a 5). That regular expression is going to match a number like 51219; however, it will not match a number like 5551219 (more than 5 digits) nor will it match a number like 41219 (doesn't start with a 5).

     

    Note. Then what do you do about a number like 5551219? You'll either need to create a more-complicated regular expression or you'll need to create a separate voice normalization rule for matching a 7-digit number that starts with 555:

     

    $regex = New-CsVoiceRegex –ExactLength 7 –StartsWith 555

     

    If we look at the value of the variable $regex we should see this:

     

    Pattern                      Translation

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

    ^(5\d{4})$                    $1

     

    The pattern – (^(5\d{4})$ – is the regular expression we created. (Oh, OK: the regular expression that New-CsVoiceRegex created for us.) The translation – $1 – is the normalized phone number. The value $1 simply means that we're going to use the exact number that the user typed in.

     

    Of course, we don't want to use the exact number that the user typed in; Lync Server doesn't know what do with a phone number like 51219. That means we need to specify how that number should be translated, something we can do in our voice normalization rule, or something we can do using New-CsVoiceRegex. (Well, as long as it's a very simple translation.) For example:

     

    $regex = New-CsVoiceRegex –ExactLength 5 –StartsWith 5 –DigitsToPrepend +120655

     

    As you can see, this time around we've included the DigitsToPrepend parameter and told New-CsVoiceRegex that we want to add this to the front of every phone number that matches the pattern:

     

    +120655

     

    Why? Because that will turn the phone number 51219 into this:

     

    +12065551219

     

    And that's a number that Lync Server can deal with. If we now look at the value of $regex we should see this:

     

    Pattern                      Translation

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

    ^(5\d{4})$                    +120655$1

     

    Notice anything different about the Translation property? That's because we added the DigitsToPrepend parameter to our command.

     

    You may have also noticed that our resulting regular expression is stored in the variable $regex. (At least we hope you noticed that.) If you want use New-CsVoiceRegex that's how you do things: you create a regular expression, you store that regular expression in a variable, and then you use that variable, along with the New-CsVoiceNormalizationRule cmdlet, to create a new voice normalization rule. For example:

     

    $regex = New-CsVoiceRegex –ExactLength 5 –StartsWith 5 –DigitsToPrepend +120655

     

    New-CsVoiceNormalizationRule -Parent SeattleUser -Name SeattleFourDigit -Description "Dialing with internal five-digit extension" -Pattern $regex.Pattern -Translation $regex.Translation

     

    Of course, for better or worse, we don't have time to discuss the New-CsVoiceNormalizationRule cmdlet today; that's something we'll have to do sometime down the road.

     

    Like, say, the next time Jean Ross challenges us to write a haiku.

     

    Note. What's that? Why doesn't Jean Ross just write those haikus herself? You know, we never thought to ask. Why doesn't she just write those haikus herself? Hmmm ….

     

    Note from Jean. I’m busy. Or, to use the most popular catch phrase here at Microsoft, “It’s like a fire drill around here.”