• Lync PowerShell Challenge Update

    We got several entries to the first challenge. But we know there are a lot more of you out there who have been thinking "You know, I'd really like to enter, but I'm just not confident I know the answer." You were thinking that, right? That's what we thought. So, to help you out, we've published a hint to Challenge 1. As we mentioned in the rules, you aren't eligible for as many points now, but don't let that stop you. This challenge will continue for several weeks so you have plenty of opportunities to make up ground. So give this one a try and start racking up those points now!

  • Haiku #29

    If there's a meeting

    And no one can find it, is

    It a real meeting?

     

    There's no doubt that the author of today's haiku has a fondness for Zen koans; he's even used a few of them in a previous article on this site. But, then again, what's not to like about koans and riddles, especially those that seem to have an obvious answer? For example, everyone knows this one: if a tree falls in the forest and no one is around to hear it, does it make a sound? Everyone who hears this riddle immediately dismisses it: of course it makes a sound.

     

    Duh.

     

    And yet, how do you know it makes a sound if no one is there to hear it? Sure, it probably makes a sound, but probably is not the same thing as definitely. (We looked that up to make sure: they aren't the same.) And what about Heisenberg's uncertainty principle, which states that the very act of trying to observe or measure something changes the behavior of that something? In other words, maybe a falling tree doesn't make a sound unless someone is there to hear it. At that point, the simple presence of an observer changes the behavior of the tree and causes it to make a sound.

     

    Note. Impossible, you say? Well, then you've never had children. Everyone knows that the first thing a kid who falls down does is look around to see if anyone saw their tragic accident. If they don't see anyone they won't cry. But if they do see someone, they cry. The simple presence of an observer changes their behavior and causes them to make a sound!

     

    And yes, we're pretty sure that proves our point. We just aren't totally sure what our point actually is.

     

    Oh, and what about solipsism, the belief that nothing exists except you and the things in your mind? (Not that the authors of the Lync Server PowerShell blog buy this theory; it's obvious that no solipsist has ever tried driving in Seattle traffic at 5:00 PM on a Friday.) And what about – what's that? What about Microsoft Lync Server 2010? What about Windows PowerShell? Beats us, what do those things have to do with today's haiku?

     

    Oh, yeah; good point. With that in mind, let's see what we can do to relate today's haiku to Lync Server.

     

    And yes, that is going to be a challenge.

     

    To begin with, if there was a weakness in Office Communications Server 2007 R2 (and note that we said if) it would have to be meeting URLs; any time you scheduled a meeting in OCS 2007 R2 that meeting would be given a URL similar to this:

     

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

     

    If you've ever wondered why you don't see many tattoos of Office Communications Server 2007 R2 meeting URLs, well, now you know.

     

    But it wasn't just the tattoo industry that found these URLs to be a pain in the … uh, to be a pain. Long, ungainly URLs like that aren't always easy to copy and paste into an email or a Web browser. And forget about reading something like that over the phone; the meeting would be over long before you finished reciting the URL.

     

    Fortunately, that doesn't have to be the case in Lync Server 2010. In Lync Server, you have the option of using "simple URLs." With a simple URL, that same meeting URL might look like this:

     

    https://meet.litwareinc.com/kenmyer/071200

     

    As you can see, Lync Server URLs are, well, simpler than the URLs used in Office Communications Server 2007 R2. And that doesn't just mean meeting URLs; you can also configure simple URLs for the dial-in conferencing Web page and for administrators to use when firing up the Lync Server Control Panel. All in all, pretty cool, if we do say so ourselves.

     

    We can't provide you with detailed instructions here on how to configure Lync Server in order to get simple URLs to work; suffice to say that it: 1) involves doing such things as creating DNS records for each URL; configuring reverse proxy rules for external access; and adding the simple URLs to the your Front End Server certificates; and, 2) is covered in more detail in the Lync Server Planning Guide. What we can do, however, is point out that, once you're set up to use simple URLs you can then manage those URLs by using the CsSimpleUrlConfiguration cmdlets: Get-CsSimpleUrlConfiguration; New-CsSimpleUrlConfiguration; Remove-CsSimpleUrlConfiguration; and Set-CsSimpleUrlConfiguration.

     

    Note. We should probably note that simple URL configurations represent a collection of simple URLs. For example, if you have simple URLs for meetings, dial-in conferencing, and the Lync Server Control Panel, those three URLs would be collectively referred to, and managed as, a simple URL configuration.

     

    So how do you go about managing these simple URL collections? Well, suppose you want to review all the simple URLs currently in use in your organization. (We might mention that you can use one global collection of simple URLs or you can configure different sets of simple URLs for your Lync Server sites.) Reviewing all your simple URLs isn't very hard; in fact, this command will do the trick:

     

    Get-CsSimpleUrlConfiguration

     

    Here's another one. You say you want to delete the simple URLs assigned to the Redmond site? Okey-doke:

     

    Remove-CsSimpleUrlConfiguration –Identity "site:Redmond"

     

    Alternatively, you can leave the collection in place but remove all the simple URLs included in that collection:

     

    Set-CsSimpleUrlConfiguration -Identity "site:Redmond" -SimpleUrl $Null

     

    Note. Good question: if a simple URL collection doesn't have any simple URLs in it, is it really a simple URL collection? We're surprised the Zen koan writers didn't think of that one.

     

    Now, admittedly, things can get a bit more complicated if you want to do something like change the simple URL for meetings, or maybe add a new simple URL for dial-in conferencing. For that, we recommend that you check out the help topics for the CsSimpleUrlConfiguration cmdlets.

     

    Note. Yes, for most technical questions related to Lync Server you should first turn to a haiku in order to get help. This is one of those rare exceptions where you might want to start with the actual help itself, and only then turn a haiku.

     

    At any rate, that's the meaning behind today's haiku: meetings used to be really hard to find, and many people would say that a meeting that no one could actually find isn't really a meeting after all. Personally, we'd say that a meeting that no one could actually find would be fantastic. But, then again, we're not really meeting people.

     

     

     

  • Determine Whether or Not a Number has Been Assigned to a Call Park Orbit

    When you work at Microsoft you often find yourself involved in truly fascinating discussions. For example, just the other day a couple of us were sitting around talking about the call park service when someone posed this question: does the Get-CsCallParkOrbit cmdlet provide an easy way for you to determine whether or not a given number has been assigned to a call park orbit? For example, take number 7452. Is that number assigned to a call park orbit, or not assigned to a call park orbit? How can you tell?

     

    Note. Well, we thought it was a truly fascinating discussion.

     

    As it turns out, the answer to that question is no, Get-CsCallParkOrbit does not provide an easy way to determine whether or not a given number has been assigned to a call park orbit. When you create a new call park orbit you don't assign individual numbers to that orbit; instead, you assign a range of numbers (for example, 7319 through 7428) to that orbit. So has 7452 been assigned to a call park orbit? Well, the only way to determine that is to look at all the call park orbits you've created and check the values of the NumberRangeStart and the NumberRangeEnd properties and see if the number in question (7452) can be found in any of those call park orbit ranges.

     

    That's what we thought, too: bummer.

     

    But you know what they say: if life hands you lemons, then make a Windows PowerShell script that can determine whether or not a number has been assigned to a call park orbit. And that's exactly what we did:

     

    $cpnumber = $args[0]

     

    $orbits = Get-CsCallParkOrbit

     

    foreach ($cpo in $orbits)

        {

         if ($cpnumber -ge $cpo.NumberRangeStart -and $cpnumber -le $cpo.NumberRangeEnd)

             {

                 $counter = 1

                 "The call park number $cpnumber is assigned to the " + $cpo.Identity + " call park orbit."

             }

        }

     

    if ($counter -ne 1)

        {

            "The call park number $cpnumber is not assigned to a call park orbit."

        }

     

    This is a pretty simple little script (for example, it doesn't include any sort of error handling), but it seems to do the job. And just how does it do the job? Well, the script starts off by taking the first argument passed to it and storing that value in a variable named $cpnumber. That means that you need to include the call park number as a command line argument when starting the script. For example, if our script is named C:\Scripts\NumberChecker.ps1 and we want to see if 7452 has been assigned to a call park orbit then we need to use this command to start the script:

     

    C:\Scripts\NumberChecker.ps1 7452

     

    If you leave off the number the script will still run, but it will simply tell you that no completely blank number has been assigned to a call park orbit.

     

    Which you probably could have figured out for yourself without having to run the script.

     

    After assigning the command-line argument to $cpnumber, we next use Get-CsCallParkOrbit to retrieve a collection of all the call park orbits configured for use in our organization; this information gets stashed in a variable named $orbits. We then use this line of code to set up a foreach loop that loops through each call park orbit stored in $orbits:

     

    foreach ($cpo in $orbits)

     

    This is where the fun begins. (Although we like to think that things have already been pretty fun.) The first thing we do inside our foreach loop is check to see if the number ($cpnumber) is greater than or equal to the NumberRangeStart value for the first call park orbit and if the number is less than or equal to the value of the NumberRangeEnd property for that same orbit:

     

    if ($cpnumber -ge $cpo.NumberRangeStart -and $cpnumber -le $cpo.NumberRangeEnd)

     

    What does that mean? Well, let's say our call park orbit includes these property values:

     

    NumberRangeStart: 7400

    NumberRangeEnd:   7499

     

    The number we're interested in is 7452. Is the value 7452 greater than or equal to (-ge) 7400? You bet it is; that means 7452 has met the first criterion. Now, is 7452 less than or equal to (-le) 7499? Yep; that means 7452 has met both our criteria. And that can only mean one thing: 7452 has been assigned to a call park orbit.

     

    At that point we run the following two lines of code:

     

    $counter = 1

    "The call park number $cpnumber is assigned to the " + $cpo.Identity + " call park orbit."

     

    In the first line, we set the value of a variable named $counter to 1; we'll explain why we do that in just a second. In the second line, we simply echo back the fact that the number has been assigned to a call park orbit, as well as reporting back the Identity ($cpo.Identity) of that orbit.

     

    And then we loop around and repeat the process for the next call park orbit in the collection.

     

    And what happens if we have a number – say, 9993 – which isn't assigned to a call park orbit? That's fine: in that case, the variable $counter will never get set to 1, and we'll never execute the line of code that says that the number has been assigned to a call park orbit. Instead, as soon as we exit our foreach loop we'll encounter this line of code:

     

    if ($counter -ne 1)

     

    Here we're simply checking to see if $counter is not equal to (-ne) 1. If the number has not been assigned to a call park orbit then this will be true: $counter will not be equal to 1. Therefore, we then run this line of code to report the fact that the number in question is not assigned to a call park orbit:

     

    "The call park number $cpnumber is not assigned to a call park orbit."

     

    Didn't we tell you that this was truly fascinating?

  • News: Call Park Orbit Script

    A new script has been added to the Lync Server PowerShell Scripts repository. This new script, cleverly titled Determine Whether or Not a Number has Been Assigned to a Call Park Orbit, will accept a number as input and will determine whether that number is within the range of any call park orbits defined within a Lync Server deployment. (See why we thought the title was so clever?) As with all the scripts in this repository, copy it and use it as is or customize it to suit your needs.

  • Haiku # 30

    Oh, you beautiful

    Doll. Oh, you must be joking.

    OU permission.

     

    Before we launch into today's article we thought we should mention that time is running out in order to enter the first-ever Lync Server PowerShell One of These Things is Not Like the Others Challenge. Do you have to enter the Lync Server PowerShell One of These Things is Not Like the Others Challenge? Well, unfortunately for us, Microsoft's legal department repeatedly insists that you don't. On the other hand, picture this: it's several years in the future, and you're sitting around the breakfast table with your darling daughter. "Mommy," says your pride-and-joy, "How did you do in the first-ever Lync Server PowerShell One of These Things is Not Like the Others Challenge?" At that point, will you really be able to look your daughter in the eye and admit that you didn't even bother to enter the first-ever Lync Server PowerShell One of These Things is Not Like the Others Challenge?

     

    We didn't think so.

     

    Fortunately, time is still on your side: we'll continue to accept entries until 9:00 AM Pacific Standard Time on Monday, January 24, 2011. And yes, that looks like you have lots of time to get your entry in. On the other hand, there are people who believe that Judgment Day will arrive on May 21, 2011. What if they're off by a couple months and Judgment Day comes this weekend? Picture this scenario: you're standing in front of St. Peter and he says, "OK, this is just a formality, I simply need to verify your score on the first-ever Lync Server PowerShell One of These Things is Not Like the Others Challenge -- oh, dear. It appears we have a problem here …."

     

    If that happens to you, those of us here at the Lync Server PowerShell blog will not be held responsible. After all, we warned you.

     

    For now, however, let's focus on today's haiku. When you install Microsoft Lync Server 2010, one of the first things you do (or, to be more precise, one of the first things Setup does) is prepare your domain for the installation of the software; that's a process that includes such things as extending the Active Directory schema to allow for the addition of attributes specific to Lync Server as well as assigning the required Access Control Entries to the universal groups needed for managing and operating Lync Server. As a general rule, you don't have to do anything when it comes to domain preparation: you just sit back and wait for Setup to finish.

     

    As we all know, however, general rules are made to be broken. If you have disabled permission inheritance on Active Directory then Setup will not be able to give the RTCUniversalUserAdmins group the permissions needed to manage users, computers, contacts, application contacts, and InetOrg persons. Domain administrators will still be able to manage these entities, but Lync Server admins won't.

     

    Note. Is that a problem? Well, we're not exactly experts when it comes to Lync Server administration. But we do believe you're better off having admins who can do administrative tasks than admins who can't do administrative tasks.

     

    So what are you supposed to do if you find yourself in this situation? For that matter, how do you even know if you're in this situation? Listen, don't worry about that: that's what the CsOUPermission cmdlets (Grant-CsOUPermission, Revoke-CsOUPermission, and Test-CsOUPermission) are for.

     

    To begin with, if you aren't sure whether or not the proper permissions have been granted on a given OU you can verify that by using the Test-CsOUPermission cmdlet. All you have to do is run a command similar to this one:

     

    Test-CsOUPermission –OU "ou=Redmond,dc=litwareinc,dc=com" –ObjectType "user", "contact", "inetOrgPerson"

     

    As you can see, all we're doing here is checking to see if permissions exist for managing users, contacts, and inetOrgPersons. (The inetOrgPerson class is very similar to the user class, and is often used when you migrate to Active Directory from some other directory service.) Test-CsOUPermission will report back True if the required permissions are there or report back False if the required permissions are not there.

     

    And yes, that is pretty easy, isn't it?

     

    And what if Test-CsOUPermission does report back False? No problem; you can simply apply the correct permissions to the OU by running the Grant-CsOUPermission cmdlet:

     

    Grant-CsOUPermission –OU "ou=Redmond,dc=litwareinc,dc=com" –ObjectType "user", "contact", "inetOrgPerson"

     

    Note that Grant-CsOUPermission gives the necessary permissions only to the security groups who would typically be given those permissions when you run Setup. You can’t use this cmdlet to grant permissions to an arbitrary user or group. If you want that user or group to have user management permissions then simply add that user (or group) to the RTCUniversalUserAdmins group.

     

    Oh, one more thing we should mention: when we set up the first-ever One of These Things is Not Like the Others Challenge, we accidentally configured the thing for "chain letter mode." That means that, if you fail to enter the challenge, and thus break the chain, you'll endure 10 years of bad luck. Is it really true that breaking the challenge chain will result in 10 years of bad luck? Let's put it this way: 10 years ago, the author of today's haiku broke a challenge chain. Recently, he received his official award for 10 years of service at Microsoft. Coincidence? Maybe. But, then again ….