PerformancePoint Top 10 Filter in Analytic Grid

Applies To: SharePoint 2010, SQL 2008 R2, PerformancePoint

Ran into a surprising issue with PerformancePoint today when creating a simple Analytic Grid. I had all the measures and dimensions setup correctly and decided it would be best to just show the top 10 rows. Fortunately, the Dashboard Designer has a handy Top 10 filter built in. Unfortunately, it doesn’t work.

When you apply the filter you will get a message like “There are no data rows to display” or “There is no data to display” or even “Drag measures, dimensions, or named sets to Rows and Columns to lay out the report.” This is especially irritating because it works just fine for Analytic Charts.

Some quick research revealed that the problem is with the generation of the MDX (Query) when working with the Analytic Grid and how SQL 2008 R2 handles it. You can request a hotfix for the problem (for SQL 2008 R2), but it apparently doesn’t fully fix the problem.

So, you’re pretty much stuck with a half fix from Microsoft. This is better than nothing and I would recommend doing it. However, if you’re like me and not in charge of the database management and will have to wait for that team to evaluate and apply the hotfix (if they even will), you might be interested in the workaround I’m using.

My workaround is pretty simple and fixes simple Analytic Grids you would like to start with the Top X type filters, but doesn’t fix the problem when these filters are applied on the fly by the end user using the dashboard. Basically, we take advantage of the fact that your grid’s report type can easily be switched in the designer and that Top X filters work fine for Analytic Charts. This solution is inspired by this Question and Answer on TechNet where Dan English delves into the auto generated MDX.

  • Create your report with all the dimensions, formatting, measures, etc. that you want with the exception of the Top X filter.
  • Right-Click on the Grid and select Report Type > Pie Chart
  • Now apply your Top X filter (Right-Click and select Filter > Top 10) – Generally you will select the Top 10 choice in the series section to apply it to one of the column values
  • Switch to the Query tab
  • Click in the text area, Select All (Ctrl-A) and Copy (Ctrl-C)
  • Switch to the Design tab
  • Right-Click and select Report Type > Grid
  • Switch to the Query tab
  • Click in the text area, Select All (Ctrl-A) and Paste (Ctrl-V)
  • Switch back to the Design tab to see it applied correctly

This solution is a little messy but it works until Microsoft releases a Service Pack with a full fix for the issue.

Note about Filters – Since the query has been edited, none of the automatic connection points exist. You will have to manually add parameters (Query Tab) to the report. For instance, I wanted to use a Time Intelligence filter with my top 10 list to show the top 10 for a given time period. With a regular report I would just add the calendar dimension to the Background and then hook up my filter by using the Source value of “Formula”. Now that the Top 10 filter has been applied and I have no automatic parameters, I simply replaced the Where portion of the query that had my background calendar dimension with a parameter (Query Tab). Then in the connection dialog of the dashboard I choose Source value equal to “Member Unique Name”.

OWSTimer Debugger Annoyances

Applies To: SharePoint 2010, Visual Studio 2010

If you’re running Visual Studio on the same machine with SharePoint 2010 you are probably familar with this error message:

