• New: How to Undo That Thing You Now Wish You Had Never Done in the First Place

    Here’s an article that shows you a simple way to use Windows PowerShell to backup and restore parts of your Lync Server 2010 implementation. “How to Undo That Thing You Now Wish You Had Never Done in the First Place” explains how to do this with client policies, but once you know how it works with client policies you can most likely make it work with any kind of policies. Or for just about any configuration for that matter.

     

    Sweet dreams.

     

    http://blogs.technet.com/b/csps/archive/2011/02/28/howtobackuppolicies.aspx

     

     

  • How to Undo That Thing You Now Wish You Had Never Done in the First Place

    Although we can't guarantee this, we can pretty much guarantee this: once you've switched to Microsoft Lync Server 2010 you'll never have nightmares again. Or, at the very least, you'll never have nightmares about Microsoft Lync Server again. Ever.

     

    Note. A strong statement? Perhaps. On the other hand, Sigmund Freud is universally acknowledged as history's foremost authority on dream studies and dream interpretation. Before writing this article, we carefully read everything Freud ever wrote. Do you know how many references to Lync Server nightmares we found in the collected works of Sigmund Freud? That's right: zero.

     

    Of course, even as you're sitting back reading this article you can probably think of at least one or two potential Lync Server nightmare scenarios. For example, consider this. Your organization has 105 users who have been enabled for Lync Server. In turn, those users have been assigned one of 3 different client policies; the breakdown of client policy assignments looks something like this:

     

    Policy

    No. of Users Assigned This Policy

    ClientPolicy1

    21

    ClientPolicy2

    13

    ClientPolicy3

    71

     

    Note. What's that? You say you'd like to able to generate a table similar to this? No problem:

     

    Get-CsUser | Group-Object ClientPolicy | Select-Object Name Count | Format-Table -Autosize

     

    But we digress. We also need to note that there's a reason why a user has been assigned a particular policy. Actually, there could be a lot of reasons why a user has been assigned a particular policy. Maybe he or she belongs to a specified security group, maybe he or she has a specific job title, maybe her or she works in a specified department and in a specific city. For our purposes, it doesn't really matter why a user has been assigned a specific policy. What does matter is that the whole thing is complicated, and you can't simply assume that all the users in a given department have the same client policy. It just doesn't work that way.

     

    With us so far? OK, let's now assume that there's been a change in management, and your new manager has decided that it's silly to have all these different client policies: he wants one policy to be assigned to all users.

     

    Note. Yes, typically we would say "he or she wants …." For some reason, though, any time a crazy decision like this gets made we assume it must be a he and not a she.

     

    So is the nightmare scenario the fact that you have to assign the same client policy to all your Lync Server-enabled users? Nope; that's not a nightmare scenario, not by a long shot. In fact, all that takes is one little PowerShell command:

     

    Get-CsUser | Grant-CsClientPolicy –PolicyName "LitwareincClientPolicy"

     

    Instead, here's the nightmare scenario: no sooner do you make this change then your help desk is deluged with complaints. As it turns out, one policy doesn't work in your organization: different users need different capabilities, and now, by taking those capabilities away, you're preventing people from being able to do their jobs. At that point, your manager turns to you and says, "Well, there's only one thing we can do now: you'll just have to put things back the way they used to be. You need to reassign each person the client policy they had before we assigned them all the LitwareincClientPolicy policy."

     

    So is that going to be a problem? No; that's going to be a nightmare. For better or worse, Lync Server doesn't have any sort of undo feature when it comes to most administrative tasks; for example, there's no way to undo the bulk assignment of policies. Furthermore, Lync Server doesn't keep a history of any kind: you can' just thumb through a list of all the client policies that have ever been assigned to a user and then restore one of those policies. Granted, if you've backed up Active Directory (which is where user data is stored) you could theoretically restore the overwritten data; however, in that case all the other changes made to Active Directory since the time you assigned the LitwareincClientPolicy policy would be lost.

     

    Uh-oh.

     

    So doesn't this mean that you should start having nightmares about Microsoft Lync Server 2010? Believe it or not, the answer is no. Admittedly, Lync Server doesn't have a built-in undo function for administrative tasks. However, if you're willing to write a couple of simple Windows PowerShell scripts, you can create your own undo function, at least for many of the things you'll do in Lync Server.

     

    Like, say, bulk assignment of client policies. In the scenario we just described, the problem isn't that we did bulk assignment of client policies; instead, the problem is that, if anything went wrong with that bulk assignment there was no easy way to put things back the way they used to be. Why is there no easy way to put things back the way they used to be? You got it: because there's no easy way of knowing how things used to be. That's why we decided to assign client policies using the following script:

     

    $backupData = (Get-CsUser | Select-Object Identity,ClientPolicy)

    $backupData | Export-Csv –Path "C:\Backup\ClientPolicies.csv" –NoTypeInformation

     

    foreach ($user in $backupData)

        {Grant-CsClientPolicy –Identity $user.Identity –PolicyName "LitwareincClientPolicy"

        }

     

    Nice, huh? Except for one thing: what does this script actually do? Well, in the first line, we use the Get-CsUser cmdlet to retrieve information about all the users who have been enabled for Lync Server. We then pipe that data to the Select-Object cmdlet, which grabs the values for just the Identity and the ClientPolicy properties. (Why just those two property values? Because those are the only two property values we care about.) That filtered data – Identity and ClientPolicy – is then stored in a variable named $backupData.

     

    In the second line, we then take the variable $backupData and pipe it to the Export-Csv cmdlet, which creates a comma-separated values file at C:\Backup\ClientPolicies.csv. That file is going to look something like this:

     

    "Identity","ClientPolicy"

    "CN=adelaney,OU=Redmond,DC=litwareinc,DC=com","ClientPolicy1"

    "CN=aglagdkikh,OU=Redmond,DC=litwareinc,DC=com","ClientPolicy3"

    "CN=aolecka,OU=Redmond,DC=litwareinc,DC=com","ClientPolicy2"

     

    Etc., etc. In other words, it's the Identity of each of our Lync Enabled-users along with the name of the client policy that's currently assigned to them.

     

    Note. Good question: what is the NoTypeInformation parameter for? Well, without it, Export-Csv would give us a text file that looked like this:

     

    #TYPE System.Management.Automation.PSCustomObject

    "Identity","ClientPolicy"

    "CN=adelaney,OU=Redmond,DC=litwareinc,DC=com","ClientPolicy1"

    "CN=aglagdkikh,OU=Redmond,DC=litwareinc,DC=com","ClientPolicy3"

    "CN=aolecka,OU=Redmond,DC=litwareinc,DC=com","ClientPolicy2"

     

    We don't have any use for that first line of type-related data, so we tacked on the NoTypeInformation parameter to prevent Export-Csv from saving that line of data in the first place.

     

    When Export-Csv finishes running, we'll have a text file that contains the names of all our users and the name of the client policy (if any) that was assigned to each one: that is, a snapshot of our client policy picture before we did the bulk update. And speaking of the bulk update, that's what we do in the final block of code:

     

    foreach ($user in $backupData)

        {Grant-CsClientPolicy –Identity $user.Identity –PolicyName "LitwareincClientPolicy"

        }

     

    Nothing fancy there: we've just set up a foreach loop to loop through each user account stored in $backupData and assign the client policy LitwareincClientPolicy to each account. As soon as we're done with that our client policy breakdown will look like this:

     

    Policy

    No. of Users Assigned This Policy

    LitwareincClientPolicy

    105

     

    Where are our other per-user client policies, like ClientPolicy1, ClientPolicy2, and ClientPolicy3? That's easy: they don't show up in the report because they are no longer assigned to anyone. Per our marching orders, all of our users have been assigned LitwareincClientPolicy instead.

     

    OK, so suppose that was a mistake, suppose we now wish we hadn't assigned everyone the same client policy after all? That's OK; it's definitely nothing to lose sleep over. Don't forget that, before we did our bulk update, we took a snapshot of the way things used to be. Assuming we didn't throw away ClientPolicies.csv (hint: don't throw away ClientPolicies.csv) we can undo our bulk policy assignment simply by running this script:

     

    $backupData = Import-Csv –Path "C:\Backup\ClientPolicies.csv"

     

    foreach ($user in $backupData)

        {Grant-CsClientPolicy –Identity $user.Identity –PolicyName $user.ClientPolicy

        }

     

    So what exactly does this script do? Well, in the first line it uses the Import-Csv cmdlet to read in all that data we stored in ClientPolicies.csv. After the data has been retrieved (and stored in our old friend, the variable $backupData) we then set up a foreach loop to iterate through all that data. Inside the loop we do one thing and one thing only: we assign each user the client policy that he or she used to have assigned to them. That's what this line of code does:

     

    Grant-CsClientPolicy –Identity $user.Identity –PolicyName $user.ClientPolicy

     

    If you're wondering how this works, $user.Identity represents the Identity of the user account and $user.ClientPolicy represents the client policy that this user used to have assigned to them. For example, suppose the first line of user account data in ClientPolicies.csv looks like this:

     

    "CN=adelaney,OU=Redmond,DC=litwareinc,DC=com","ClientPolicy1"

     

    In that case, $user.Identity will be equal to CN=adelaney,OU=Redmond,DC=litwareinc,DC=com and $user.ClientPolicy will be equal to ClientPolicy1. Which also means that the user adelaney is going to be reassigned ClientPolicy1. That's because we'll actually be running this line of code:

     

    Grant-CsClientPolicy –Identity "CN=adelaney,OU=Redmond,DC=litwareinc,DC=com" –PolicyName "ClientPolicy1"

     

    As soon as the script finishes, everything will be as it once was:

     

    Policy

    No. of Users Assigned This Policy

    ClientPolicy1

    21

    ClientPolicy2

    13

    ClientPolicy3

    71

     

    Pleasant dreams, eh?

     

    Of course, maybe you don't need to reassign client policies for all of your users; maybe the only people who can't use LitwareincClientPolicy are those people who used to be assigned ClientPolicy1. That's fine; it's easy enough to modify the script so it only reassigns policies to a subset of users (that is, users who used to be assigned ClientPolicy1):

     

    $backupData = Import-Csv –Path "C:\Backup\ClientPolicies.csv"

     

    foreach ($user in $backupData)

        {if ($user.ClientPolicy –eq "ClientPolicy1")

            {Grant-CsClientPolicy –Identity $user.Identity –PolicyName $user.ClientPolicy}

          }

     

    In this modified script, the first thing we do inside the loop is check to see if our user used to be assigned the client policy ClientPolicy1:

     

    if ($user.ClientPolicy –eq "ClientPolicy1")

     

    If that turns out to be true, then we reassign them their old policy. If it's not true (for example, if they used to be assigned ClientPolicy2) then we don't do anything at all.

     

    Pretty cool, huh?

     

    So does this mean you now have a sure-fire way to undo anything you might do in Lync Server? No. Instead, what you have is a way to undo a very specific task: bulk assignment of client policies (something which you might never do anyway). On the other hand, you also have an idea of how you can use a simple script to provide a little peace-of-mind before you undertake a major operation; you could easily modify this script to back up other types of policy data, to back up user information data, to back up client version policy rules, etc., etc. In other words, not only will this approach prevent nightmares, but it might also inspire you to dream up new ways to backup and restore Lync Server information. After all, as George Carlin once said:

     

    "Some people see things that are and ask, 'Why?' Some people dream of things that never were and ask, 'Why not?' Some people have to go to work and don't have time for all that."

     

    Which reminds us: we need to get back to work right now. If you have questions about these scripts, or how you might be able to modify them to fit your own needs, just email us: cspshell@microsoft.com

     

  • Haiku #56

    No thanks, Theraflu.

    I'll use file filtering to

    Thwart those viruses.

     

    Remember computer viruses? Well, of course, you do; sadly, computer viruses are still around, and probably will be for a long time to come. People always say that, in the event of an all-out nuclear war that totally wipes out all humanity, the one thing that would survive is the cockroach. The truth is, however, that there are probably two things that will survive: cockroaches, and some 15-year-old kid who writes computer viruses in his spare time.

     

    Note. The big question is whether that 15-year-old kid will be able to survive on Twinkies. Some people say yes: there have long-been rumors that Twinkies have an indefinite shelf life, that they "will last longer than the cellophane they're wrapped in." For better or worse, however, that does not appear to be true. Instead, Twinkies only have a shelf life of 25 days.

     

    And sorry, but, just by biting into one, we don’t know how to tell the difference between a good Twinkie and a bad Twinkie. We'll look into that for you.

     

    Oh and, on the bright side, if you microwave a Twinkie for 45 seconds (on high) it will explode. Do we recommend that you try this at home? Well, we definitely don't recommend that you try it at your home. Or, we hasten to add, at our home.

     

    But while computer viruses are still around, they're definitely not as much … fun … as they used to be. Remember the ILOVEYOU virus, which infected some 50 million computers back in the year 2000? Those were the days, huh? But those days are largely a thing of the past.

     

    One reason that computer viruses aren't quite as big a threat as they used to be is because software makers (including us here at Microsoft) have taken a number of steps to prevent the easy propagation of viruses. For example, the ILOVEYOU virus was actually a VBScript script (a .VBS file) that was sent via Outlook. People would double-click the script attachment (thinking it was a text file) and the virus would immediately set to work, deleting files and sending copies of itself to everyone in your address book.

     

    Note. In case you're wondering, no, the author of today's haiku was not a victim of the ILOVEYOU viruses. He gets so many emails from people telling him how they love him that, by the year 2000, he'd already given up even bothering to look at them.

     

    Nowadays, the ILOVEYOU virus would run into a few roadblocks: you can't send a .VBS file through Outlook; you can't execute a .VBS file from within Outlook; and you can't run a script that will automatically send an email to everyone in your address book. (Instead, you must answer yes to a pop-up that asks if you really want to send that email to everyone in your address book.) All in all, it's a lot harder for a virus to get through to people, and a lot harder for people to actually activate that virus. It's not impossible but, at the same time, it's definitely tough to be a computer virus writer these days.

     

    Note. But don't feel too bad for the virus writers. They all seem to have found gainful employment writing Facebook scams instead.

     

    Of course, as a Lync Server administrator you might be thinking, "Hmmm, Microsoft Lync allows users to transfer files; in fact, you can easily transfer a file to everyone in a conference. Does Lync do something to help lessen the chance that someone sitting in a meeting might send a virus to everyone else sitting in that meeting?"

     

    Funny you should ask: you bet it does. With file transfer filtering, and the CsFileTransferFilterConfiguration cmdlets (Get-CsFileTransferFilterConfiguration, New-CsFileTransferFilterConfiguration, Remove-CsFileTransferFilterConfiguration, and Set-CsFileTransferFilterConfiguration) you can take the same approach to file attachments that Outlook does: you can restrict the type of files that can be transferred based on the file extension of those files. For example, by default users are allowed to use Microsoft Lync to transfer Windows PowerShell script files (.PS1 files). You say you're a little uncomfortable with that? That's fine; you can just add the .PS1 file extension to the list of file types that can't be transferred using Microsoft Lync:

     

    Set-CsFileTransferFilterConfiguration -Identity global -Extensions @{Add=".ps1"}

     

    Pretty easy, huh? If you later change your mind and decide that it's OK to transfer .PS1 files after all, well, just remove that file extension from the list of prohibited file types:

     

    Set-CsFileTransferFilterConfiguration -Identity global -Extensions @{Remove=".ps1"}

     

    And, of course, you can use this same approach to block any file extension, not just file extensions that might be used by a virus writer. For example, we don't know of too many viruses that use either the .WMA or the .MP3 file extension. Nevertheless, you might not want people sending 500-megabyte video clips to everyone else in a meeting, or you might not want people distributing illegally-downloaded .MP3 files to all their colleagues. That's fine; all you have to do is add the .WMA and the .MP3 file extensions to the list of prohibited extensions. In fact, you can add both those extensions with a single command:

     

    Set-CsFileTransferFilterConfiguration -Identity global -Extensions @{Add=".wma",".mp3"}

     

    And if you don't like the idea of people transferring files at all, then just set the Action property to BlockAll:

     

    Set-CsFileTransferFilterConfiguration -Identity global –Action BlockAll

     

    That will disable all file transfers using Microsoft Lync.

     

    Note. In case you're wondering, by default the Action property is set to Block. In that case, Lync will block any file extensions that appear in the list of prohibited file types. If an extension isn’t on that list, however, then Lync will allow you to transfer files of that type.

     

    Ah, good question: how do you know which file extensions are in the list of prohibited file types? Well, if you just run the Get-CsFileTransferFilterConfiguration cmdlet without any parameters you'll be a bit disappointed; you'll get back output similar to this:

     

    Identity   : Global

    Extensions : {.ade, .adp. .app, .asp…}

    Enabled    : True

    Action     : Block

     

    As you can see, in that case Get-CsFileTransferFilterConfiguration shows you only the first few extensions on the list; that's probably not what you had in mind. To see the complete list, use a command similar to this one:

     

    Get-CsFileTransferFilterConfiguration -Identity global | Select-Object –ExpandProperty Extensions

     

    Give that a try and see what happens.

     

    Now, admittedly, until software makers figure out a way to do away with users altogether you'll never be 100% protected from computer viruses or from people overloading the network by sharing videos of their cat. Still, the CsFileTransferFilterConfiguration cmdlets can help, and will definitely give you fewer things to worry about when it comes to Lync Server administration.

     

    Note. Oh, and you shouldn't worry about cockroaches, either. Cockroaches can go a month without food, can got 45 minutes without air, and have been known to go as long as 7.5 minutes without sending a text message or checking their email (!). Cockroaches will be just fine.

     

     

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

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

     

    And now for the moment you've all been waiting for. The winner of this year's Academy Award for Best Motion Picture goes to --

     

    Oops; sorry. For a moment there we forgot we were dealing with Microsoft Lync Server 2010 administrators. When Lync Server administrators go looking for a little fun and a little excitement, they don't look to the movies (bore-ing). Instead, Lync Server administrators go looking for the latest Lync Server PowerShell One of These Things is Not Like the Others challenge. That means that the way we should have started this article is like this:

     

    And now for the moment you've all been waiting for. The latest Lync Server PowerShell One of These Things is Not Like the Others challenge is this:

     

    Which of these Lync Server PowerShell cmdlets is not like the others:

     

    Get-CsPool

    Get-CsService

    Get-CsTopology

    Get-CsSite

     

    That's more like it, eh?

     

    If you think you know the answer, send that answer, along with your name or alias, to cspshell@microsoft.com. (Oh, and if you think about, please include a short explanation of why you believe that's the answer.) Correct entries received before 9:00 AM Pacific Standard Time on Thursday, March 3, 2011 will be awarded 3 challenge points. (Note that you can send in multiple entries. But you can only get a maximum of 3 points per challenge.) On Thursday, March 3rd we'll post a hint to this challenge. After the hint has been posted, correct entries received before 9:00 AM Pacific Standard Time on Monday, March 7, 2011 will be awarded 1 challenge point.

     

    Challenge 7 Hint

     

    Challenge Home

     

     

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

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

     

    To be honest, there's a lot of pressure involved in running a highly-prestigious competition such as the weekly Lync Server PowerShell One of These Things is Not Like the Others Challenge.

     

    Note. If you aren't familiar with the Challenge, many people consider it to be the Nobel Prize of the Lync Server world, the only real difference between the two being that people actually care about the Nobel Prize.

     

    Well, that and the fact that people who win the Nobel Prize receive $1.4 million dollars. People who win the Lync Server PowerShell Challenge get about $1.4 million dollars less than that.

     

    At any rate, one of the pressures involved in running the Lync Server PowerShell Challenge is trying to balance the need to make the weekly question difficult enough to still be considered a challenge, yet not so difficult that no one can answer it. Make the question too hard and everyone complains that the question was too hard; make the question too easy and everyone complains that the question was too easy. But make the question just right and – well, we’ll let you know what everyone says about that just as soon as we actually make the question just right.

     

    Our solution to this on-going problem has been to try to mix things up a bit: some weeks the questions are easy, some weeks the questions are not-so-easy. For example, last week we gave you an easy question to answer. (How do we know that? Well, for one thing, every single person who submitted an answer got it correct.) In our last Challenge, we presented you with the following four Lync Server PowerShell cmdlets and asked you to tell us which of those four cmdlets was not like the others:

     

    Grant-CsExternalAccessPolicy

    Grant-CsDialPlan

    Grant-CsOUPermission

    Grant-CsConferencingPolicy

     

    And the answer to this challenge? Grant-CsOUPermission.

     

    But, needless to say, you already knew that, didn't you?

     

    Why Grant-CsOUPermission? Well, as everyone pointed out, the other three cmdlets in the group – Grant-CsExternalAccessPolicy, Grant-CsDialPlan, and Grant-CsConferencingPolicy – are used to assign something (an external access policy, a dial plan, and a conferencing policy) to a specific user or set of users. For example, this command grants a specific external access policy to the user Ken Myer:

     

    Grant-CsExternalAccessPolicy –Identity "Ken Myer" –PolicyName "RedmondAccessPolicy"

     

    And this command grants a dial plan to all the users in the Redmond OU:

     

    Get-CsUser –OU "OU=ou=Redmond,dc=litwareinc,dc=com" | Grant-CsDialPlan –PolicyName "RedmondDialPlan"

     

    So what's different about Grant-CsOUPermission? Well, with that cmdlet you can't assign something (i.e., user management permissions) to any old person or group of people. Instead, running the cmdlet automatically grants user management permissions to one group and one group only: the RTCUniversalUserAdmins security group. If you want Ken Myer to have these user management permissions you can't use Grant-CsOUPermission to specifically assign those permissions to Ken. Instead, you need to make Ken a member of the RTCUniversalUserAdmins group. That's the only way to get him those permissions.

     

    Note. We should point out that you don't necessarily have to run Grant-CsOUPermission: when you install Lync Server, Setup will try to grant all the required permissions for you. Grant-CsOUPermission is typically only needed in a locked-down domain where permission inheritance has been disabled. If you don't have a locked-down domain, then you won't need to run Grant-CsOUPermission; Setup itself will make sure that the RTCUniversalUserAdmins group has all the user management permissions it needs.

     

    So how could you figure this out? Well, to be honest, the only way we know of is to read the help. For example, if you read the help for the Grant-CsOUPermission cmdlet you'll see this sentence:

     

    Note that this cmdlet only grants permissions to a set of predefined security groups; the cmdlet cannot be used to grant permissions to arbitrary security groups or to individual users.

     

    Because the help for the other three cmdlets show a number of examples in which items are assigned to individuals and groups of individuals, well, there's your answer right there.

     

    See? We told you last week's Challenge was easy.

     

    And what about this week's Challenge: is it an easy one or is it a hard one? You'll just have to see for yourself.

     

    Challenge Home