Monday, May 14, 2012

Creating Custom Timer Job for Automations in SharePoint 2010

Business Scenario:

We have a Project collaboration environment with 5000+ site collections. This environment has been primarily used for managing project artifacts by various teams. Every day, We - Admin Team, get lot of requests to create site collections, Change Owners of the site collections, Increase the Site quota for the existing site collection and requests for deleting site collections once the project is closed.

Earlier, as part of process automation, what I've done is: Created a dedicated site collection (Named it as "Self Service site") where users will come and fill the above requests in separate lists. Then I wrote  .Net console applications, placed them under task scheduler. The task scheduler will run these executable once a day. Refer my old posts for the process flow and complete code.
When the End-user fills the request forms (Say, Request for creating a new site collection), We capture the related details such as Site Name, URL, Site Primary & Secondary Owners, Purpose of the site, Site's category,etc. My .Net console application reads the pending requests, validate and then and programmatically perform the tasks (such as creating site collections). 


Solution:

This time, instead of creating a .Net console application/PowerShell and placing them in Task scheduler, Why don't we create a custom SharePoint timer job to do the automation? Alright, I decided to make use of SharePoint 2010's custom timer jobs. By this way, we can have this as a Solution package. 

How to Create a Custom Timer Job in SharePoint 2010?

What is Timer Job? As per MSDN: "A timer job runs in a specific Windows service for SharePoint. Timer jobs also perform infrastructure tasks for the Timer service, such as clearing the timer job history and recycling the Timer service; and tasks for Web applications, such as sending e-mail alerts. A timer job contains a definition of the service to run and specifies how frequently the service is started."

What we need to get a Custom timer job created?

1. Custom Timer Job Class:
Custom timer jobs are created by creating a class which extends "SPJobDefinition" class inside Microsoft.SharePoint.Administration namespace. Also we have to create few constructors and override the Execute() method.

2. Feature Receiver:
To associate the timer job with web application and delete it when we don't need it anymore, we'll have to deal with these two event receiver methods.
  • featureActivated event - To instantiate the timer job created. Assign a schedule for it.
  • featureDeactivating event - To delete the timer job when the feature is deactivated.

Step by Step Instructions to Create a Custom Timer Job:

Here is the step by step procedure to create a custom timer job for SharePoint 2010 using Visual Studio 2010. 

1. Create a new Project in Visual studio
sharepoint 2010 create timer job
2. Select the  Empty SharePoint Project as project type, Give it a name. say "SPAdmin.QuotaChange.TimerJob"
sharepoint 2010 create timer job c#
3. Enter the URL for debugging. Select "Deploy as a Farm solution" since timer jobs are not available in sandbox solutions.
sharepoint 2010 create timer job programmatically
 4. Add a new Item to the project
sharepoint 2010 create timer job visual studio
 5. Select Class and give it a name, say :QuotaChangeTimerJob.cs
sharepoint 2010 create custom timer job
 6. Right click on the Features and click on Add Feature.
sharepoint 2010 timer job feature
 7. Add an event receiver to the project. Set the title, Description and Scopes for the Project.
 Now the project structure will be like this.
sharepoint 2010 timer job feature scope
SharePoint 2010 timer job feature scope

8. Now, the Most important part: Update the code for Custom timer job Class and Feature Receivers as below:

Update the Class File: (create SharePoint 2010 custom timer job coded in c#)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;

namespace SPAdmin.QuotaChange.TimerJob
{
    //Timer job Class should be public
    public class QuotaChangeTimerJob : SPJobDefinition
    {
        public const string JOB_NAME = "QuotaChangeTimerJob";

        //Create necessary Constructors
        public QuotaChangeTimerJob() : base() { }

        public QuotaChangeTimerJob(SPWebApplication webApp)
            : base(JOB_NAME, webApp, null, SPJobLockType.ContentDatabase)
        {
            // Assign the title
            this.Title = "Quota Change Timer Job";
        }

        //Override the Execute method
        public override void Execute(Guid targetInstanceId)
        {
            try
            {
                //SPWebApplication webApp = this.Parent as SPWebApplication;

                //Temporary Code placed to Test the timer job - Insert new item to Task List
                SPSite oSPSite = new SPSite("http://sharepoint");
                SPWeb oSPWeb = oSPSite.RootWeb;
                oSPWeb.AllowUnsafeUpdates = true;

                SPList taskList = oSPWeb.Lists["Tasks"];
                SPListItem newTaskItem = taskList.Items.Add();
                newTaskItem["Title"] = DateTime.Now.ToString();
                newTaskItem.Update();

                oSPWeb.AllowUnsafeUpdates = false;

                //Method to Handle the Quota change Automation
                // HandleQuotaChangeRequests();
            }
            catch (Exception ex)
            {
                System.Diagnostics.EventLog.WriteEntry("Quota Change Timer Job", ex.Message);
            }

        }
    }
}

9. We have our timer job ready. Next step? Associate the timer job using feature activation code.

Update the Feature Receiver Code:
using System;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;

namespace SPAdmin.QuotaChange.TimerJob.Features.ProcessQuotaRequests
{
   
    [Guid("5c0c3568-31c4-4f1e-800f-690a2e499c5c")]
    public class SPAdminQuotaChangeTimerJobEventReceiver : SPFeatureReceiver
    {
       const string JOB_NAME = "QuotaChangeTimerJob";

        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            // create the timer job when the feature is activated
            SPWebApplication webApp = properties.Feature.Parent as SPWebApplication; // get the web application reference

            // Delete the job, If its already created
            foreach (SPJobDefinition job in webApp.JobDefinitions)
                if (job.Name == JOB_NAME)
                {
                    job.Delete();
                }

            //Create the timer job by creating the instance of the class we have created
            QuotaChangeTimerJob customTimerJob = new QuotaChangeTimerJob(webApp);

            // Create a schedule interval for timer job
            SPMinuteSchedule customSchedule = new SPMinuteSchedule();  // You can create Hourly, Daily,  Weekly schedules as well
            customSchedule.BeginSecond = 0;
            customSchedule.EndSecond = 59;
            customSchedule.Interval = 15;  //Run every 15 minutes

            // assign the schedule to the timer job
            customTimerJob.Schedule = customSchedule;
            customTimerJob.Update(); 

        }


      public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
       {
        SPWebApplication webApp = properties.Feature.Parent as SPWebApplication;

        foreach (SPJobDefinition job in webApp.JobDefinitions) 
            { 
             if (job.Name == JOB_NAME)
                {
                     job.Delete();
                 }
             }
        }
    
    }
    }
