Creating Timer Jobs in SharePoint 2010 that Target Specific Services

Summary: Learn how to create a Microsoft SharePoint 2010 timer job that is associated with a particular SharePoint service in SharePoint 2010.

Wrox logo

Wrox SharePoint Books

Applies to: Business Connectivity Services | Open XML | SharePoint Designer 2010 | SharePoint Foundation 2010 | SharePoint Online | SharePoint Server 2010 | Visual Studio

Author: Bryan Phillips

Editors: WROX Tech Editors for SharePoint 2010 Articles

Contents

  • Overview of Timer Jobs in SharePoint 2010

  • Preparing to Create a SharePoint Timer Job

  • Creating a SharePoint Timer Job

  • Enabling Configuration for Your SharePoint Timer Job

  • Deploying Your Timer Job

  • Testing and Debugging Your SharePoint Timer Job

  • Conclusion

  • About the Author

  • Additional Resources

Overview of Timer Jobs in SharePoint 2010

Microsoft SharePoint 2010 timer jobs perform much of the back-end work that is required to maintain your SharePoint farm. Timer jobs are executable tasks that run on one or more servers at a scheduled time. They can be configured to run exactly one time, or on a recurring schedule. They are similar to Microsoft SQL Server Agent jobs, which maintain a SQL Server installation by backing up databases, defragmenting database files, and updating database statistics. SharePoint uses timer jobs to maintain long-running workflows, to clean up old sites and logs, and to monitor the farm for problems. Depending on your edition of SharePoint and any installed third-party products, you can have many timer jobs in your farm, or just a few. Timer jobs have several advantages. They can run periodically and independently of users who are accessing your SharePoint sites, they can offload long-running processes from your web front-end servers (which increases the performance and responsiveness of your pages), and they can run code under higher privileges than the code in your SharePoint site and application pages.

You can view the timer jobs in your farm by using the Job Definitions page in SharePoint 2010 Central Administration. To access the Job Definitions page, click All Programs, Microsoft SharePoint 2010 Products, SharePoint 2010 Central Administration. On the Central Administration site, click the Monitoring link. Finally, click the Review Job Definitions link in the Timer Jobs section of the Monitoring page. The list of timer job definitions in your farm is displayed, as shown in Figure 1.

Figure 1. List of SharePoint timer job definitions

List of SharePoint timer job definitions

Because SharePoint timer jobs run in the background, they perform their tasks behind the scenes, even if no users are accessing your SharePoint sites. The Windows SharePoint Services Timer service runs the timer jobs in your farm. The service must be enabled and running on each server in your farm. The service enables the various SharePoint timer jobs to configure and maintain the servers in the farm. If you stop the Windows SharePoint Services Timer service on a server, you also stop all SharePoint timer jobs running on that server; for example, jobs that index your SharePoint sites, import users from Active Directory, and perform many other processes that affect the performance and usability of SharePoint.

Preparing to Create a SharePoint Timer Job

Before you can create your SharePoint timer job, you must install Microsoft Visual Studio 2010 (Professional, Premium, or Ultimate edition) on Windows Vista, Windows 7, or Windows Server 2008. SharePoint 2010 must be installed on the development computer.

After you install the required software, create a new SharePoint project in Visual Studio by selecting File, New, Project, which displays the New Project dialog box, shown in Figure 2. In the dialog box, ensure that .NET Framework 3.5 is selected in the drop-down list at the top of the dialog box, and expand the list of project templates in the left pane of the dialog box until 2010 is displayed under SharePoint. Select 2010 to display a list of SharePoint 2010 project templates in the right pane of the dialog box. Select Empty SharePoint Project from the list of templates, specify the project information at the bottom of the dialog box, and then click OK. You use the new project to develop your new timer job, package it for deployment to SharePoint, and then debug it.

Figure 2. New Project dialog box

New Project dialog box

Note

Your New Project dialog box might seem to be different from the dialog box shown in Figure 2, depending on your Visual Studio configuration.

Immediately after you click OK in the New Project dialog box, the SharePoint Customization Wizard dialog box appears, as shown in Figure 3. Type the URL of your SharePoint site in the text box, select Deploy as a farm solution, and then click Finish. You must select the Deploy as a farm solution radio button because timer jobs require a higher level of trust to execute than sandboxed solutions.

