Hi Friends,
There are many articles you will find on internet about Timer Jobs in SharePoint 2010 which is based on web application but not on service. That is the reason i am sharing this article.
Timer job based on web application having one major problem. i.e- Job will not work if that application not worked or crashed or say front end on which web application hosted is down.
Here i will not tell whole story of Timer Job, you will get better information here
A Complete Guide to Writing Timer Jobs in SharePoint 2010
To create timer job based on service or say service application, we will have to do few things, this are below
Steps in detail
1: Open Visual Studio 2010 and create farm based SharePoint Solution (use blank SharePoint Project Template), add class file named CustomTimerJobService.cs, code is below
2: Add feature of scope Site to the solution and then add feature receiver.
Here we will associate timer job to service
There are many articles you will find on internet about Timer Jobs in SharePoint 2010 which is based on web application but not on service. That is the reason i am sharing this article.
Timer job based on web application having one major problem. i.e- Job will not work if that application not worked or crashed or say front end on which web application hosted is down.
Here i will not tell whole story of Timer Job, you will get better information here
A Complete Guide to Writing Timer Jobs in SharePoint 2010
To create timer job based on service or say service application, we will have to do few things, this are below
- Create custom service and add to the local farm
- Create service instance based on above custom service and add this to all the servers in the farm
- Create timer job
- Associate timer job to service
Steps in detail
1: Open Visual Studio 2010 and create farm based SharePoint Solution (use blank SharePoint Project Template), add class file named CustomTimerJobService.cs, code is below
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint.Administration;
namespace CustomTimerJobService
{
[System.Runtime.InteropServices.Guid("6D53ECA1-E5E4-47CF-961F-28D80C8C5B98")]
public class CustomTimerJobService : SPService
{
public const string serviceName = "Custom Timer Job Service";
//private static CustomTimerJobService local;
public CustomTimerJobService() { }
public CustomTimerJobService(SPFarm farm) : base("CustomTimerJobService", farm)
{ }
//public static CustomTimerJobService Local
//{
// get
// {
// if (CustomTimerJobService.local == null)
// {
// CustomTimerJobService.local = SPFarm.Local.Services.GetValue<CustomTimerJobService>("CustomTimerJobService");
// }
// return CustomTimerJobService.local;
// }
//}
public override void Provision()
{
base.Provision();
}
public override string TypeName
{
get
{
return serviceName;
}
}
public override string DisplayName
{
get
{
return serviceName;
}
}
}
}
2: Add class file named CustomTimerJobServiceInstance.cs, code is below
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint.Administration;
namespace CustomTimerJobService
{
public class CustomTimerJobServiceInstance : SPServiceInstance
{
public const string serviceDescription = "Custom Service for service based timer jobs";
public CustomTimerJobServiceInstance() : base()
{ }
public CustomTimerJobServiceInstance(string name, SPServer server, CustomTimerJobService service) : base(name, server, service)
{ }
public override string Description
{
get
{
return serviceDescription;
}
}
}
}
3: Add feature of scope Farm to the solution and then add feature receiver.
Here we will add service to the local farm, then instantiate above service on all the servers in the farm.
Here we will add service to the local farm, then instantiate above service on all the servers in the farm.
using System;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Administration;
namespace CustomTimerJobService.Features.AddTimerJobService
{
[Guid("8daf90a1-df8a-4646-a606-0646498a6242")]
public class AddTimerJobServiceEventReceiver : SPFeatureReceiver
{
public const string serviceName = "Custom Timer Job Service";
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
//1: Add service in local farm
//2: Add service instance of this service on every server in the farm
//Create service definition instance
CustomTimerJobService timerJobService = new CustomTimerJobService(SPFarm.Local);
//Get all services from local farm and add our custom service in farm
SPServiceCollection services = SPFarm.Local.Services;
services.Add(timerJobService);
SPFarm.Local.Update();
//Get all servers in local farm
SPServerCollection servers = SPFarm.Local.Servers;
//Add service instance on all the servers
foreach (SPServer server in servers)
{
//Create new service instance based on our custom service and add in server
CustomTimerJobServiceInstance timerJobServiceInstance = new CustomTimerJobServiceInstance(serviceName, server, timerJobService);
server.ServiceInstances.Add(timerJobServiceInstance);
server.Update();
}
}
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
//1: Remove service instance of this service on every server in the farm
//2: Remove service in local farm
//Get all servers in local farm
SPServerCollection servers = SPFarm.Local.Servers;
foreach (SPServer server in servers)
{
//Remove instance on every server
CustomTimerJobServiceInstance timerJobServiceInstance = server.ServiceInstances.GetValue<CustomTimerJobServiceInstance>();
if (timerJobServiceInstance != null && timerJobServiceInstance.DisplayName.ToString().Equals(serviceName, StringComparison.OrdinalIgnoreCase))
{
server.ServiceInstances.Remove(timerJobServiceInstance.Id);
server.Update();
}
}
//Remove service from the farm
CustomTimerJobService timerJobService = SPFarm.Local.Services.GetValue<CustomTimerJobService>();
if (timerJobService != null)
{
timerJobService.Delete();
SPFarm.Local.Update();
}
}
}
}
Next step is to create timer job and associate it to service
Steps in detail
1: Open Visual Studio 2010 and create farm based SharePoint Solution (use blank SharePoint Project Template), add class file named CustomTimerJob.cs.cs, code is below
Steps in detail
1: Open Visual Studio 2010 and create farm based SharePoint Solution (use blank SharePoint Project Template), add class file named CustomTimerJob.cs.cs, code is below
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
namespace CustomTimerJobDemo
{
public class CustomTimerJob : SPFirstAvailableServiceJobDefinition
{
//If you are taking configuration values from the site where you are going
//to activate this timer job feature then make persisted property
//By doing this we can use it further
[Persisted]
public string configSiteURL = null;
public CustomTimerJob()
: base()
{ }
public CustomTimerJob(string jobName, SPService service, SPSite site)
: base(jobName, service)
{
this.Title = jobName;
this.configSiteURL = site.Url;
}
public override void Execute(SPJobState jobState)
{
if (jobState.ShouldStop != true)
{
this.UpdateProgress(10);
//To Do: Do some activity here
this.UpdateProgress(100);
}
}
}
}
Here we will associate timer job to service
using System;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Deployment;
namespace CustomTimerJobDemo.Features.CustomTimerJobDemo
{
[Guid("a26f0c48-6464-4438-bbd0-35fac5218a0b")]
public class CustomTimerJobDemoEventReceiver : SPFeatureReceiver
{
public const string jobName = "Custom Timer Job for demo";
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
SPSite currentSite = properties.Feature.Parent as SPSite;
//Check current context whether it is a normal feature activation or through any custom deployment job
//Timer job should not be created if feature activation occurs through any custom deployment job
if (!SPImportContext.Current.IsRunning)
{
SPService timerJobService = GetCustomTimerJobService();
if (timerJobService != null)
{
// Remove job if it already associated with the service
foreach (SPJobDefinition job in timerJobService.JobDefinitions)
{
if (job.Name.Equals(jobName, StringComparison.OrdinalIgnoreCase))
{
//Deleting existing job
job.Delete();
}
}
//Create new job here
CustomTimerJob timerJob = new CustomTimerJob(jobName, timerJobService, currentSite);
SPDailySchedule dailySchedule = new SPDailySchedule();
dailySchedule.BeginMinute = 0;
dailySchedule.EndMinute = 59;
dailySchedule.BeginHour = 0;
dailySchedule.EndHour = 12;
timerJob.Schedule = dailySchedule;
timerJob.Update();
}
}
}
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
//Get custom timer service
SPService timerJobService = GetCustomTimerJobService();
if (timerJobService != null)
{
// Remove job
foreach (SPJobDefinition job in timerJobService.JobDefinitions)
{
if (job.Name.Equals(jobName, StringComparison.OrdinalIgnoreCase))
{
//Deleting job
job.Delete();
}
}
}
}
private static SPService GetCustomTimerJobService()
{
SPService timerJobService = null;
string serviceName = "Custom Timer Job Service";
//Get all services from the farm
SPServiceCollection services = SPFarm.Local.Services;
foreach (SPService service in services)
{
if (service.DisplayName.Equals(serviceName, StringComparison.OrdinalIgnoreCase))
{
timerJobService = service;
break;
}
}
if (timerJobService == null)
{
throw new Exception("Service not available. Please check service on servers.");
}
return timerJobService;
}
}
}
This is done now, you can go to central admin and run timer job or it will run based on schedule you configured for it.
Bye Good Day....!