Timer job in SharePoint for specific site

Timer job in SharePoint for specific site
7 votes, 4.14 avg. rating (83% score)

Introduction

In this post we will see how to create Timer job in SharePoint 2007 / SharePoint 2010.
What are the points that are covered

  • Creating custom Timer job
  • How to execute Timer job for a specific site (without changes to web config and without any static siteurl)
  • How to pass values to property bag of Timer job from feature

SharePoint Timer Job




The following code creates Timerjob class that inherits from SPJobDefinition

using System;
using System.Collections.Generic;
using System.Web;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint;

namespace TestSharepointProject
{
    public class TimerJob : SPJobDefinition
    {
        SPWeb mySiteWeb;
        string mySiteUrl = "";
        public TimerJob(SPWebApplication webApp): base("TimerJob", webApp, null, SPJobLockType.ContentDatabase) 
        {
            this.Title = "TimerJob";
        }
        public TimerJob():base()
        {
        }
        public override void Execute(Guid targetInstanceId)
        {
            if (!string.IsNullOrEmpty(this.Properties["mySiteUrl"].ToString()))
            {
                mySiteUrl = this.Properties["mySiteUrl"].ToString();
            }

            if (!string.IsNullOrEmpty(mySiteUrl))
            {
                using (SPSite mySite = new SPSite(mySiteUrl))
                {
                    using (mySiteWeb = mySite.OpenWeb())
                    {
                        //provide your logic here for the site
                    }
                }
            }

        }
    }
}

In the above code,the timer job is getting property “mySiteUrl” and creating the site object. The default constructor is required as in the above code, otherwise error will come.

Now our timer job class is ready and we will see how we can add key value pairs in the property bag of our custom timer job class.
Create a feauture “TimerJobFeatureReceiver” with scope as web. Following is the code for the feauture reciever which adds key values.

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

namespace TestSharepointProject
{
    public class TimerJobFeatureReceiver : SPFeatureReceiver
    {
        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            try
            {
                
                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    SPWeb web = properties.Feature.Parent as SPWeb;
                    web.AllowUnsafeUpdates = true;
                    SPWebApplication webApp = web.Site.WebApplication;
                    foreach (SPJobDefinition job in webApp.JobDefinitions)
                        if (job.Name == "TimerJob") job.Delete();

                    string key = "mySiteUrl";
                    string value = web.Url;

                    TimerJob tmrJob = new TimerJob(webApp);
                    //remove the key if already exists
                    bool isKeyExists = tmrJob.Properties.ContainsKey(key);
                    if (isKeyExists)
                    {
                        tmrJob.Properties.Remove(key);
                    }
                    tmrJob.Properties.Add(key, value);
					SPMinuteSchedule schedule = new SPMinuteSchedule();
                    schedule.BeginSecond = 0; //to start immediately
                    // schedule.EndSecond = 59; //use this if timer job is to end after some seconde
                    schedule.Interval = 60; //number of minutes
                    tmrJob.Schedule = schedule;
                    tmrJob.Update();

                    web.AllowUnsafeUpdates = false;
                });
            }
            catch (Exception ex)
            {
                //log exception if any
            }
        }

        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            try
            {
                //remove the scheduled job
                SPSecurity.RunWithElevatedPrivileges(delegate()
                 {
                     SPWeb web = properties.Feature.Parent as SPWeb;
                     web.AllowUnsafeUpdates = true;
                     SPWebApplication webApp = web.Site.WebApplication;
                     foreach (SPJobDefinition job in webApp.JobDefinitions)
                         if (job.Name == "TimerJob") job.Delete();
                     web.AllowUnsafeUpdates = false;
                 });
            }
            catch (Exception ex)
            {
                //log exception if any
            }
        }
    }
}

One generic way I generally prefer is; create a custom list. Provide key value columns in the list.
Read the custom list in feature acitvation event and add those values in the timerjob property bag. In this way we can maintain config values to
timer job without any changes to web.config just to read some key values.

Remarks

Make sure that the user with whom we are activating the feature should have valid permission as the code is dealing with timer job.
We may encounters some errors like

Access denied.
at Microsoft.SharePoint.Administration.SPPersistedObject.Update()
at Microsoft.SharePoint.Administration.SPJobDefinition.Update()
at Pages.SurveyFeatureReceiver.<>c__DisplayClass1.b__0()

Its suggestable to activate the feature from command prompt and we won’t be getting the above though both are running with same user.