Figure 3. SharePoint Customization Wizard dialog box

SharePoint Customization Wizard dialog box

After you click Finish in the SharePoint Customization Wizard dialog box, Visual Studio creates and opens the project, as shown in Figure 4. Now that the project is created, you can start adding the classes that are required to form the basis of your SharePoint timer job. The next section outlines how to create those classes.

Figure 4. New SharePoint project open in Visual Studio

New SharePoint project open in Visual Studio

Creating a SharePoint Timer Job

All timer jobs, including those installed with SharePoint, are created and executed by using the SPJobDefinition class. To create a new SharePoint timer job, you must first add a class to your project that inherits from the SPJobDefinition class.

To add the class to your project

  1. Right-click the project and then choose Add, Class from the context menu to open the Add New Item dialog box.

  2. Specify a name for the class, and then click Add. Visual Studio opens the new class in the text editor.

  3. Change the visibility of the class to public, and make the class inherit from the SPJobDefinition class.

The following code snippet shows an example of a class that inherits from the SPJobDefinition class.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint;

namespace MonitoringJob {
    public class MonitoringJob : SPJobDefinition {
        public MonitoringJob() : base() { }

        public MonitoringJob(string jobName, SPService service)
            : base(jobName, service, null, SPJobLockType.None) {
            this.Title = jobName;
        }

        public override void Execute(Guid targetInstanceId) {
            // Put your job's code here.
        }
    }
}

In the code snippet, the MonitoringJob class inherits from the SPJobDefinition class, defines one non-default constructor, and overrides the Execute method of the base class. The non-default constructor is required because the default constructor of the SPJobDefinition class is for internal use only. When you create your constructor, you must pass the values for the four parameters described in Table 1 to the base class constructor.

Table 1. Parameters for the SPJobDefintion constructor

Name

Description

name

The name of the job.

service

An instance of the SPService class that owns this job. Only the servers where the service, represented by the SPService object, is running can run this job.

server

An instance of the SPServer class associated with this job. Pass null if this job is not associated with a specific server.

lockType

An SPJobLockType value that indicates the circumstances under which multiple instances of the job can be run simultaneously.

In the preceding code snippet, null is passed as the value for server because this job is not associated with a specific server. SPJobLockType.None is passed as the value for lockType to enable SharePoint to run multiple instances of the job simultaneously. Table 2 lists the possible SPJobLockType values and their descriptions.

Table 2. SPJobLockType values

Value

Description

None

Locking is disabled. Job runs on all servers in the farm unless you pass an SPServer object for the server parameter.

ContentDatabase

Job runs for each content database associated with the job's web application.

Job

Only one server can run the job at a time.

After you create the constructors, you must override the Execute method of the SPJobDefinition class and replace the code in that method with the code that your job requires. If your code can run without further configuration, you are finished creating this class. Otherwise, you must add configuration screens and classes to your project, as shown in the next section. The next section also discusses the actual code from the sample that belongs in the Execute method.

Enabling Configuration for Your SharePoint Timer Job

To store configuration data for the job, create classes to contain that configuration and store it in SharePoint. First, the class must inherit from the SPPersistedObject class. Next, the fields in the class must be public, marked with the [Persisted] attribute, and have a data type that is either built-in (Guid, int, string, and so on), inherits from SPAutoSerializingObject, or is a collection type that contains one of the built-in types or a type inheriting from SPAutoSerializingObject. Only fields are saved, not properties, as you might be used to when you serialize objects to XML. The following code snippet shows the two classes that are used to configure the MonitoringJob class.

using Microsoft.SharePoint.Administration;
public class MonitoringJobSettings : SPPersistedObject {
    public static string SettingsName = "MonitoringJobSettings";

    public MonitoringJobSettings() { }
    public MonitoringJobSettings(SPPersistedObject parent, Guid id) :
        base(SettingsName, parent, id) { }

    [Persisted]
    public string EmailAddress;
}

In the code snippet, the MonitoringJobSettings class is used to configure the MonitoringJob class. It inherits from SPPersistedObject and has a single field named EmailAddress that is marked with the [Persisted] attribute. The EmailAddress field is used for the recipient of emails that are sent.