Build and Deploy the project.

10. Verify the timer job created in Central Admin:
Go to Go to central administration  >> Monitoring >>  Timer Jobs >> Review Job Definitions
and you should See our Custom Timer Job "Quota Change Timer Job"
sharepoint 2010 how to create timer job
SharePoint 2010 timer job in central admin
sharepoint 2010 timer job frequency
SharePoint 2010 timer job interval
Click on the timer job "Quota Change Timer Job" to get into the properties page of it. From here, we can change the interval parameter, Enable/Disable or run the timer job on demand.


Debugging:

Important: If you make changes to your code, you need to restart the SharePoint Timer service. Which can be done by restarting SharePoint Timer job from Services console (Go to Run >> Type "Services.msc")
sharepoint 2010 timer job restart

Or it can be done by command lines:

net stop SPTimerV4 – Its' good to add this in Pre-build command in visual studio.
net start SPTimerV4 – Add this as Post build command

How to Debug Custom Timer Job:
Set a break point in code and go to Debug menu, choose Attach to Processsharepoint 2010 timer job debug 
Select the OWSTIMER.EXE process(Make sure you have both the Show Process from All users and Show Process in All sessions checked) and click on Attach.
sharepoint 2010 custom timer job visual studio
debug SharePoint 2010 timer job

Click on Run now button from Timer job's property page in Central Administration, Now visual studio will take you to the code where you set break-point.sharepoint 2010 timer job tutorial

 MSDN Link: How to Create a Timer Job - http://msdn.microsoft.com/en-us/library/ff798313.aspx



You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


Check out these SharePoint products:

7 comments :

  1. nice posting.can you please provide the steps to create timer job for creation new site collection automation

    Regards,
    Ibraheem

    ReplyDelete
    Replies
    1. Hello Ibrahim,

      Here is the code to create site collection programmatically:
      string WebAppURL="http://sharepoint.com";
      string SiteURL="/sites/Sales";
      string SiteTitle="Sales";
      string OwnerAccount="domain\user1";
      string OwnerDomainAccount="domain\user1";
      string OwnerEMail="user@domain.com";
      //Get web app
      SPWebApplication WebApp = SPWebApplication.Lookup(new Uri(WebAppURL));
      //Create the site collection
      SPSiteCollection siteCollection = WebApp.Sites;
      SPSite site = siteCollection.Add(SiteURL, SiteTitle, null, 1033, "STS#0", OwnerAccount, OwnerDomainAccount, OwnerEMail);

      Delete
  2. very helpful Salaudeen

    ReplyDelete
  3. I have a question though....
    I created the timer job and ran it. I deleted the list, and gave a new list name in the code to update in other list that I have made. It didn't work this time. When I checked the logs it still searching for the old listname which I have deleted. So, I went to Services.msc and restarted the Timerjob service but it still doesn't update.
    Here is the log
    08/06/2013 13:53:31.70 OWSTIMER.EXE (0x1B34) 0x1844 SharePoint Foundation Timer 6398 Critical The Execute method of job definition TimerJob.ListTimerJob (ID 476a6c3c-250d-4896-a107-e3f7e7df903f) threw an exception. More information is included below. List 'Roster' does not exist at site with URL 'http://it-vtest1:3911'. be25d1e4-e77e-4b89-bca1-976755f7e9f5

    ReplyDelete
    Replies
    1. If your custom timer job caches old code, even after Restarting SharePoint timer job, Change your assembly version in the code! you can also try clearing SharePoint configuration cache if that doesn't solve the problem.

      Clear SharePoint configuration Cache

      Delete
  4. Hello,
    Nice article on timer job.
    I am trying to write timer job similar to yours but I am very new to all these.
    Can you please let me know the steps to write custom timer job to sync AD groups with SharePoint list periodically?
    Thanks

    ReplyDelete

Please Login and comment to get your questions answered!

You might also like:

Related Posts Plugin for WordPress, Blogger...