Monday, June 8, 2009

SPTimerScheduler for SharePoint Improvement

By Hristo Yankov

At some point of time, you will need to create a Timer Job (scheduled task) for your custom SharePoint web solution. For example, you may need it to synchronize two systems.

Out of the box, you can create a SharePoint timer job, by inheriting the SPJobDefinition class and then creating a timer job installer, by inheriting SPFeatureReceiver. What this basically does is, during the activation of your feature, the installer will kick in and add your timer job to SharePoint timer jobs list. On deactivation of the feature, the timer job will be 'uninstalled'. This is associated to a huge inconvenience - you can't change the schedule of your task, unless you change your source code and redeploy. In a production environment this may cause a big stir.

This is where you can use SPTimerScheduler! It is really convenient and easy to install. After deploying the solution and activating the feature, you get a 'TimerJobSchedule' list, where you can define all your timer jobs. You just 'point' to the assembly, class and method you want to execute, pass constructor parameters (optional) and you are done! It allows for simple and easy task (re)scheduling, which is generally why you want to use this solution in the first place.

If there is one nice thing about the native SharePoint timer jobs, it is the fact that if your code throws an exception during execution, it will be logged by the SharePoint timer service in the Event Log. This is missing from SPTimerScheduler!

The purpose of this article is to show you how to extend this custom solution functionality so you can see what the error was, if any.

First, you need to download the source code of SPTimerScheduler from here. As of right now, the latest release is

After you download the source, open SharePointerTimerJobScheduler.sln in Visual Studio. It may prompt you to remove the version control associated to the project, to which you agree.

We will start by adding one more column to the 'TimerJobSchedule' list, which will store the latest Exception message. Please note that the project stores the list template as TimerJobSchedule.stp file, which you can not edit directly. Generally, what you have to do is import the stp file to SharePoint, create an instance of this list type, edit it by adding one more column - LastExceptionMessage (multiline, plain) and then export it again. Overwrite the old stp file with the newly exported one. Here are detailed instructions:

1) Go to your SharePoint web site -> Site Actions -> Site Settings. Under 'Galleries', click on 'List Templates'.

2) Click Upload button -> "Upload Document"

3) Browse for "12\TEMPLATE\FEATURES\SharePointerTimerJobScheduler\TimerJobSchedule.stp" file from the source code and upload it.

4) Now you have added the SPTimerScheduler as a type of a custom list. Create a new instance of it. Click on 'Create' and under 'Custom Lists' you should see 'TimerJobSchedule'. Click on it.

5) Give the list instance a name and click Create. The go to the settings of the list and under 'Columns' click 'Create column' link.

6) Name the column 'LastExceptionMessage' and make it of type 'Multiple lines of text', 'Plain text' and click ok.

7) Go to the Site Settings -> List templates again and delete the TimerJobSchedule list template you imported on step 3. You need to do this as preparation for the next step.

8) Now go to the list you created (of type 'TimerJobSchedule'. Remember, you gave it a name at step 5) and open its settings. Under 'Permissions and Management' there is a link 'Save list as template'. Click on it.

9) Under 'file name' and 'template name' fields call it 'TimerJobSchedule' as it used to be when you first imported it. Do not include content and click OK button.

10) Go to site settings again -> List templates. You should see the TimerJobSchedule template there. Click on the Name field of the item, which is a link. Save the file TimerJobSchedule.stp back to 12\TEMPLATE\FEATURES\SharePointerTimerJobScheduler.

You have now effectively added one more column to the list - LastExceptionMessage.

Now we need to edit the code too. You should have the solution open in your Visual Studio. Open TimerJobScheduler.cs for edit and go to line 140. This is the catch statement, right after the 'RunTheTimerJobInstance(Item);' block. As you can see, logging logic is not yet implemented there. What you want to do is add the following code in this catch statement:

Item["LastExceptionMessage"] = NowDateTime + " - " + ex.Message;

Basically it will write a time stamped exception message into the 'LastExceptionMessage' column you have created earlier. As you can see, we don't even need logging components such as log4net at this point. We are using the column to store the message.

Right click the 'SharePointerTimerJobScheduler' project in Visual Studio and select Properties. Go to the Build Events tab and take a look at the "Post-build event command line" text box. There is an entry saying:
makecab /f solution.ddf"

Change it to:
makecab /f solution.ddf

I.e. - remove the " character at the end of the line, as it is there by mistake (I guess).

There is also an error in TimerJobSchedulerFeature.cs file of the source. Find the line:
AddListTemplateToGallery(@"C:\Program Files\Common Files\
Microsoft Shared\web server extensions\12\

And replace it with:
AddListTemplateToGallery(@"C:\Program Files\Common Files\
Microsoft Shared\web server extensions\12\

I have notified the developer about those findings here.

After you are done with all of the above, rebuild the solution. The "Deployment\SharePointerTimerJobScheduler.wsp" will be refreshed. You need to redeploy it. You can do that by copying 'SharePointerTimerJobScheduler Source\Deployment\SharePointerTimerJobScheduler.wsp' (which is the output of the source project) into 'SharePointerTimerJobScheduler Release' (which was the release folder of the project, if you downloaded it. And you should!).

After deployment, by running 'SharePointerTimerJobScheduler Release\Install Feature.cmd' (and re-activation of the 'SharePointer Timer Job Scheduler' site feature) make sure the 'LastExceptionMessage' column is visible in your default list view, so you can monitor it for errors.

And that's all. Now just make sure that the method you are executing as a timer job, throws a meaningful exception, which will be visualized in the list column!
Bookmark and Share

1 comment:

Virginie & Mathieu said...

Hi, very good, It's ok. But after this, I would like to change code of the SharePointerTimerJobScheduler (add the stacktrace of the error), but when I uninstall and reinstall, my change not apply. Do you know how I can totally delete SharePointerTimerJobScheduler and redeploy with my change ?

Thanks, Mathieu