One detail to note is that the MonitoringJobSettings class has two constructors defined; a default constructor, which is required for all serializable classes, and a second constructor that calls a constructor on its base class. This second constructor passes in the name of the SPPersistedObject, an instance of an SPPersistedObject that acts as the "parent" of the MonitoringJobSettings object, and a Guid that is used to assign it a unique identifier in SharePoint. Because MonitoringJob is associated with a specific SPService object, the same SPService object becomes the parent of the MonitoringJobSettings object when it is saved to SharePoint. There is more information about how this works later in this section.

After you create the classes for the job and its configuration, you can use the following code snippet to save the configuration of the job to SharePoint. Later, you add this code to an event handler that executes when the feature that contains your timer job is activated.

// Get an instance of the SharePoint Farm.
SPFarm farm = SPFarm.Local;

// Get an instance of the service.
var results = from s in farm.Services
    where s.Name == "SPSearch4"
    select s;

SPService service = results.First();

// Configure the job.
MonitoringJobSettings jobSettings = new MonitoringJobSettings(service, 
    Guid.NewGuid());
jobSettings.EmailAddress = "myemail@demo.com";
jobSettings.Update(true);

In the code snippet, a reference to the SPService object that represents the SharePoint Search service is obtained and passed to the constructor of the MonitoringJobSettings class together with a unique Guid. After that, the EmailAddress property of the class is configured, and the class's Update method is called to persist the object to SharePoint. Passing true to the Update method specifies that you want SharePoint to overwrite any existing saved configuration. Otherwise, an exception is thrown.

To retrieve your configuration, get an instance of the SPService, call its GetChild method, and then pass in the class type that you are retrieving, together with the name of the setting. The following code snippet shows part of the implementation of the Execute method of the SPJobDefinition-derived class.

public override void Execute(Guid targetInstanceId) {
    MonitoringJobSettings jobSettings =
        this.Service.GetChild<MonitoringJobSettings>(
            MonitoringJobSettings.SettingsName);

    if (jobSettings == null) {
        return;
    }

    // Code omitted.
}

The MonitoringJobSettings class was retrieved from SharePoint by calling the GetChild method of the job's parent SPService object. If nothing was previously saved to SharePoint, the call to the GetChild method returns null. After you have an instance of your job's configuration, the rest of the code in your Execute method can run.

Deploying Your Timer Job

Now that you have created the job and configuration classes, you must add a SharePoint Feature to enable your SharePoint administrators to use the functionality in SharePoint. A SharePoint Feature is a set of provisioning instructions written in XML that tell SharePoint what to do when the feature is activated. You can see a list of example features by clicking the Site Features or Site Collection Features link on the Site Settings page of your site.

To add a feature to your project

  1. Right-click the Features folder and choose Add Feature from the context menu.

    Figure 5. New feature added

    New feature added

  2. Type a user-friendly title and description in the top two text boxes. The values that you specify for the title and the description are displayed on the Web Application Features page in SharePoint Central Administration.

  3. Because this feature registers the job with one of the web applications in your farm, set Scope to WebApplication.

  4. Click the Save button in the toolbar.

Now that you have created and configured the feature, you must add an event receiver to the feature so that you can add the code that is required to register your job. An event receiver is a class that runs code when certain events occur in SharePoint. In this case, you add an event receiver to run code when the feature is activated or deactivated. To add an event receiver, right-click your feature and then choose Add Event Receiver from the context menu.

After you add the event receiver, you must uncomment the FeatureActivated and FeatureDeactivating methods. You can remove the other methods because they are not used. Next, you must add code in the FeatureActivated method to register the job with SharePoint. Finally, you add code in the FeatureDeactivating method to unregister the job. The following code example shows how to register and unregister the MonitoringJob object.

public override void FeatureActivated(
    SPFeatureReceiverProperties properties) {

    // Get an instance of the SharePoint farm.
    SPFarm farm = SPFarm.Local;

    // Get an instance of the service.
    var results = from s in farm.Services
                  where s.Name == "SPSearch4"
                  select s;

    SPService service = results.First();

    // Remove job if it exists.
    DeleteJobAndSettings(service);

    // Create the job.
    MonitoringJob job = new MonitoringJob(
        MonitoringJob.JobName, service);

    // Create the schedule so that the job runs hourly, sometime 
    // during the first quarter of the hour.
    SPHourlySchedule schedule = new SPHourlySchedule();
    schedule.BeginMinute = 0;
    schedule.EndMinute = 15;
    job.Update();

    // Configure the job.
    MonitoringJobSettings jobSettings = new MonitoringJobSettings(
        service, Guid.NewGuid());
    jobSettings.EmailAddress = "myemail@demo.com";
    jobSettings.Update(true);
}

