Problem in creating Timer Job
Asked Answered
V

3

6

I have created a site collection inside a web application with user A as a site collection adminstrator. I have added a link in site feature page. On click of that link I am trying to create a timer job.Below is the code executed on click of the link

//Allow unsafe updates.
 SPContext.Current.Web.AllowUnsafeUpdates = true;

//Get current web application.
SPWebApplication webApp = SPContext.Current.Site.WebApplication;

// Create new job.
ArchiveJob automaticArchiveJob = new ArchiveJob(scheduleDetails.scheduleName, webApp);

SPHourlySchedule hourlySchedule = new SPHourlySchedule();
hourlySchedule.BeginMinute = 0;
hourlySchedule.EndMinute = 1;
automaticArchiveJob.Schedule = hourlySchedule;

//Finally update archival job.
automaticArchiveJob.Update();

Now when I logged in with user A and click on that link on 'site settings' page, I get an security exception with message "Access Denied" at line automaticArchiveJob.Update(). But if I logged in with administrator user (I am also logged in to the machine using this user) and click on the link it successfully creates the job. Also I made user A member of WSS_ADMIN_WPG group but still getting the same problem. Is there any thing else that I need to do to resolve the problem.

Vaduz answered 24/6, 2009 at 5:50 Comment(0)
I
23

The "Access Denied" is expected behavior given what you're attempting to do. Allow me to explain.

When a timer job instance is created, it is persisted to the farm configuration database. Accessing this database for write purposes is a privileged operation; as a rule of thumb, only the farm service account (that is, the account under which OWSTIMER.EXE executes) or accounts that explicitly have the rights required to carry out such an operation on the config database (typically administrators) will succeed.

By default, attempting to instantiate a timer job from within the site collection context is going to fail. Attempting the operation in an elevated privilege block (via SPSecurity.RunWithElevatedPrivileges) is only going to result in the web application's application pool account context being used instead of the current user context; this only succeeds if the app pool account has rights to write to the farm configuration database. If this happens, it's typically because (a) the farm service account is being used in roles that it shouldn't be in (to run content web apps, for example), or (b) extra permissions have been granted to the application pool account. Both cases represent a deviation from a best-practices operating model.

Timer job instances are typically created at Feature activation time in Features scoped at either the Farm or WebApplication level. Why? Because those Features are normally activated by administrators from either the command line (assuming the admin also has rights in the farm config database) or from within Central Administration (where activation occurs through the farm service account -- guaranteed to have rights to the config database). When the Feature is activated and the SPFeatureReceiver's FeatureActivated method is called, it is safe (from a security perspective) to setup the timer job.

Solving your particular problem properly will involve turning the problem on its head a bit. Instead of trying to instantiate the timer job from within the site collection on demand, I'd recommend setting up the equivalent of a "sweep" timer job at the time your Feature is activated. Admittedly, this takes more planning and effort than what you're trying to do, but your current path is only going to work if security is somehow adjusted -- and that's not recommended.

When I was putting together my BLOB cache farm flush Feature (http://blobcachefarmflush.codeplex.com), I had to do much the same thing myself. You can see the specifics of how I worked through timer job creation in the FeatureReceiver class (BlobCacheFarmFlushSweepJobFeatureReceiver). The rest of the code and associated documentation may also help with some of the other challenges that come up.

Feel free to use what you find in any way; that's why it's there!

I hope that helps. If there are follow-up questions, fire away and I'll answer as best as I can :-)

Idocrase answered 24/6, 2009 at 13:53 Comment(4)
Hey Sean Thanx for your reply.....I found it very useful. I will certainly ask queries if i will have....Thanx againVaduz
How to configure and run this job then?Winser
What are you specifically asking, Evgeny? There are plenty of samples on the Internet that discus how to create a timer job, configure it, and run it - including my BLOB cache farm flush Feature (mentioned above). The point I was trying to make with response was this: timer job creation will not work from code running at the site collection level unless the farm is misconfigured.Idocrase
Several years later and this post is still a good resource. Explained perfectly!Icarian
S
0

Try to override the SPPersistedObject.HasAdditionalUpdateAccess() method and return true.

protected override bool HasAdditionalUpdateAccess() { return true; }

Shyamal answered 25/1, 2016 at 5:18 Comment(0)
V
-3

I have used RunWithElevatedPrivileges

SPSecurity.RunWithElevatedPrivileges(delegate() { });

It works for me.....Does anybody have another solution? If so please let me know.

Vaduz answered 24/6, 2009 at 6:49 Comment(1)
Anoop, see the explanation from Sean above why you should never (be able to) use the method you describe here. Sean has done a great job in explaining this clearly.Absenteeism

© 2022 - 2024 — McMap. All rights reserved.