Creating Custom Timer Job for Automations in SharePoint
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, gets a lot of requests to create site collections, Change Owners of the site collections, Increase the Site quota for the existing site collection, and request 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 “Self Service site”) where users will come and fill the above requests in separate lists. Then I wrote .Net console applications, placed them under the task scheduler. The task scheduler will run these executables once a day. Refer to 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, validates, and then and programmatically performs the tasks (such as creating site collections).
Solution:
This time, instead of creating a .Net console application/PowerShell and placing them in the 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. In this way, we can have this as a Solution package.
How to Create a Custom Timer Job in SharePoint?
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 that extends “SPJobDefinition” class inside Microsoft.SharePoint.Administration namespace. Also, we have to create a 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
2. Select the Empty SharePoint Project as project type, Give it a name. say “SPAdmin.QuotaChange.TimerJob”
3. Enter the URL for debugging. Select “Deploy as a Farm solution” since timer jobs are not available in sandbox solutions.
4. Add a new Item to the project
5. Select Class and give it a name, say :QuotaChangeTimerJob.cs
6. Right click on the Features and click on Add 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 |
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("https://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 timer job in central admin |
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”)
Or it can be done by command lines:
net stop SPTimerV4 – It’s 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 breakpoint in code and go to Debug menu, choose Attach to Process
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.
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.
MSDN Link: How to Create a Timer Job – https://msdn.microsoft.com/en-us/library/ff798313.aspx
Very good article
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
very helpful Salaudeen
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 ‘https://it-vtest1:3911’. be25d1e4-e77e-4b89-bca1-976755f7e9f5
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
nice posting.can you please provide the steps to create timer job for creation new site collection automation
Regards,
Ibraheem
Hello Ibrahim,
Here is the code to create site collection programmatically:
string WebAppURL=”https://sharepoint.com”;
string SiteURL=”/sites/Sales”;
string SiteTitle=”Sales”;
string OwnerAccount=”domainuser1″;
string OwnerDomainAccount=”domainuser1″;
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);