public override void FeatureDeactivating(
    SPFeatureReceiverProperties properties) {

    // Get an instance of the SharePoint farm.
    SPFarm farm = SPFarm.Local;

    // Get an instance of the service.
    var results = from s in farm.Services
                  where s.Name == "SPSearch4"
                  select s;

    SPService service = results.First();

    DeleteJobAndSettings(service);
}

private void DeleteJobAndSettings(SPService service) {
    // Find the job and delete it.
    foreach (SPJobDefinition job in service.JobDefinitions) {
        if (job.Name == MonitoringJob.JobName) {
            job.Delete();
            break;
        }
    }

    // Delete the job's settings.
    MonitoringJobSettings jobSettings =
        service.GetChild<MonitoringJobSettings>(
            MonitoringJobSettings.SettingsName);
    if (jobSettings != null) {
        jobSettings.Delete();
    }
}

In the preceding code example, the FeatureActivated method gets an instance of the SPFarm object by accessing the local static property of the SPFarm class. After that, the SPFarm class's Services property is enumerated to obtain an SPService instance to represent the SharePoint Search service.

Next the FeatureActivated method calls the DeleteJobAndSettings method to remove the job if it already exists. The job might already exist if the feature was previously deployed, but experienced a problem during deactivation. Afterwards, an instance of the job definition is created by passing in the name of the job and an instance of the SPService class. After the job is created, you must set its Schedule property to an instance of the one of the SPSchedule classes described in Table 3.

Table 3. SPSchedule class types

Type

Description

SPMinuteSchedule

Runs the job every x number of minutes. This class can be used to schedule jobs for periods of time other than hour, day, week, month, or year. For example, to run a job every 11 days, use this class and set its Interval property to 15840 minutes.

SPHourlySchedule

Runs the job every hour.

SPDailySchedule

Runs the job daily.

SPWeeklySchedule

Runs the job weekly.

SPMonthlySchedule

Runs the job monthly.

SPYearlySchedule

Runs the job yearly.

In the preceding code example, the SPHourlySchedule class is used to run the job every hour. The properties that begin with Begin and End specify the earliest and latest time, respectively, that the job can start. The Timer service randomly selects a time during that interval to start the job. After you set the Schedule property of your job, call the Update method of the job to register it with SharePoint. The final step in the method is to create an instance of the MonitoringJobSettings class, set its properties, and then save it by calling its Update method.

In the FeatureDeactivating method, the DeleteJobAndSettings method is called to delete the previously registered job. The DeleteJobAndSettings method uses the JobDefinitions property to get a list of the jobs registered for that SPService object and deletes the job the feature previously created. The method also gets the job's configuration and deletes it.

At this point, you are ready to test your code. In the next section, you learn how to test and debug your SharePoint job.

Testing and Debugging Your SharePoint Timer Job

When you debug SharePoint code, you typically set the build type of the project to debug, and then press F5 to debug the project. Visual Studio compiles your code, packages the resulting assembly and XML files into a SharePoint solution package (.wsp) file, and then deploys the solution package to SharePoint. After the solution package is deployed, Visual Studio activates the features that you created.

To debug the timer job

  1. To debug a timer job in SharePoint, you must attach to the process that is behind the SharePoint Timer Service. To attach to the SharePoint Timer Service, select Debug and then choose Attach To Process from the menu bar.

  2. In the Attach To Process dialog box, make sure that the check boxes at the bottom of the dialog box are both checked, and then select OWSTIMER.EXE from the Available Processes list.

    Figure 6. Attach To Process dialog box

    Attach To Process dialog box

  3. Click Attach to finish attaching to the SharePoint Timer Service.

    Now you can add breakpoints in your job code.

To make the job run immediately, you can issue a Windows PowerShell command that causes the SharePoint Timer Service to run your job immediately. To open Windows PowerShell, click All Programs, click Microsoft SharePoint 2010 Products, and then choose SharePoint 2010 Management Shell.

The Windows PowerShell console opens with the SharePoint namespaces already registered. Type the following command on one line, and then press Enter to schedule your job for immediate execution.

