Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.
I’ve been working on a sample app for SharePoint 2010 that demonstrates the Sync Framework, Custom Service Applications and a Custom Timer.
There’s a few good articles on MSDN and elsewhere that document the process of creating a custom timer job pretty well. This hasn’t changed much in 2010 – if at all – from what I can see. However, the samples don’t show you how to create a Service/Server level job definition, so here’s my small addendum to show how to do this.
Creating a Service Job
When you construct a new job definition – custom or otherwise – there are two constructors you use:
protected SPJobDefinition(string name, SPWebApplication webApplication, SPServer server, SPJobLockType lockType); protected SPJobDefinition(string name, SPService service, SPServer server, SPJobLockType lockType);
protected SPJobDefinition(string name, SPWebApplication webApplication, SPServer server, SPJobLockType lockType);
protected SPJobDefinition(string name, SPService service, SPServer server, SPJobLockType lockType);
You can override the constructors in your custom job. For a service timer you should use the 2nd constructor. In this case, the lockType can only be Job or None.
Persisted Configuration
If you take a look at the definition of SPJobDefinition you will notice that it inherits SPPersistedObject. The MSDN sample talks about creating a separate persisted object for the job configuration data. This is not necessary. Instead, you can add your [Persisted] public fields directly to your custom job definition.
Errors
When you run a timer job that is created for a service, the service must be running – yes, strangely :) If it’s not the job will fail silently and you have to look in the logs to see the error. There doesn’t seem to be any way to catch this exception.
Weirdness
I managed to waste about 3 hours trying to track down why timer execution of my service method was failing when calling it directly would work. There is no special logic in the timer. The bug I was seeing was something that I had fixed previously so I was baffled why it was failing for the timer and not for my web page.
Overnight, and after a few IISResets, redeployments and reboots, it came right and now works correctly. I also made sure the GAC was cleared out between deployments. It seems to me like there was an old version of the service application dll that the timer was using and the rest of the site wasn’t. I cant prove this but that’s certainly how it appeared.
Debugging
As Andrew Connell points out in his articles, you need to fire an Assert() to get the debugger to stop in the job Execute() method.
#if DEBUG System.Diagnostics.Trace.Assert(false);#endif
Attaching to OWTIMER.exe is not enough. However, for me, this Assert does not popup a message – you need to attached to OWTIMER first. This maybe a SP or VS 2010 thing.
Enjoy :)