February 24, 2021
Hot Topics:

Running Timed Jobs within SharePoint

  • By Gustavo Velez
  • Send Email »
  • More Articles »

Programming a Timed Job

The Job installed in the aforementioned paragraph does not actually work because there is no "logic" to execute. To create a new Job, it is necessary to program a new class library and add it to the Global Assembly Cache (GAC) to make the logic accessible to SharePoint.

The first step is to create a new "Class Library" Visual Studio 2005 project with a suitable name, then add a reference to Windows SharePoint Services (Microsoft.SharePoint.dll) and "using" directives to Microsoft.SharePoint and Microsoft.SharePoint.Administration. The Class needs to inherit from "SPJobDefinition" and to have at least one constructor to initialize the new objects. The definition of the empty class reads:

using System;
using System.IO;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;

namespace CountDocs
   public class CountDocsJob : SPJobDefinition
      public CountDocsJob()

      //public CountDocsJob(string MyJobName,
      //SPService MyService,
      //SPServer MyServer, SPJobLockType MyTargetType) :
      //base(MyJobName, MyService, MyServer, MyTargetType)

      public CountDocsJob(string MyJobName, SPWebApplication
         MyWebApplication) : base(MyJobName, MyWebApplication,
         null, SPJobLockType.Job)

      public override void Execute(Guid ContentDataBaseID)

The base class has two constructors but if two are unnecessary, it is possible to define only one (the second one is commented in the example). The constructor of the sub-classing indicates that the third parameter (the SPServer parameter) is superfluous in this case.

The functional source code is written in the override "Execute" function. This function always has a parameter that receives the ID of the SharePoint's content DataBase that is executing the Job. For the example, the code reads the number of entries in a List and each time it runs, a new entry is created indicating the time and number of found entries:

public override void Execute(Guid ContentDataBaseID)
      SPSite mySite = new SPSite("http://ServerName");
      SPWeb myWeb = mySite.OpenWeb();
      SPList myList = myWeb.Lists["MyJobs"];

      int intCounter = 0;
      foreach (SPListItem myItem in myList.Items)

      SPListItem newTask = myList.Items.Add();
      newTask["Title"] = "Counter of Items at " +
      newTask["Description"] = "At " + DateTime.Now.ToString() +
         " there are " + intCounter.ToString() +
         " items in the List";
   catch (Exception ex)
      TextWriter myWriter =
         new StreamWriter(@"c:\CountDocsJobError.txt");

In the case in point, the code makes a reference to the Site, Web, and List, counts the number of entries in the List, and creates a new entry. The names of the Site and List are fast-coded, but they can be configured in the web.config file of the WebApplication using code similar to this:

Configuration MyConfig =
   WebConfigurationManager.OpenWebConfiguration("/", "Sharepoint -80");
string myValue = myConfig.AppSettings.Settings["MyKeyName"].value;

or extracted from the "ContentDataBaseID" variable.

Sign the assembly with a Safe Name and install it in the GAC (obligatory). After resetting the IIS (iisreset), the previously discussed "CreateJob" routine can be modified to install the Job in the server:

static void CreateJob()
   SPServer myServer = SPServer.Local;
   SPSite mySite = new SPSite("http://ServerName");
   SPWebApplication myApplication = mySite.WebApplication;
   SPJobDefinitionCollection myJobsColl =

   CountDocsJob myJob = new CountDocsJob("myCountDocsJob",
   myJob.Title = "Docs Counter Job";

   SPMinuteSchedule myMinuteSchedule = new SPMinuteSchedule();
   myMinuteSchedule.BeginSecond = 0;
   myMinuteSchedule.EndSecond = 59;
   myMinuteSchedule.Interval = 1;
   myJob.Schedule = myMinuteSchedule;


   Console.WriteLine("Job Installed");

Page 4 of 5

This article was originally published on August 14, 2007

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date