Get-SPTimerJob "jobname" -WebApplication "url" | Start-SPTimerJob

In the command line, jobname is the name of your project and url is the URL of your web application. The Get-SPTimerJob command gets the job definition for your job, and the pipe (|) sends the job definition to the Start-SPTimerJob command, which in turn schedules it to run. The SharePoint Timer Service usually takes less than 30 seconds to finish running. If it does not execute, make sure that the debugger is not paused in Visual Studio.

Conclusion

Timer jobs give you the flexibility to offload your long-running or scheduled processes from your Internet Information Services (IIS) sites. Timer jobs are powerful because they can be configured to run on a specific schedule and can include any functionality that you must have to create world-class, SharePoint-based solutions for your enterprise.

About the Author

Bryan Phillips is a senior partner at Composable Systems, LLC, and a Microsoft Most Valuable Professional in SharePoint Server. He is a co-author of Professional Microsoft Office SharePoint Designer 2007 and Beginning SharePoint Designer 2010 and maintains a SharePoint-related blog. Bryan has worked with Microsoft technologies since 1997 and holds the Microsoft Certified Trainer (MCT), Microsoft Certified Solution Developer (MCSD), Microsoft Certified Database Administrator (MCDBA), and Microsoft Certified Systems Engineer (MCSE) certifications.

The following were tech editors on Microsoft SharePoint 2010 articles from Wrox:

  • Matt Ranlett is a SQL Server MVP who has been a fixture of the Atlanta .NET developer community for many years. A founding member of the Atlanta Dot Net Regular Guys, Matt has formed and leads several area user groups. Despite spending dozens of hours after work on local and national community activities, such as the SharePoint 1, 2, 3! series, organizing three Atlanta Code Camps, working on the INETA board of directors as the vice president of technology, and appearing in several podcasts such as .Net Rocks and the ASP.NET Podcast, Matt recently found the time to get married to a wonderful woman named Kim, whom he helps to raise three monstrous dogs. Matt currently works as a senior consultant with Intellinet and is part of the team committed to helping people succeed by delivering innovative solutions that create business value.

  • Jake Dan Attis. When it comes to patterns, practices, and governance with respect to SharePoint development, look no further than Jake Dan Attis. A transplant to the Atlanta area from Moncton, Canada, Dan has a degree in Applied Mathematics, but is 100% hardcore SharePoint developer. You can usually find Dan attending, speaking at, and organizing community events in the Atlanta area, including code camps, SharePoint Saturday, and the Atlanta SharePoint User Group. When he's not working in Visual Studio, Dan enjoys spending time with his daughter Lily, watching hockey and football, and sampling beers of the world.

  • Kevin Dostalek has over 15 years of experience in the IT industry and over 10 years managing large IT projects and IT personnel. He has led projects for companies of all sizes and has participated in various roles including Developer, Architect, Business Analyst, Technical Lead, Development Manager, Project Manager, Program Manager, and Mentor/Coach. In addition to these roles, Kevin also managed a Solution Delivery department as a Vice President for a mid-sized MS Gold Partner from 2005 through 2008 and later also served as a Vice President of Innovation and Education. In early 2010 Kevin formed Kick Studios as a company providing consulting, development, and training services in the specialized areas of SharePoint and Social Computing. Since then he has also appeared as a speaker at numerous user group, summit, and conference type events across the country. You can find out more about Kevin on his blog, The Kickboard.

  • Larry Riemann has over 17 years of experience architecting and creating business applications for some of the world’s largest companies. Larry is an independent consultant who owns Indigo Integrations and does SharePoint consulting exclusively through SharePoint911. He is an author, writes articles for publication and occasionally speaks at conferences. For the last several years he has been focused on SharePoint, creating and extending functionality where SharePoint leaves off. In addition to working with SharePoint, Larry is an accomplished .Net Architect and has extensive expertise in systems integration, enterprise architecture and high availability solutions. You can find him on his blog.

  • Sundararajan Narasiman is a Technical Architect with Content Management & Portals Group of Cognizant Technology Solutions, Chennai, with more than 10 years of Industry Experience. Sundararajan is primarily into the Architecture & Technology Consulting on SharePoint 2010 Server stack and Mainstream .NET 3.5 developments. He has passion for programming and also has interest for Extreme Programming & TDD.

Additional Resources

For more information, see the following resources: