By Arjun Chakraborty
SharePoint is an amazing medium for information management because of the variety of custom services that are supported. It is famous for its web services and workflows, but custom code can also be used in timer services and event handlers. Unfortunately, since these features are not utilized very frequently, documentation for them can be difficult to find.
Today, I’d like to talk about quickly deploying a timer service into SharePoint. Timer services, as their name implies, are useful for performing programmatic tasks at regular, periodical intervals. For example, suppose at the end of each week, you would like to migrate the contents of a single Library into other categorical libraries based on the content’s metadata. This would be a perfect opportunity to develop a timer service and impress your boss/client/friends.
Timer services run in the farm level, so they are a little trickier to activate than workflows or event handlers. To deploy and activate a timer service, you should use Visual Studio 2k8 and WSPBuilder. WSPBuilder is a free product which will immensely facilitate your SharePoint programming endeavors. You can download it from here. Also note that installing WSPBuilder onto Visual Studios 2k8 will require you to have SP1 for Visual Studios 2k8 already installed on your machine. While we will use the WSPBuilder to create a solution for SharePoint, we will be using stsadm to deploy and activate the solution to SharePoint.
Creating the Project:
Hopefully you have installed WSPBuilder by now. Afterwards, run Visual Studio 2k8 and go down to the WSPBuilder category and select the WSPBuilder Project with Workflow template. Obviously, we will not actually utilize a workflow, but the option is still there in case you choose to engineer a creative timer service/workflow hybrid of some kind.
Figure 1: Select WSPBuilder Project with Workflow.
Initially, there isn’t much in this solution:
Figure 2: In the beginning, there are no classes in this project.
First, Right click on Example_Timer_Service (or whatever your project is called). Then, go to properties and make sure the Target Framework is set to .NET Framework 3.5.
Figure 3: Make sure the Target Framework is set to 3.5.
Save the properties window, and then again, right click on Example_Timer_Service. Go down to Add, and then click on New Item… .
The Add New Item dialogue box should appear. On the left, select WSPBuilder (again), and select the Feature with Receiver template:
Figure 4: Add a Feature with Receiver.
Set the name, click Add, and then afterwards, make sure the scope is Site in the new dialogue box. The scope, title and description can be easily changed, and I’ll show you how later. We are using this template because it comes with the feature elements built for us.
One last step is needed before you can code your merry way to your brilliant timer job. Right click on the project (Example_Timer_Service or whatever), click on Add, and then Class… . Name the class to whatever you want, and then click on Add.
Figure 5: Add a new class, which will hold the code that gets executed when the timer service triggers.
Hurray, you are now ready to code the timer service! Your Solution Explorer should look like this now:
Figure 6: After you have all the files you need, your solution explorer should look like this.
There are three files here that you should keep in mind:
Feature.xml will allow you to chance the scope, name and description for this SharePoint feature. It also holds the feature ID (a guid) which will come in handy later. Example_Timer_Service_Feature.cs holds the code which will add or remove the timer service feature to and from SharePoint. Lastly, Example_Timer_Service_Code.cs will hold the code that actually gets executed when the timer service reaches a certain moment (or set of moments) in time.
Coding the “Example_Timer_Service_Feature.cs”:
Before I continue, I would like to point out that most of the Example_Timer_Service_Feature.cs code I present here were already written in Andrew Connell’s famous article on creating timer jobs. The article can be found here. I’m not one to reinvent the wheel, so I’ll simply present his code (or I guess my adaptation of his code). The intention of this article is not to recreate the code but to streamline the deployment of the timer service.
Open up Example_Timer_Service_Feature.cs. Inside, you will find four methods.
· FeatureInstalled is unnecessary, so simply remove the exception throwing line of code.
· FeatureUninstalling is unnecessary, so simply remove the exception throwing line of code.
· FeatureDeactivating is important. As the name implies, this method is used to remove the timer service when the feature is deactivated. My code looks something like this:
Obviously, this is strikingly similar to Andrew Connell’s code. Note, TASK_LOGGER_JOB_NAME is a class level constant string. Right now I have it equal to “Example Timer Service Name”.
· FeatureActivated is also important, as it creates the timer service when the feature is activated. My code looks something like this:
Notice the Example_Timer_Service_Code object created in the middle of the code. That is the timer service itself.
Furthermore, notice the SPSchedule.FromString("every 5 minutes"); . The string can be rewritten to be whatever time interval or specific time of day (or week, or month) that you want. To get a better feel for this string’s format, take a look here.
Congratulations! At this point, you no longer have to think about Example_Timer_Service_Feature.cs. Instead, you now have to think about…
Coding the “Example_Timer_Service_Feature.cs”:
This class will be pretty simple. It needs to inherit from SPJobDefinition, and contains 4 methods: 3 constructors and 1 void method. The entire class should look like this:
class Example_Timer_Service_Code : SPJobDefinition
public Example_Timer_Service_Code(string jobName, SPService service, SPServer server, SPJobLockType targetType)
: base(jobName, service, server, targetType)
public Example_Timer_Service_Code(string jobName, SPWebApplication webApplication)
: base(jobName, webApplication, null, SPJobLockType.ContentDatabase)
this.Title = "Example Timer Service Title";
public override void Execute(Guid contentDbId)
// get a reference to the current site collection's content database
SPWebApplication webApplication = this.Parent as SPWebApplication;
SPContentDatabase contentDb = webApplication.ContentDatabases[contentDbId];
string relativeSiteUrl = "/";
using (SPSite site = contentDb.Sites[relativeSiteUrl])
using (SPWeb web = site.OpenWeb())
//do stuff here.
A few things to Note:
· The three constructors must look exactly like they do right now.
· The Execute method is what occurs when the timer service becomes triggered. This is to say, when the conditions of the previously mentioned SPSchedule are met, the Execute method will be … executed.
· Within the Execute method, you will find the relativeSiteUrl string variable. Keep in mind that the Url you are feeding into the SPWeb will need to be a relative url. That is to say, if the url for your site is http://machine:1337/sites/asdf/default.aspx, then relativeSiteUrl should equal “/sites/asdf/”.
· In the third constructor (the one we actually use), you will find this.Title. This is the title used in the Timer Job Definition page in Central Admin. You can use this to see if the timer service has actually been activated.
· The part where I commented out “do stuff here” is where you can put your document migrating/library deleting code (or whatever else you wish to do).
Deploying the Solution:
Finally, after you have coded in the timer service, it is time to deploy it to SharePoint and activate it. WSPBuilder will go 80% of the way there, and then it’s all up to you. First, right click on Example_Timer_Service (project name) in the solution Explorer. Click on Build. If you hit any compile errors, fix and repeat. Then, right click on the project and go to the WSPBuilder menu:
Figure 7: The WSPBuilder menu, which you will be using a lot.
Click on Build WSP. Wait till the Output box tells you it is done:
Figure 8: The Output box after the project is compressed into a WSP file.
Then, go back to the WSPBuilder menu and click on Deploy. Again, wait till the output box tells you that the process is complete.
Figure 9: The Output box after the project, as a WSP file, is deployed into SharePoint.
Great! Now, the feature should be on SharePoint. If it failed to deploy, here is what you do:
1. Right click on the project, and click on Open Folder in Windows Explorer.
2. Open command prompt and change directory to the project folder that you just opened.
3. Use the stsadm command:
stsadm -o addsolution -filename Example_Timer_Service.asp
Now, the last step is to actually activate the timer service feature. The timer service is a site collection feature, so, using a web browser, go to the site collection and then to site settings. In there, click on site collection features. You should see the feature, with the name and description found in the feature.xml mentioned before.
Figure 10: The timer service feature, found in the site collection features page.
Now if you can click on Activate and it works, then hurray, your work is finished! More likely than not, you will get the following ambiguous message:
Figure 11:If you get this error, you need to use stsadm to activate the timer service.
This is because the site collection application account does not have the privileges necessary to create the timer job on the farm level.
No big deal; we’ll just use stsadm. Use the following stsadm command:
Stsadm -o activatefeature -id %ID% -url %URL%
· %ID% is the feature ID, which can be found in the top of the feature.xml mentioned before.
· %URL% is the url for the site collection, such as http://machine:1337/
Refresh the site collection features page, and the feature should now be activated. Hurray!
1. If you want to modify the timer service after it has already been activated, you have to deactivate it first. Deactivating it uses the same stsadm command as above, except its deactivatefeature instead of activatefeature.
2. One nifty way to debug a timer service is to create a custom list called “Timer Service Log”. Whenever you want feedback from the Execute method, simply add a SPListItem to this custom list, and then change its Title to whatever message you want to feed back to yourself.
---By: Arjun Chakraborty