Tuesday, December 16, 2008

Sharepoint TimerJobScheduler - The easier way of scheduling SPTimerJobs

Ever since I've been working with Sharepoint I have coded Sharepoint Timer Jobs to run those tasks you want scheduled every day (or even every hour). Sharepoint is certainly a platform that lends itself to scheduling of batch process, with all the publishing of data there are going to be times when you want to schedule code to run at regular intervals.

So what are our options.... Well currently your only real option is to code a Sharepoint Timer Job solution which inherits SPJobDefinition and then code a SPFeatureReceiver which installs a Timer Job and points it at your newly created SPJobDefinition code.

This is all well and good but the real fun and games start when you want to change when the Job runs or how often it runs... What if you change you mind several times? (Well it has been known to happen). This is where SPTimerJobs really fail to live up to expectation.

So I decided to code a easily installable solution where Jobs can be Scheduled from a Sharepoint List which sits in the RootWeb of the Sharepoint Site. Now we can change the Days and Hours the Job, runs not to mention we can also start the job automatically. We can aslo Disable the job easily too.

Download the Sharepoint TimerJobScheduler - http://www.codeplex.com/SPTimerScheduler

Just download the zip file and follow the release notes to install the Feature into the site. Then you are ready to add your own code as Job Instances to the list.

This solution is a SPTimerJob which looks at the TimerJobSchedule List in the RootWeb and runs any TimerJobInstances when the Current Day and Hour is equal to the DaysToRun and HoursToRun fields.

The underlying SPTimerJob runs every 2 minutes which means when you go into the Instance and check the RunAtNextOpportunity checkbox, your TimerJobInstance will run almost immediately.



Once you've set the Days and Hours to run you need to set the Assembly, Class, Method and ConstructorParameters. The Assembly needs to be strong named and placed in the GAC. The Assmebly name will need to be fully Qualified (e.g SharePointerTimerJobScheduler, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8e20aa8796940e26).
The Class name will need to be the full path including the namespace (e.g SharePointer.Utilities.TestTimerSchedule).
The Method name doesn't need to include the brackets (e.g Execute).
If ConstructorParameter1 is null then the TimerJobScheduler assumes that this is a Class with a default constructor. (If ConstructorParameter2 is null then it assumes it is a Class with a constructor that has a single parameter.. And so on).



Code Example



using Microsoft.SharePoint;
namespace SharePointer.Utilities
{
public class TestTimerSchedule
{
SPSite Site;
SPWeb Web;
string ListName;
string ListItemPrefix;
public TestTimerSchedule(string strURL, string webURL, string strListName)
{
Site = new SPSite(strURL);
Web = Site.OpenWeb(webURL);
ListName = strListName;
ListItemPrefix = "New Item";
}
public void Execute()
{
if (!ListAlreadyExist(Web.Lists))
{
CreateTestList();
}
Web.AllowUnsafeUpdates = true;
SPListItem Item = Web.Lists[ListName].Items.Add();
Item["Title"] = ListItemPrefix + " added at - " + DateTime.Now.ToString();
Item.Update();
}
private void CreateTestList()
{
Web.Lists.Add(ListName, "A list to test the execution of the TimerJobScheduler", SPListTemplateType.GenericList);
}
private bool ListAlreadyExist(SPListCollection sPListCollection)
{
foreach (SPList list in sPListCollection)
{
if (list.Title == ListName)
{
return true;
}
}
return false;
}
}
}


Hope it helps
Cheers

6 comments:

  1. Hi Damian,
    Nice approach, I do this in a different way.
    I am working with timer jobs and read the schedule from feature.xml.
    >Properties
    &gtProperty Key="jobSchedule" Value="every 2 minutes between 0 and 59"/&lt
    or something like this
    &gtProperty Key="jobSchedule" Value="daily at 14:30:00"/&lt
    &gt/Properties&lt

    In the FeatureInstalled read this and add this to the job.Properties collection, this way don't have to do any code for schedule in code and is configurable.

    Cheers,
    Ajay

    ReplyDelete
  2. I like that approach Ajay.

    With this I was really looking for a solution for "Power Users" or Admins to edit and add jobs through the Sharepoint UI.

    ReplyDelete
  3. Thanks very much Damian for such a wonderful functionality; This is the exact functionality I was looking for very desperately.

    I've configured as per your instructions and scheduler job is now getting activated as per it's schedule. I now want to use this timer job to activate a workflow however I'm not familiar with coding so I don't know where to look for now.

    Basically, I want to run a workflow in a task list every morning 6 am so I can send reminders if due date has reached.

    Any help or pointers is appreicated.

    Thanks Once again,
    Skillz

    ReplyDelete
  4. Hi Damian,

    Thanks for the tool.
    I have used it in my sharepoint site and had followed all instructions in codeplex site.

    The timer does not run, as the LastRunDateTime is not updated.


    Am I missing some configuration ? can you please advice .

    Thanks

    ReplyDelete
  5. I would check the following in this order -
    Check That your "Job Instance" is set to Enabled... If it isn't it won't even log the fact that the job has tried to run.

    Check that the TimerJobScheduler Sharepoint Timer Job is running as this is the Main job that Starts all of your Job Instances. To do this go to Sharepoint Central Admin > Operations > Timer Job Definitions > TimerJobScheduler and see the "Last run time" is recent.

    The job will also only run against the "Root" Site Collection of the Web Application... So if your site is e.g http://mySite/sites/myChildSite then it won't run. I will need to address this in the next release.

    If none of the above apply to you then it may be that it is throwing an exception somewhere along the line... I'm planning to add Logging to the next release.

    let me know what you find.

    Cheers Damian

    ReplyDelete
  6. Hi,

    Great tool!

    Until you add logging, here is a quick 'work-around' for the rest of the users :)

    http://blog.myitechnology.com/2009/06/sptimerscheduler-improvement.html

    ReplyDelete