“An unhandled exception (‘System.Security.Cryptography.CryptographicException’) occurred in OWSTIMER.EXE [#]. The Just-In-Time debugger was launched without necessary security permissions. To debug this process, the Just-In-Time debugger must be run as an Administrator. Would you like to debug this process?”

In fact, you are probably very familiar with this dialog since it will pop up at least once a day. If you haven’t logged in in a while, then you will have multiple windows to cancel debugging in.

The problem is due to a threading issue related to an encryption key used by the OWSTIMER service. In SharePoint 2010 the timer service gets recycled daily (default is 6 AM) using a timer job mysteriously called “Timer Service Recycle”. The details aren’t all that important, but you can read more here and get even more information about how the mistake really occurs here. To summarize, the key isn’t found due to impersonation issues. (BTW, that number at the end of the error message is just the process ID and will change each time.)

Bottom line for me is that the error is not really a problem and can safely be ignored in your logs. The annoyance comes when you have Visual Studio installed and the JIT debugger is enabled.

You can either adjust your settings using the registry, or even better, just open up Visual Studio (2010) and adjust your options. Using the menu, choose Tools > Options. Then expand Debugging from the tree on the left (if it isn’t showing, check the Show all settings box) then choose Just-In-Time. To turn it off, just uncheck all the boxes and press OK:

Now those annoying messages will stop and the people will rejoice. Just remember that it can be very helpful to turn these back on when attempting to debug certain types of things (Custom Timer Jobs for instance), but be sure to bookmark this page because you will forget to turn it back off and then you will be sad again and I don’t want you to be sad.

Verifying Constrained Delegation

Applies To: Active Directory

When using Kerberos with SharePoint 2010 you run into the requirement to use Constrained Delegation all over the place. Basically, even though you have the SPNs setup, you’ll need to specify which services your accounts can delegate to by using Active Directory. This is all covered elsewhere and can be found using some simple Google searches so I won’t go into any more detail.

The problem I run into is that I’m not allowed to set this up in Active Directory in our production environment and I have to trust someone else to do this. I don’t mind that, but I do want to be able to check the settings when troubleshooting. Using the Active Directory tools (Here’s a guide to getting these setup), even if you don’t have permission to edit anything, you can take a look at most of the account information. Unfortunately, the delegation tab has everything disabled.

Names hidden to protect the innocent

If you just have a few items setup, then you can see the first six or so, but you can’t scroll down and you can’t expand the entries. Why Microsoft made this impossible to view is beyond me, but you can get to it using the command line.

Since you’ve got the tools installed, fire up a command prompt (Go ahead and Run as Administrator). Then type this command:

ldifde -f C:\ConstrainedDelegation.txt -d "cn=SharePoint AppPool,ou=SharePoint,ou=Services,dc=MyDomain,dc=Com" -l msDS-AllowedToDelegateTo

This will write a list of all the services the account can delegate to (To see all the properties just leave the msDS-AllowedToDelegateTo off the end). Also, make sure you replace the part in quotes with the actual path to your account.

The easiest way to figure out the correct path is to open the Active Directory Users and Computers and expand the OUs (folders) until you find your account. Then take the display name of the account as the cn= part and work backwords up the “folders” specifying ou= for each. Finally, add the dc= for each part of your FQDN. Usually something.something. In the above example, I had expanded MyDomain.com then the Services folder and then then SharePoint folder to find my account named SharePoint AppPool.

In your face Microsoft! I used your tools to get around your tools! Hopefully this can help relieve some of the frustration of troubleshooting Kerberos errors during installation or configuration. Even with the above tip, you’re gonna want a hanky to cry into and a teddy bear to squeeze.

Wallpaper Happiness in Windows 7

Applies To: Windows 7

This is not the usual technical article, but I wanted to share something I’ve done that makes my day a little better. I’ve taken a bunch of relaxing or neat wallpaper photos and using Windows 7 I’ve set them up to automatically change every minute. This is super easy to do and takes just a few minutes, so… Get on it!

The best way to get some good looking photos is to use a Windows 7 Theme. To get these, just right-click on your desktop and choose Personalize. This will open the Personalization Control Panel:

Then click the Get more themes online link in the control panel:

This will open the Windows 7 Themes gallery site in your browser. Look through the themes and pick one to start with. For me, some of the best were in the RSS dynamic themes category. Terra Dynamic is a good one to start with. Click Download and then choose Open:

This will launch the Personalization control panel and install the theme. If it is one of the RSS dynamic themes you will be prompted to download the attachments, choose to download them:

It may take a few minutes, depending on the theme, to finish downloading all the images. To get at them, click on the Desktop Background button at the bottom of the Control Panel. Then to find the location of these images, right-click on the path above the thumbnails. This may cause a Windows Security warning depending on your settings. If it does, choose OK:

In the Context Menu, choose Properties:

In the properties dialog select the full path in the Location section (Leave out the All in text) and right-click and choose Copy:

Then open a folder and paste the copied path into the path url box and press enter:

This will open the folder with all of the images. Select all the images and copy them to some folder in your My Documents or elsewhere. Then repeat the above process for as many themes as you want.

Dynamic themes (RSS) will store their images in the same location (they’ll just have a different GUID – ugly number in brackets), so you can just leave that folder open. Standard themes will save their images to C:\Users\[Your User Name]\AppData\Local\Microsoft\Windows\Themes and will have a folder that matches the theme name. In those folders will be a folder of images you can copy from.

To uninstall the theme, just delete it’s folder from the themes folder.

Once you’ve assembled a ton of images from all sorts of themes in a single folder, briefly go through them and get rid of any that doesn’t immediately appeal to you. I have around 250 images in my folder. Open the Personalization Control Panel again. Pick any theme (preferably one with sounds you like) and click the Desktop Background button.

Click the Browse button next to the Picture location dropdown and choose your folder. Choose Fill for the Picture Position and set the “Change picture every” to something you like (mine is 1 minute). I also picked Shuffle so that it would pick a random order each time. When you are satisfied, click Save changes.

That’s it! You now have a beautiful new image to look at every minute or so as you are working! The good news is since this is your folder, you can drop images from anywhere in there and they will automatically get added to the rotation.

As you watch them change you can pretend you live in the photo or are at least visiting instead of sitting in a dark cubicle slowly developing diabetes and heart disease! When your boss tells you that your number one priority is a list of like 5 things that are all “equally important” because he/she doesn’t understand priority or your coworker sprays perfume on his feet because they smell so bad, you can just stare at the picture of some field somewhere and put off the madness for one more day.

Updating an XML File in the 14 Hive Using a Custom Timer Job

Applies To: SharePoint 2010, .NET Framework (C#, VB.NET)

As mentioned in a previous post, I’ve recently put together a solution for automatically configuring your SharePoint servers to use the Adobe PDF icon for PDF files. You can download the solution as well as the source for free from CodePlex here: WireBear PDFdocIcon. I’m going to show some of the code as it currently exists below, but be sure to check out the CodePlex site to ensure you have the latest version.

I’ve also provided the bulk of the code and some explanation for installing/uninstalling a custom job from a SharePoint solution in my last post: Implementing a Custom SharePoint Timer Job. In this post we’ll explore what’s actually happening in the execution of the timer job.

The goal is to update the DOCICON.xml file in the 14\TEMPLATE\XML folder within the SharePoint 2010 Hive to include or remove a mapping entry for a specific file extension. Here is the entire DocIconJob class:

The Code:

Imports Microsoft.SharePoint.Administration
Imports System.IO
Imports Microsoft.SharePoint.Utilities
Imports System.Xml

Public Class DocIconJob
    Inherits SPServiceJobDefinition

#Region "Properties"

    Private _dociconPath As String
    Public ReadOnly Property DocIconPath() As String
        Get
            If String.IsNullOrEmpty(_dociconPath) Then _dociconPath = SPUtility.GetGenericSetupPath("TEMPLATE\XML\DOCICON.XML")
            Return _dociconPath
        End Get
    End Property

    Private Const InstallingKey As String = "DocIconJob_InstallingKey"
    Private Property _installing() As Boolean
        Get
            If Properties.ContainsKey(InstallingKey) Then
                Return Convert.ToBoolean(Properties(InstallingKey))
            Else
                Return True
            End If
        End Get
        Set(ByVal value As Boolean)
            If Properties.ContainsKey(InstallingKey) Then
                Properties(InstallingKey) = value.ToString
            Else
                Properties.Add(InstallingKey, value.ToString)
            End If
        End Set
    End Property

    Private Const FileExtensionKey As String = "DocIconJob_FileExtensionKey"
    Private Property _fileExtension() As String
        Get
            If Properties.ContainsKey(FileExtensionKey) Then
                Return Convert.ToString(Properties(FileExtensionKey))
            Else
                Return String.Empty
            End If
        End Get
        Set(ByVal value As String)
            If Properties.ContainsKey(FileExtensionKey) Then
                Properties(FileExtensionKey) = value
            Else
                Properties.Add(FileExtensionKey, value)
            End If
        End Set
    End Property

    Private Const ImageFilenameKey As String = "DocIconJob_ImageFilenameKey"
    Private Property _imageFilename() As String
        Get
            If Properties.ContainsKey(ImageFilenameKey) Then
                Return Convert.ToString(Properties(ImageFilenameKey))
            Else
                Return String.Empty
            End If
        End Get
        Set(ByVal value As String)
            If Properties.ContainsKey(ImageFilenameKey) Then
                Properties(ImageFilenameKey) = value
            Else
                Properties.Add(ImageFilenameKey, value)
            End If
        End Set
    End Property

#End Region

    Public Sub New()
        MyBase.New()
    End Sub

    Public Sub New(JobName As String, service As SPService, Installing As Boolean, FileExtension As String, ImageFilename As String)
        MyBase.New(JobName, service)
        _installing = Installing
        _fileExtension = FileExtension
        _imageFilename = ImageFilename
    End Sub

    Public Overrides Sub Execute(jobState As Microsoft.SharePoint.Administration.SPJobState)
        UpdateDocIcon()
    End Sub

    Private Sub UpdateDocIcon()
        Dim x As New XmlDocument
        x.Load(DocIconPath)

        Dim mapNode As XmlNode = x.SelectSingleNode(String.Format("DocIcons/ByExtension/Mapping[@Key='{0}']", _fileExtension))

        If _installing Then
            'Create DocIcon entry
            If mapNode Is Nothing Then
                'Create Attributes
                Dim keyAttribute As XmlAttribute = x.CreateAttribute("Key")
                keyAttribute.Value = _fileExtension
                Dim valueAttribute As XmlAttribute = x.CreateAttribute("Value")
                valueAttribute.Value = _imageFilename

                'Create Node
                mapNode = x.CreateElement("Mapping")
                mapNode.Attributes.Append(keyAttribute)
                mapNode.Attributes.Append(valueAttribute)

                Dim byExtensionNode = x.SelectSingleNode("DocIcons/ByExtension")
                Dim NodeAdded As Boolean = False
                If byExtensionNode IsNot Nothing Then
                    'Add in alphabetic order
                    For Each mapping As XmlNode In byExtensionNode.ChildNodes
                        If mapping.Attributes("Key").Value.CompareTo(_fileExtension) > 0 Then
                            byExtensionNode.InsertBefore(mapNode, mapping)
                            NodeAdded = True
                            Exit For
                        End If
                    Next

                    If Not NodeAdded Then byExtensionNode.AppendChild(mapNode)
                    x.Save(DocIconPath)
                End If
            End If
        Else
            'Remove DocIcon entry
            If mapNode IsNot Nothing Then
                Dim byExtensionNode = x.SelectSingleNode("DocIcons/ByExtension")
                If byExtensionNode IsNot Nothing Then
                    byExtensionNode.RemoveChild(mapNode)
                    x.Save(DocIconPath)
                End If
            End If
        End If
    End Sub

End Class

What’s Going On:

Lines 9-73 are just the declaration of and logic needed to persist some properties. Again more information can be found in my last post, but basically I am using the SPJobDefinition’s Properties HashTable to store my own properties as specified in the constructor. Except for in the case of the DocIconPath property which is really just wrapping up some logic to get a reference to the 14 Hive’s TEMPLATE\XML directory using the SPUtility class.

The Execute method beginning in line 86 is what is called when the Timer Job actually runs. I override this method to ensure my custom code gets called instead. My custom code really begins in the UpdateDocIcon method starting at line 90.

In lines 91-94, I load the DOCICON.xml file into and XmlDocument object and attempt to find the mapping node that applies to the appropriate file extension (In this case it’s going to be pdf).

If this job is installing (Running on Solution Activation), then I just check to see if the node was found. If so, all done! If not, then it’s time to add it. I create the node and setup it’s attributes in lines 100-108 using standard objects from the System.Xml namespace.

In order to work, the mapping node needs to be added as a child of the ByExtension element, so we find that in line 110. By default the mapping nodes are listed in alphabetical order by their extension. Since I’m anal, I use a method in lines 114-120 presented by Steve Goodyear to ensure I insert the mapping node in it’s proper position. Failing that, I add it to the end in Line 122 and save the file in line 123.

If this job is uninstalling (Running on Solution Deactivation) and the mapping exists, we delete it and save the file in lines 128-134.

Isn’t that Super Exciting?!?! Hopefully this example will help make the concepts I was talking about in my previous post make some sense. If not, then sadness will fill my soul and flowers will no longer bloom or something.

Implementing a Custom SharePoint Timer Job

Applies To: SharePoint 2010

As mentioned in my previous post, I’ve recently put together a solution for automatically configuring your SharePoint servers to use the Adobe PDF icon for PDF files. You can download the solution as well as the source for free from CodePlex here: WireBear PDFdocIcon. I’m going to show some of the code as it currently exists below, but be sure to check out the CodePlex site to ensure you have the latest version.

In order to perform the necessary work on each server in the farm, the PDFdocIcon solution uses a custom Timer Job. This post will focus on the plumbing necessary to setup your own custom timer job that runs on every server in the farm. The actual code to change the DOCICON.XML file will be saved for later.

Choosing Your Job Definition Type

To make your own Timer Job you’ll want to subclass an exisiting Job Definition object and override the Execute method. There are several to choose from, here’s a helpful table:

Job Definitions you can inherit from in the Microsoft.SharePoint.Administration namespace:
SPAdministrationServiceJobDefinition Invokes the SharePoint Administration Service
SPAllSitesJobDefinition Iterates through all sites in a Web Application
SPContentDatabaseJobDefinition Executed per Web Application and each Content Database is processed by individual jobs (Pausable)
SPFirstAvailableServiceJobDefinition Timer Job that runs on the first available server where the specified service exists (Pausable)
SPJobDefinition Base Class for Timer Jobs (Generally, this is the one to use)
SPPausableJobDefinition Timer Job that can be paused
SPServerJobDefinition Executed on a specific server (Pausable)
SPServiceJobDefinition Runs on every server in the farm where the service exists (Pausable) – This is the one I chose
SPWorkItemJobDefinition  Works with the Timer Job to process work items (Pausable)

For simple jobs the SPJobDefinition is the most flexible and is what you’ll generally want to use. For the PDFdocIcon solution, I needed the Timer Job to execute on every server in the farm. So I used the SPServiceJobDefinition and specified the Timer Service.

Storing Persistent Properties

You may not need properties, but if you’re doing anything even mildly complex you probably will. There are a couple of different alternatives here, but basically your properties need to serialize down to strings. You can look up a few examples of custom properties objects that do this, or you can just use my method of storing your properties in the JobDefinition’s Properties object (HashTable).

Here’s how I store the Boolean property _installing:

    Private Const InstallingKey As String = "DocIconJob_InstallingKey"
    Private Property _installing() As Boolean
        Get
            If Properties.ContainsKey(InstallingKey) Then
                Return Convert.ToBoolean(Properties(InstallingKey))
            Else
                Return True
            End If
        End Get
        Set(ByVal value As Boolean)
            If Properties.ContainsKey(InstallingKey) Then
                Properties(InstallingKey) = value.ToString
            Else
                Properties.Add(InstallingKey, value.ToString)
            End If
        End Set
    End Property

Basically, you have a String key for each property that you use to store/retrieve the value from the Properties HashTable. By wrapping those calls in a property you can treat it like a standard variable in the rest of your code and forget all about the specialized storage/retrieval required.

Constructors

You are required to have an empty (parameterless) constructor for serialization, so make sure you’ve got that:

    Public Sub New()
        MyBase.New()
    End Sub

But you will probably need to implement at least a matching constructor with some custom properties. In my Timer Job, I wanted to pass three properties (which I then store using the method above), so I use this:

    Public Sub New(JobName As String, service As SPService, Installing As Boolean, FileExtension As String, ImageFilename As String)
        MyBase.New(JobName, service)
        _installing = Installing
        _fileExtension = FileExtension
        _imageFilename = ImageFilename
    End Sub

Execution

Depending on the base Job Definition class you chose, the Execute method may have a slightly different signature, but either way this is the method to override to provide your own custom logic. In an SPServiceJobDefinition subclass the signature looks like this:

    Public Overrides Sub Execute(jobState As Microsoft.SharePoint.Administration.SPJobState)
        'Custom code here!!
    End Sub

Installing Your Job with a Solution

Using Visual Studio you can create a new Empty SharePoint Project and add your Timer Job class to it. To deploy it you’ll need to add a Feature (Right-click on Features and choose Add Feature). To install your job, you’ll need to add an Event Receiver (Right-click on your new Feature and choose Add Event Receiver).

Uncomment the FeatureActivated and FeatureDeactivating methods. Create a new method (Mine is named RunDocIconJob) with a Boolean and SPFeatureReceiverProperties parameters. This will be the method where we install or uninstall your custom job. In your FeatureActivated and FeatureDeactivating methods call this new method accordingly:

    Public Overrides Sub FeatureActivated(properties As Microsoft.SharePoint.SPFeatureReceiverProperties)
        RunDocIconJob(True, properties)
    End Sub

    Public Overrides Sub FeatureDeActivating(properties As Microsoft.SharePoint.SPFeatureReceiverProperties)
        RunDocIconJob(False, properties)
    End Sub

Then your Job method will look something like this:

    Private _fileExtension As String = "pdf"
    Private _iconFileName As String = "ICPDF.png"

    Public Sub RunDocIconJob(Installing As Boolean, properties As SPFeatureReceiverProperties)
        Dim JobName As String = String.Format("DocIconJob_{0}", _fileExtension)

        'Ensure job doesn't already exist (delete if it does)
        Dim query = From job As SPJobDefinition In properties.Definition.Farm.TimerService.JobDefinitions Where job.Name.Equals(JobName) Select job
        Dim myJobDefinition As SPJobDefinition = query.FirstOrDefault()
        If myJobDefinition IsNot Nothing Then myJobDefinition.Delete()

        Dim myJob As New DocIconJob(JobName, SPFarm.Local.TimerService, Installing, _fileExtension, _iconFileName)

        'Get that job going!
        myJob.Title = String.Format("{0} icon mapping for {1}", IIf(Installing, "Adding", "Removing"), _fileExtension)
        myJob.Update()
        myJob.RunNow()
    End Sub

This is the method I use for my SPServiceJobDefinition. I am not doing any kind of scheduling since this job just runs once on initial deployment and once when being removed. However, you may want to adjust your method to include a schedule (Just set the myJob.Schedule parameter before the Update() call).

Lines 5-10 are finding any existing job definitions that share the same name and deleting them since creating jobs with duplicate names will cause an error. The Title doesn’t have to be unique, but the name does.

Line 12 actually creates the job with my default parameters and then line 15 sets a Title. This is where you would introduce a schedule if you wanted the job to run more than once, but if not just call Update() to save your job. I want my job to run immediately, so in line 17 I call the RunNow() method to do exactly that.

That’s it! You now have a shell for setting up and installing a custom job – specifically one that runs on every server in the farm. My next post will cover what I’m actually doing in the Execution to ensure the DOCICON.xml file is updated appropriately.

Quick Note about testing: In many cases you will need to either restart the Timer Job Service on each server or change your Assembly Version number to get the timer job to pick up any code changes. This doesn’t always happen, but it happens enough to be annoying.

Automatically Setting Up PDF Icon Mapping in SharePoint 2010

Applies To: SharePoint 2010

Nearly everyone who has ever used SharePoint has had to setup the PDF icon mapping so that PDF documents will have the familiar Adobe logo rather than the blank, unknown icon SharePoint uses by default. This is relatively simple and there are guides to do doing this all over the internet. (Microsoft’s can be found here).

Here is a very brief summay of the steps that must be performed manually on every server:

  1. Copy the PDF icon picture from Adobe and put it in your 14 Hive (TEMPLATE\IMAGES)
  2. Edit the DOCICON.xml file in your 14 Hive (TEMPLATE\XML) to add a Mapping element for pdf documents pointing to your new icon
  3. Reset IIS

These aren’t super complicated steps but there are some pretty big problems (or at least irritations) with using this approach:

  • Manual changes can often be error-prone, especially for those not familiar with XML
  • The change must be performed on every server
  • The change must be performed whenever a new server is added to the farm
  • The change will have to be redone in the event of disaster recovery

So, like many before me, I thought, surely this can all be automated! So I looked and I found some solutions for SharePoint 2007 and several solutions that only worked for Standalone Servers or for only one server in the farm. These were of help, but still no good for my needs. So, I wrote my own.

You can find it over on CodePlex as WireBear PDFdocIcon. There’s some stuff about it’s license over there (Free for personal and commercial use, etc.) and the basic installation instructions. It’s super easy to setup since it’s just a standard SharePoint Solution that you globally deploy.

The full source code is available on CodePlex, but I’ll be going in depth about how it works over the next few posts. But to summarize, here’s what happens:

  • The Adobe PDF icon file is copied to the 14\TEMPLATE\IMAGES folder using standard resource deployment
  • On Activation and Deactivation a one time Service Timer Job is run.
  • On Activation, the Timer job searches for a mapping for PDF documents within the 14\TEMPLATE\XML\DOCICON.xml file. If not found, it adds one (in alphabetic order) and points it to the icon file
  • An IIS Reset is performed to get the changes activated
  • When Deactivating, the Timer job removes the mapping for PDF documents
So why use this thing?
  • The changes will be reapplied in the event of Disaster Recovery
  • The changes will be applied to new servers as they are added to your farm
  • You don’t have to personally edit the 14 Hive on every server in your farm
  • It makes a special place in your heart of hearts that keeps the beast at bay

In making this, I came across several blog entries that were especially helpful, here are most of these (Thanks!):

I’ve found this to be a helpful approach and I hope you do too.