Following is the quick code to activate or deactivate the feature by stsadm
Activating the feature
stsadm -o activatefeature -fileName TimerJobFeatureReceiver\Feature.xml -url http://adicodes/sites/mysite -force

Deactivating the feature
stsadm -o deactivatefeature -fileName TimerJobFeatureReceiver\Feature.xml -url http://adicodes/sites/mysite -force

Conclusion

Also don’t forget to check the common errors and resolutions that occur in timer job. It save lot of time to fix the frequent errors
that come up timer job.
Hope you understand how to create timer job in SharePoint and how to pass properties to run for a specific site.

AdiCodesCoverage
Creating Custom Timer Job in SharePoint 2010
SharePoint 2010 Timer Job Item
Timer Jobs in SharePoint 2010
Timer Jobs in SharePoint 2007
Timer Jobs in SharePoint
Developing Custom Timer Job in SharePoint

June 13, 2012 В· Adi В· 7 Comments
Posted in: Sharepoint 2007, Sharepoint 2010

7 Responses

  1. phq - December 7, 2012

    Thanks, that’s what I was looking for! Now my timer job got the right site url :)
    Would you mind if i link your post on my blog?
    Cheers!

  2. Adi - December 7, 2012

    No worries, you can post my link in your blog

  3. Deploy custom SharePoint timer job with site url in property bag | phq.be devblog - December 7, 2012

    […] on / credits to: ADI CODES This entry was posted in Sharepoint 2007 and tagged property bag, sharepoint 2007, site url, […]

  4. Kaushik - November 13, 2013

    thanks for the code.

    can we get the currentuser?
    while debugging i’m getting the system account.
    what if i need the currect logged in user?

  5. Adi - November 13, 2013

    Hi Kaushik,

    Glad that the code helped you. For your question, timer job is an independent one. We cannot get SPContext in it.
    If you check “SharePoint 2010 Timer” service under services.msc, it is the user “log on as” the value you get for the user identity.

    may be this scenario will help you to understand, I have set the timer job to run everyday at 11:00pm. The code will run automatically at that time and it will be running under only one user context.

    I generally use the below method to get the user with which timer job is running

    private string GetContextUser()
            {
                string _timerJobUser = @"SHAREPOINT\System";
                try
                {
    
                    string httpContextUser = ((HttpContext.Current != null) && (HttpContext.Current.User != null) && (HttpContext.Current.User.Identity != null)) ?
                    HttpContext.Current.User.Identity.Name : string.Empty;
                    string windowsIdentity = (WindowsIdentity.GetCurrent() != null) ? WindowsIdentity.GetCurrent().Name : string.Empty;
                    if (!(string.IsNullOrEmpty(httpContextUser)))
                    {
                        _timerJobUser = httpContextUser;
                    }
                    else if ((string.IsNullOrEmpty(httpContextUser)) && (!string.IsNullOrEmpty(windowsIdentity)))
                    {
                        _timerJobUser = windowsIdentity;
                    }
                }
                catch (Exception ex)
                {
                    //log it before throwing
                    throw (ex);
                }
    
                return _timerJobUser;
    
            }
    

    Hope this help. If you can let me know your scenario, I can give more info :)

    Regards,
    Adi

  6. Varun - April 30, 2015

    A little late to the party but needed some help.

    I used your code above for my task of Updating my list column “Status”. Updating its value value from “Scheduled” to “Pending” as per the date and time set by the user from the front end and the timer job running every hour.

    All help will be appreciated thank you.

  7. samolpp - June 30, 2017

    will this work for SP 2013?
    this is how my current code looks like:
    public override void Execute(Guid targetInstanceId)
    {
    SPWebApplication webApp = this.Parent as SPWebApplication;

    string strwebappname = webApp.Name.ToString();

    // PRASAD ON 25-APRIL-2017 2-PM
    // NOW RUN THE JOB for UNFREEZING THE ITEMS IN CASE THE FIRST CAML QUERY FAILS
    //commenting just for testing on 11-may-2017 2pm

    //SPSite npdSiteCollec= webApp.

    SPList objListProjRequest = webApp.Sites[0].RootWeb.Lists.TryGetList(“ProjectRequest”);

    }
    but we are getting the issue , this timer is running multiple times.
    we have 2content dbs attached and its running 4 times.
    how to fix this issue?
    will your above code fix my critical issue?

Leave a Reply

What is 7 + 2 ?
Please leave these two fields as-is:
IMPORTANT! To be able to proceed, you need to solve the following simple math (so we know that you are a human) :-)