One of the core building blocks when designing solutions for SharePoint is Timer Jobs. These have been a part of the core product for many years now. Microsoft themselves use these within SharePoint for most of the long running processes as well as what I would call the “heavy lifting” elements of SharePoint. An example would be things like content type syndication which utilizes multiple jobs for pushing the content types, as well as the subscriber jobs allow the content types to be bought down to the site. The normal time you would interact with timer jobs is when you would be deploying a Solution (WSP), as that is how the components are deployed within SharePoint.
Timer Jobs are not simple things to create, as they run out of the context of the core Internet Information Server (IIS) Process known as “w3wp.exe”. In fact, they run within a component called “owstimer.exe” which is a separate service in its own right. Timer Jobs are a necessity for certain types of features and functions that you need within a SharePoint solution.
If we open up Central Administration you can see the list of Timer Jobs, called Definitions that are available.
Central Administration has a Timer Job Status page on which you can check the status of a timer job and a Job Definitions page on which you can edit the timer job definition. You can also review job definitions to see a list of all timer jobs, or click check job status to see scheduled and running timer jobs.
On the Timer Job Status page, on the View menu, you can filter the timer jobs at the following levels:
- All - Displays all timer jobs for the farm.
- Service - Displays all the timer jobs for a particular service. If you select this option, use the Service menu to select the service by which you want to filter the listed jobs.
- Web Application - Displays all the timer jobs for a web application. If you select this option, use the Web Application menu to select the web application by which you want to filter the listed jobs.
- Server - Displays all the timer jobs for the specified server. If you select this option, use the Server menu to select the server by which you want to filter the listed jobs.
- Job Definition - Displays all the timer jobs for the specified job definition. On the Timer Job Status page, open the Job Definition menu, and then click Change Job Definition to get a list of job definitions.
- Failed Jobs - Displays all the timer jobs on the farm that failed to finish.
Based on the filtering you can also see that timer jobs can be scoped at different levels, which means we can have the timer jobs available as needed and run our custom code only where we need it.
Writing Timer Jobs is not complicated it just takes time to understand what code to use and what is allowed. All timer jobs stem from the “SPJobDefinition” class, which is all that is needed to generate one. To create a time job, you simply add an empty class and add the following statements:
The core class then needs to inherit from the “SPJobDefinition” class, with the following method added (if my class was called “CustomTimerJob”).
public CustomTimerJob(string jobName, SPService service) : base(jobName, service, null, SPJobLockType.None)
public CustomTimerJob(string jobName, SPWebApplication webapp) : base(jobName, webapp, null, SPJobLockType.ContentDatabase)
These three methods are where our settings will go for the timer job, next we need to override the “Execute” method which will contain code that does whatever we need it to do, whether it is heavy lifting code for SharePoint if it does something else outside of SharePoint. Now that is not all of it, as the class by itself will do nothing. Next we need to add a feature to the project, along with a feature receiver so that we can associate the timer job with something that is activated.
Within the feature receiver we can now set the properties of when the timer job should run as well as any other settings we need. This call will contain the feature activation method which we will then utilize to add or remove our custom timer job. Adding the timer job is simple using code like this:
CustomTimerJob job = new CustomTimerJob (JobName, site);
SPMinuteSchedule schedule = new SPMinuteSchedule();
schedule.BeginSecond = 0;
schedule.EndSecond = 59;
schedule.Interval = 15;
job.Schedule = schedule;
This code sets our custom timer job to run hourly and ensure it gets listed within Central Administration within the category we have defined. Once this code is compiled and deployed you will then be able to see your custom timer job listed and then enable, disable or run the timer job as needed.
Timer Jobs are great as they give us a scheduling process for any code that you may need within a solution. Now often timer jobs are not used due to the complexity and the inherent lock into the SharePoint Stack. Some developers prefer to generate console applications and use schedule tasks instead which works well, and yes indeed does remove some of the core dependency of SharePoint. For an On-Premises solution I would encourage that if the solution you need is only SharePoint and tied your single farm then a timer job is great as it benefits from core SharePoint services.
However, if you are moving to, we now have a problem where we are unable to deploy timer jobs due to them needing to be full trust solution which is not allowed. So, the question would be how do we get the same functionality in Office 365?
With Office 365 being backed by Microsoft Azure Services we have the ability to combine both services and create the same idea as a Timer Job by using Azure Web Jobs.
An Azure Web Job in its simplest form is a console application that we upload into Azure and allow it to run isolated to our tenant and cross connect to our Office 365 tenant. Azure Web Jobs are based on normal console code you would write with the exception that you need to add the client side DLL references for SharePoint Online so that you can connect to the Office 365 tenant. Within Visual Studio you are able to add the nugget package for “App for SharePoint Web Toolkit”, or whatever it is called as they rename the components. Either way the toolkit is needed for our connection. Next we need to add our Office 365 tenant details such as Tenant URL and Login details.
To start with the code, we simply need to reference “Microsoft.SharePoint.Client” so we can call into the site with code like this (sample code):
var url = https://something.sharepoint.com // Tenant URL
var account = firstname.lastname@example.org //Tenant Admin Email Address
var password = new SecureString();
password.AppendChar("Pass@word1"); // Tenant Admin Password
ClientContext context = new ClientContext(url
context.AuthenticationMode = ClientAuthenticationMode.Default;
context.Credentials = new SharePointOnlineCredentials(account, password);
Once we have the connection made we can then make it do whatever we needed to within SharePoint or any application we could code to. Once done we then compile what in reality is a console application ready to use within Azure.
Creating Azure Web Jobs is well documented and there are many different types of jobs we can use. Within the Microsoft site Azure Web Job types are listed with examples of how to create them. However, the core steps are:
- Create an On-Demand Web Job within Azure
- Provide a Name for the Job
- Specify the “How to Run” based on what you need
- Upload the file, in this case it would be an “exe” file but could be a “cmd, bat, sh, py or js” file
- Simply create the job
Once the Web Job is added you can simply run it manually, or go back and modify the job to be continuous allowing you to start and stop the process. Notice that we only have two options, if you needed to have a specific schedule then you can utilize the Azure Scheduler mechanism which allows the same process to be done but allows you to set the schedule.
Choosing specific time allows you to set the starting date, time and then the time zone.
If you choose other options within the scheduler you can then create a completely custom schedule.
Creating them this way gives you better control of when and how often the console code gets ran. Of course, because it is in Office 365 and Azure you get great logging of the process.
As you can both options are great, one for On-Premises, one for Office 365. The choice is simple for me; I am following the Microsoft pattern I would build the scheduled code as console applications making it almost cloud ready for when you move to Office 365.