· Click on Add.
Timer Job Class Requirements:
· The class must be public.
· It must implement the SPJobDefinition class.
PublicclassCompletedProjectsJob : SPJobDefinition
{
..............
}
· It must have a default constructor.
Public CompletedProjectsJob() : base() { }
· The timer job is scoped at the web application level, so it must define a constructor that accepts an argument of type SPWebApplication.
public CompletedProjectsJob(SPWebApplication webApplication)
: base(jobName, webApplication, null, SPJobLockType.Job)
{
Title = "Completed Projects Job";
}
CompletedProjectsJob.cs
· Replace CompletedProjectsJob.cs with the following code.
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 CustomTimerJob
{
public class CompletedProjectsJob : SPJobDefinition
{
public const string jobName = "CompletedProjectsJob";
public CompletedProjectsJob() : base() { }
public CompletedProjectsJob(SPWebApplication webApplication)
: base(jobName, webApplication, null, SPJobLockType.Job)
{
Title = "Completed Projects Job";
}
public override void Execute(Guid targetInstanceId)
{
SPWebApplication webApp = this.Parent as SPWebApplication;
SPWeb web = webApp.Sites["/sites/test"].RootWeb;
SPList list = web.Lists.TryGetList("Completed Projects");
SPListItem items;
bool flag = true;
SPListItemCollection itemColl = list.Items;
var query = new SPSiteDataQuery();
query.Lists = "<Lists BaseType='0' />";
query.ViewFields = "<FieldRef Name='Title' Nullable='TRUE' />" +
"<FieldRef Name='ProjectStatus' Nullable='TRUE' />" +
"<FieldRef Name='ProjectID' Nullable='TRUE' />" +
"<FieldRef Name='FileRef' Nullable='TRUE' />";
query.Query = "<Where>" +
"<Eq>" +
"<FieldRef Name='ProjectStatus' />" +
"<Value Type='Choice'>Completed</Value>" +
"</Eq>" +
"</Where>";
query.Webs = "<Webs Scope='SiteCollection' />";
DataTable dt = web.GetSiteData(query);
foreach (DataRow row in dt.Rows)
{
items = list.Items.Add();
if (itemColl.Count != 0)
{
foreach (SPListItem item in itemColl)
{
if (item["ProjectID"].ToString() == row["ProjectID"].ToString())
{
flag = false;
break;
}
else
{
flag = true;
}
}
if (flag == true)
{
items["Title"] = row["Title"].ToString();
items["ProjectStatus"] = row["ProjectStatus"].ToString();
items["ProjectID"] = row["ProjectID"];
items.Update();
list.Update();
}
}
else
{
items["Title"] = row["Title"].ToString();
items["ProjectStatus"] = row["ProjectStatus"].ToString();
items["ProjectID"] = row["ProjectID"];
items.Update();
list.Update();
}
}
}
}
}
Registering the timer job:
· To register a timer job, create a feature and use the event receiver to register the timer job.
· Right click on the Features folder and click on "Add Feature".
· Change the feature name as "Completed Projects Job Feature".
· Change the scope to "Web Application".
· Right click on "Completed Projects Job Feature" and click on "Add Event Receiver".
· My solution looks like the following.

· Replace "Completed Projects Job Feature.EventReceiver.cs" with the following code.
using System;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Administration;
namespace CustomTimerJob.Features.Completed_Projects_Job_Feature
{
[Guid("a19d07a5-bb92-4e5f-8086-b6eee82e9cb2")]
public class Completed_Projects_Job_FeatureEventReceiver : SPFeatureReceiver
{
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
SPWebApplication webApp = properties.Feature.Parent as SPWebApplication;
DeleteJob(webApp.JobDefinitions);
CompletedProjectsJob tasksTimerJob = new CompletedProjectsJob(webApp);
SPMinuteSchedule schedule = new SPMinuteSchedule();
schedule.BeginSecond = 0;
schedule.EndSecond = 59;
schedule.Interval = 1;
tasksTimerJob.Schedule = schedule;
tasksTimerJob.Update();
}
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
SPWebApplication webApp = properties.Feature.Parent as SPWebApplication;
DeleteJob(webApp.JobDefinitions);
}
private void DeleteJob(SPJobDefinitionCollection jobs)
{
foreach (SPJobDefinition job in jobs)
{
if (job.Name.Equals(CompletedProjectsJob.jobName,
StringComparison.OrdinalIgnoreCase))
{
job.Delete();
}
}
}
}
}