What is the Timer Job???
Timer Job is a background process that is run by SharePoint. In Central Administration, select Monitoring link from the main page, and then select Review job definitions link under the Timer Jobs section, then you will see the list of scheduled timer job definitions
How to Create a Custom Timer Job??
Problem
Execute code in SharePoint at every 15 minutes and adds a new record to the Task list.
Solution
Need to create a Timer job that will run automatically every 15 minutes. Following are the steps to create a custom timer job definition and deploy it.
Creating Job Definition Class
Step 1
Create an empty SharePoint project from visual studio 2010 or 2012 and give the name TimerJobApplication. You can give any name to this project but here in our example, we are using this name. Press OK and select "Deploy as Farm Solution"
Step 2
Add a new class to the project and give the name CustomTimerJob.cs. You can give any name to this class but here in our example, I am using this name.
To do this, right click on the project name in solution explorer, select Add -> New Item. Under C# category select Code tab, select Class and give the class name.
TimerJobApplication -> Add -> New Item -> Class
Step 3
Derive this from class
CustomTimerJob
SPJobDefinition
.
You need to add the following statements to do this.
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
public class CustomTimerJob : SPJobDefinition
{}
Step 4
Add following 3 constructors to your class.
public CustomTimerJob() : base() { }
public CustomTimerJob(string jobName, SPService service):
base(jobName, service, null, SPJobLockType.None)
{
this.Title = "Task Complete Timer";
}
public CustomTimerJob(string jobName, SPWebApplication webapp):
base(jobName, webapp, null, SPJobLockType.ContentDatabase)
{
this.Title = "Task Complete Timer";
}
Step 5
Override the
Execute()
method to do your stuff. Whenever timer job executes, it will run the code written inside the Execute()
method.public override void Execute(Guid targetInstanceId)
{
SPWebApplication webApp = this.Parent as SPWebApplication;
SPList taskList = webApp.Sites[0].RootWeb.Lists["Tasks"];
SPListItem newTask = taskList.Items.Add();
newTask["Title"] = "New Task" + DateTime.Now.ToString();
newTask.Update();
}
Here in our example, a new record will be added to
Tasks
list whenever the timer job gets executes.You can write your own logic here.
Following is the complete code file for the class.
CustomTimerJob
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using System.Data;
using System.IO;
namespace TimerJobApplication
{
public class CustomTimerJob : SPJobDefinition
{
public CustomTimerJob() : base() { }
public CustomTimerJob(string jobName, SPService service)
: base(jobName, service, null, SPJobLockType.None)
{
this.Title = "Task Complete Timer";
}
public CustomTimerJob(string jobName, SPWebApplication webapp)
: base(jobName, webapp, null, SPJobLockType.ContentDatabase)
{
this.Title = "Task Complete Timer";
}
public override void Execute(Guid targetInstanceId)
{
SPWebApplication webApp = this.Parent as SPWebApplication;
SPList taskList = webApp.Sites[0].RootWeb.Lists["Tasks"];
SPListItem newTask = taskList.Items.Add();
newTask["Title"] = "New Task" + DateTime.Now.ToString();
newTask.Update();
}
}
}
Registering Timer Job Definition
Step 6
Add a new feature to register our custom timer job.
To do this, right click on Features inside project in solution explorer and click "Add Feature".
Rename this feature to CustomTimerJobFeature.
Give Scope this feature to "Web Application".
For this, double click on CustomTimerJobFeature and choose scope "Web Application". Now press F4 so it will open property window of feature. Select False in "Activate on Default".
The reason behind selecting False is that we have to give feature scoped web application level and we don't want to activate this for all application. You have to activate this feature for the application for which you want to register a timer job.
Step 7
Add Feature event receiver for this feature.
Right click on
CustomTimerJobFeature
and select "Add Event Receiver".
Write the following code to CustomTimerJobFeatureEventReceiver.cs class.
using System;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Administration;
namespace TimerJobApplication.Features.CustomTimerJobFeature
{
[Guid("e6ea0027-1187-419d-b357-306244d0ae37")]
public class CustomTimerJobFeatureEventReceiver : SPFeatureReceiverimer
{
const string JobName = "New Task Timer";
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
try
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
SPWebApplication parentWebApp = (SPWebApplication)properties.Feature.Parent;
SPSite site = properties.Feature.Parent as SPSite;
DeleteExistingJob(JobName, parentWebApp);
CreateJob(parentWebApp);
});
}
catch (Exception ex)
{
throw ex;
}
}
private bool CreateJob(SPWebApplication site)
{
bool jobCreated = false;
try
{
CustomTimerJob job = new CustomTimerJob(JobName, site);
SPMinuteSchedule schedule = new SPMinuteSchedule();
schedule.BeginSecond = 0;
schedule.EndSecond = 59;
schedule.Interval = 15;
job.Schedule = schedule;
job.Update();
}
catch (Exception)
{
return jobCreated;
}
return jobCreated;
}
public bool DeleteExistingJob(string jobName, SPWebApplication site)
{
bool jobDeleted = false;
try
{
foreach (SPJobDefinition job in site.JobDefinitions)
{
if (job.Name == jobName)
{
job.Delete();
jobDeleted = true;
}
}
}
catch (Exception)
{
return jobDeleted;
}
return jobDeleted;
}
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
lock (this)
{
try
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
SPWebApplication parentWebApp = (SPWebApplication)properties.Feature.Parent;
DeleteExistingTimerJobFromSite(this.JobName, parentWebApp);
});
}
catch (Exception ex)
{
throw ex;
}
}
}
}
}
You can create different schedules as per your requirements. Here we have created
SPMinuteSchedule
for executing our job at every 15 minutes.
Other schedules you can also use as per your requirements. Following is the list of schedules.
Class Name | Recurrence |
SPYearlySchedule | Runs the timer job once per year |
SPMonthlySchedule | Runs the timer job once per month on the specified day. For example, the 15 of the month |
SPMonthlyByDaySchedule | Runs the timer job once per month on the specified day and week. For example, the 3rd Friday of the month |
SPWeeklySchedule | Runs the timer job once per week |
SPDailySchdedule | Runs the timer job once every day |
SPHourlySchedule | Runs the timer job once every hour |
SPMinuteSchedule | Runs the timer job once every n minutes where n is the value in the Interval property |
SPOneTimeSchedule | Runs the timer job once |
Deploying and Debugging
Right click on the project name in your solution explorer and select Deploy.
After successfully deployed, you need to activate the feature manually because we have set the property "Activate on Default" to False.
Open Central Administration and select manage web application.
Select your web application and on ribbon control select "Manage Feature" tab then you will see the pop-up window displaying all your application scoped features.
Find the feature that we have created here and activate it.
Find the feature that we have created here and activate it.
When the feature is activated, your timer job will be registered.
To see the list of all registered timer jobs, Go to central administration and select "Monitoring" section.
To see the list of all registered timer jobs, Go to central administration and select "Monitoring" section.
Select "Review Job Definitions".
You will be able to see all registered timer job. In this list, you will also find our custom timer job listed.
Your code written in
Execute()
method will start executing at every 15 minutes (or whatever schedule you have set).Debugging Timer job
Debugging timer job is quite different than debugging normal C# code. You need to attach "OWSTIMER.EXE".
To do this, after deploying the project, whenever you want to debug
You can also open this dialog box manually from the Debug menu. Debug -> Attach to Process
Execute()
method, press CTRL+ALT+P and select the process "OWSTIMER.EXE" and click Attach.You can also open this dialog box manually from the Debug menu. Debug -> Attach to Process
Now, put the break-point at
Execute()
method so whenever your timer job executes, you can debug the code.
If you don't want to wait for timer job to be executed (15 minutes in our case), for testing purpose you can run timer job immediately from central administration.
To do this select timer job listed in all Job Definitions and it will give you an option to "Run" or "Disable" job as well as you can also set a time schedule.
To do this select timer job listed in all Job Definitions and it will give you an option to "Run" or "Disable" job as well as you can also set a time schedule.
Important Note
- Note that, whenever you change the logic or code inside
Execute()
method, you must restart the Timer service from Services.msc. - If you just deploy without restarting service, it will not take your latest updates. So always have practice to restarting the "SharePoint Timer Service" from Services.msc.
- If you still face any problem registering or deploying timer job, try uninstalling your assembly and restart the IIS and then deploy again.
- To uninstall assembly, in "Run" type "assembly" and press enter. In the list of assemblies, you will see the assembly of your project name. Select that and uninstall by right click.
- To restart IIS, in "Run" type iisreset and press Enter.
What is SPjobLockType?
Use the LockType property to prevent the same job from simultaneously running on multiple machines and processing the same data.
Architecture:
There are 8 Servers, in these servers
1 Database Server
1 Mail Server
2 Web-FrontEnds
4 App Servers (out of which one is the Central Admin and also a Web Frontend)
Observation:
If you take a look at the Job Status in the Operations tab of the Central Admin, we can see that some jobs are running 6 instances, some 3 and some 1 instance.
The number of instances is controlled by the SPJobLockType parameter, that has to be passed to your job constructor.
For a guide to creating custom jobs refer Andrew Connell's article http://www.andrewconnell.com/blog/articles/CreatingCustomSharePointTimerJobs.aspx )
There are 3 LockTypes available.
If you take a look at the Job Status in the Operations tab of the Central Admin, we can see that some jobs are running 6 instances, some 3 and some 1 instance.
The number of instances is controlled by the SPJobLockType parameter, that has to be passed to your job constructor.
For a guide to creating custom jobs refer Andrew Connell's article http://www.andrewconnell.com/blog/articles/CreatingCustomSharePointTimerJobs.aspx )
There are 3 LockTypes available.
- SPJobLockType.None -- if you set it none, the instance will run in all the available servers in the Farm (e.g. Application Server Timer Job)
- SPJobLockType.ContentDatabase – this will cause 3 instances to be running in each of the Web-Frontends.
- SPJobLockType.Job – this will cause only one instance of the job to run on any of the front-end servers. (Note: it is possible to see multiple instances listed in the Job Status .. but if you look at the time it was the last run.. only one would have run lately)
If you have to develop a job, you have to first decide on the type of lock you need for your job.
E.g. If your job does something with the files in the Web-Frontend server you might want to use a ContentDatabase lock.. or if you have something that manipulates the data in a list.. you will have to use Job lock.
Note: If you use other types of locks to manipulate the data in a list.. the multiple job instances will run simultaneously and cause Data Update conflict errors.
Note: If for any reason you re-deploy your job.. either put the dll directly in GAC or deploysolution.. make sure you restart the 'Windows Sharepoint Services Timer' service. (OWSTIMER.EXE)
E.g. If your job does something with the files in the Web-Frontend server you might want to use a ContentDatabase lock.. or if you have something that manipulates the data in a list.. you will have to use Job lock.
Note: If you use other types of locks to manipulate the data in a list.. the multiple job instances will run simultaneously and cause Data Update conflict errors.
Note: If for any reason you re-deploy your job.. either put the dll directly in GAC or deploysolution.. make sure you restart the 'Windows Sharepoint Services Timer' service. (OWSTIMER.EXE)
Note: The account used by the Timer service should have access to the Content Database.
No comments:
Post a Comment