Custom SPJobDefinition and “Access denied” Error

October 22 2010 34 comments

I found Stef Van Hooijdonk’s post when trying to install a custom timer job and having the “Access denied” -issue. I tried Stef’s workaround by running the powershell -script he provided and got my custom timer job to install via web scoped feature’s feature receiver.

I think there are issues to consider though. Do we want to permanently set the RemoteAdministratorAccessDenied false or do we want to run one script to set RemoteAdministratorAccessDenied false before feature activation/deactivation and after that run another script to set it back true again? Installing custom timer job evidently is an operation where Farm Admin privileges are needed and if the activator is web- or site-scoped feature, the activation dialog (the Activate/Deactivate-buttons in ManageFeatures.aspx) is available also for users with inadequate privileges. After further investigation it seems that to activate a feature from content application’s feature management UI, it is necessary to have the same application pool accounts for the content application and central admin – it seems not to be enough to be logged on to your content web app with farm admin account or with the central admin’s application pool account. The behavior is a little weird but at least when I tested different scenarios, this is how it appears to be. To have same application pool account in Central Admin and content web app, however, is not recommended.

Nevertheless, I needed a custom timer job to be installed from a web scoped feature because the timer job handles information per web. Therefore the name of the installed timer job is per web and properties to determine which web should be handled when timer job ticks are also added to the timer job’s properties.

So, I took the idea from Stef’s post and used the same idea in my feature receiver and by doing so I don’t have to run the powershell-script per environment before feature activation:

public class MyFeatureReceiver : SPFeatureReceiver
{
    private const string MyCustomTimerJobName =
        "Custom Timer Job for web: {0}";

    public override void FeatureActivated(SPFeatureReceiverProperties
        properties)
    {
        using (var web = properties.Feature.Parent as SPWeb)
        {
            if (web == null) return;

            // THE ORIGINAL VALUE OF REMOTE ADMINISTRATOR
            var remoteAdministratorAccessDenied =
                SPWebService.ContentService.
                RemoteAdministratorAccessDenied;
            try
            {

                // SET THE REMOTE ADMINISTATOR ACCESS DENIED FALSE
                SPWebService.ContentService.
                    RemoteAdministratorAccessDenied = false;
                // delete the custom timer job if it exists
                var app = web.Site.WebApplication;
                foreach (var job in
                    app.JobDefinitions.Where(job =>
                        job.Name == string.Format(MyCustomTimerJobName,
                        web.Url)))
                {
                    job.Delete();
                }
                // install the custom timer job
                var schedule = new SPMinuteSchedule
                {
                    BeginSecond = 0,
                    EndSecond = 59,
                    Interval = 5
                };
                var myTimerJob =
                    new MyTimerJob(
                        string.Format(MyCustomTimerJobName,
                        web.Url), web.Site.WebApplication,
                        null, SPJobLockType.Job)
                        { Schedule = schedule };
                // add properties to determine which site and web
                // the timer job handles
                myTimerJob.Properties.Add("site-id", web.Site.ID);
                myTimerJob.Properties.Add("web-id", web.ID);
                myTimerJob.Update();

            }
            finally
            {
                // SET THE REMOTE ADMINISTATOR ACCESS DENIED BACK WHAT
                // IT WAS
                SPWebService.ContentService.
                    RemoteAdministratorAccessDenied =
                    remoteAdministratorAccessDenied;
            }
        }
    }

    public override void FeatureDeactivating(SPFeatureReceiverProperties
        properties)
    {
        using (var web = properties.Feature.Parent as SPWeb)
        {
            if (web == null) return;

            // THE ORIGINAL VALUE OF REMOTE ADMINISTRATOR
            var remoteAdministratorAccessDenied =
                SPWebService.ContentService.
                RemoteAdministratorAccessDenied;

            try
            {
                // SET THE REMOTE ADMINISTATOR ACCESS DENIED FALSE
                SPWebService.ContentService.
                    RemoteAdministratorAccessDenied = false;
                // delete the custom timer job if it exists
                var app = web.Site.WebApplication;
                foreach (var job in
                    app.JobDefinitions.Where(job =>
                        job.Name == string.Format(MyCustomTimerJobName,
                        web.Url)))
                {
                    job.Delete();
                }
            }
            finally
            {
                // SET THE REMOTE ADMINISTATOR ACCESS DENIED BACK WHAT
                // IT WAS
                SPWebService.ContentService.
                    RemoteAdministratorAccessDenied =
                    remoteAdministratorAccessDenied;
            }
        }
    }
}

The idea is that remote administration is allowed (SPWebService.ContentService.RemoteAdministratorAccessDenied = false) for the period of time the custom timer job is either installed (activated) or deleted (deactivated) and it’s set back to what it was at the end.

Below is a custom timer job stub just to make the point complete:

public class MyTimerJob : SPJobDefinition
{
    public MyTimerJob()
    {
    }

    public MyTimerJob(string name, SPService service, SPServer server,
        SPJobLockType lockType)
        : base(name, service, server, lockType){}

    public MyTimerJob(string name, SPWebApplication webApplication,
        SPServer server, SPJobLockType lockType)
        : base(name, webApplication, server, lockType){}

    public override void Execute(Guid targetInstanceId)
    {
        if (!Properties.ContainsKey("site-id") ||
            !Properties.ContainsKey("web-id"))
            return;

        var siteId = (Guid)Properties["site-id"];
        var webId = (Guid)Properties["web-id"];

        using (var site = new SPSite(siteId))
        {
            using (var web = site.OpenWeb(webId))
            {
                // do your deeds
            }
        }
    }
}

I made my feature hidden only to be activated via scripting to be sure no one would try to activate the feature from my content web application’s UI.

The sample about creating custom timer jobs in msdn (also linked in Stef’s post) article installs the custom timer job via WebApplication-scoped feature. I think timer jobs are only meant to be installed in Central Admin’s context but then how could you fluently develop timer jobs that handle something in your content applications if you can’t install timer jobs per site or web.

The workaround is however something I would’t have wanted to find out, nor use, so use it with your own risk.

Popularity: 4% [?]

34 comments to “Custom SPJobDefinition and “Access denied” Error”

  1. Danny says:

    Hello,

    This line:

    SPWebService.ContentService.RemoteAdministratorAccessDenied = false;

    Also gives a access denied in my installation of SP2010.

    Am I forgetting something

  2. Juha Pitkänen says:

    Activate your feature with PowerShell or stsadm:

    Enable-SPFeature
    or
    stsadm -activatefeature

    as an administrator.

  3. Danny says:

    I am logged in in my site as a domain administrator. Is this not enough to run from site collection feature screen? Or is this just not possible?

  4. Juha Pitkänen says:

    See the second chapter of this post “…After further investigation it seems that to activate a feature from content application’s feature management UI, it is necessary to have the same application pool accounts for the content application and central admin – it seems not to be enough to be logged on to your content web app with farm admin account or with the central admin’s application pool account…”.

    And the chapter after the second code clip: “I made my feature hidden only to be activated via scripting to be sure no one would try to activate the feature from my content web application’s UI.”.

    The post was only to get rid of setting RemoteAdministratorAccessDenied to false with powershell script before activating the feature that installs the timer job. The activation of the feature, unfortunately, has to be done with “Enable-SPFeature” or “stsadm -activatefeature”.

  5. Danny says:

    Will try. But all my sites and central admin all run under same app_pool account.This should not be a problem. Will get back to you

  6. Juha Pitkänen says:

    If you have the same app pool accounts for both your content web app and CA, you can log on to your content web app with the app pool account or use SPSecurity.RunWithElevatedPrivileges in your FeatureActivated and FeatureDeactivating. I just tested both scenarios and there is no problem activating/deactivating the feature from the button in your content web app’s feature management.

  7. Je trouve que votre blog est très bien fait, encore un post très intéressant. Continuez-le.

  8. Juha Pitkänen says:

    Danke schon ;)

  9. Andy Burns says:

    Yeah, the problem you’ve found here is that in Least Privileges configured farms the content app pool account doesn’t have any access to SharePoint’s Config database. Even if you RunWithElevatedPrivileges in your content web app you’ll only be running as the content app pool, and you won’t be able to access the config database.

    Sadly, that’s exactly what you need to be able to do to create a new timer job.

    The central admin app pool, however, must have access to the config database to work at all! Thus, code run within this app pool will create the timer job nicely.

    Options are:
    A) Make this happen from within Central Admin. I have seen a solution that created a “master” timer job which would check various web applications – and create “slave” Timer Jobs for those web applications if required. All the feature in the content app pool would do was flag that it wanted a timer job created for it.

    B) Grant access writes to the config db to your content app pool account.

  10. Juha Pitkänen says:

    Than you Andy for clarifying this out for us!

    Just out of curiosity, do you have an explanation to not being able to activate the feature from content app’s UI, when logged on to the content app with central admin’s app pool account? That to me was strange.

  11. “Danke schon”

  12. SaM says:

    HI
    I am having an issue with custom timer job webpart.
    I have two different Sharepoint 2010 envirionment with the service account as farm administrator with write privilage to the configuration database.The problem is if I have a custom timer job created with feature which works perfectly on both of the envirionment.But When I created a webpart to display the status of the timer job,and run and schedule the timer job.The webpart work perfectly in one envirionment but display the status but it doesnot run or could schedule job in other envirionment.I was suggested that I should enable remotedesktopadministor in the box which cannot run the timer job when in webpart.But its no help So could you please let me know if there is some other services I need to start before I set remoteAdministratorAccessDenied. I was trying to read more on the new Feature remoteAdministratorAccessDenied.Can somebody point me out how it works.
    Thanks
    Sam

  13. Allen Eick says:

    Heya i am for the primary time here. I came across this board and I in finding It really helpful & it helped me out much. I am hoping to give one thing again and help others like you aided me.

  14. sympa mais ce soir” il faut “a venir mon site registre des creations

  15. Thanks for sharing such a fastidious thought, post is nice, thats why i have read it fully

  16. minority a says:

    My brother suggested I might like this web site. He
    was totally right. This post truly made my day.
    You can not imagine simply how much time I had spent for this info!
    Thanks!

  17. Instead, opt for fewer pieces that are truly unique and have
    a presence of their own. Paint your walls a different color to give the room a whole new look.
    It is going to be a setting the tone for any huge component of one’s d.

    Feel free to surf to my blog: ideas for coffee table decor

  18. I am genuinely delighted to read this web site posts which
    consists of lots of useful information, thanks for
    providing these statistics.

  19. I blog quite often and I genuinely appreciate your information. The article has truly peaked my interest.

    I’m going to book mark your blog and keep checking for new information about once a week.
    I opted in for your RSS feed as well.

  20. Touche. Solid arguments. Keep up the great work.

    Check out my website … barmatch.com/node/1289718

  21. It’s actually a great and useful piece of information. I am
    glad that you just shared this helpful information with us.
    Please keep us up to date like this. Thank you for sharing.

  22. Viagra says:

    to capitalize on the American demand for affordable prescriptions.
    Raynaud’s disorder is known as a therapy tolerant condition. If you are not sexually
    aroused, cheap generic Kamagra is not going to give you an erection.

  23. Howdy! I know this is somewhat off topic but I was wondering which blog platform are you using for this website?
    I’m getting tired of WordPress because I’ve had issues with hackers
    and I’m looking at alternatives for another platform.
    I would be awesome if you could point me in the direction of a
    good platform.

    Here is my weblog: high protein foods for muscle building

  24. Good day very nice site!! Guy .. Excellent .. Wonderful ..
    I’ll bookmark your blog and take the feeds also? I am
    satisfied to seek out a lot of helpful information right here in the put up,
    we’d like develop extra techniques in this regard, thanks for sharing.

    . . . . .

  25. The younger and more inexperienced the driver iis under age,it will cost before you go
    for search abc insurance policies online.

  26. Thanks to my father who shared with me on the topic of
    this web site, this weblog is genuinely remarkable.

  27. Annette says:

    I’m not sure why but this weblog is loading extremely slow for me.
    Is anyone else having this issue or is it a problem on my end?
    I’ll check back later and see if the problem still exists.

  28. Ԝay cool! Some extremely valid points! I apρreciate you writing this post and the rest of the website is extremelƴ
    ɡooԀ.

  29. A fascinating discussion is definitely worth comment.
    I believe that you ought to publish more about this subject, it
    may not be a taboo matter but usually people don’t discuss these
    topics. To the next! All the best!!

  30. Great article tnx for sharing that!!!
    check this domain http://blah-blah.com

  31. source says:

    The Nux Downloader for Black – Berry lets you specify via a URL,
    what files to download, but only direct download links will work.
    Mosaic Creator allows you to create a large regular mosaic patterned images from
    many small cells. If I could sum it up in one sentence, I would say that you can
    use L2TP VPN for Android, and Open – VPN for Windows and not
    go wrong.

  32. Writing articles is necessary for any enterprise or individual
    trying to get exposure from prospects on the web. It is important to hire a reliable and trustworthy
    company that can submit the articles to various article submission websites.
    So if you are thinking for making use of directory submission service or manual directory submission then one of the best options is
    to try and contact an experienced team online.

  33. Other devices connected to thhe network will also be scanned, provided that they support the SNMP protocol.

    If you really want to leverage the electrical power of on-lineworld wide
    web builder then utilizing a template is a starting up
    position need to be considered your best choice.
    More specifically, it is a program that can help you lose 25 lbs in 25 days while still giving you the freedom to
    indulge in whatever diet you crave every fifth day.

  34. Hello Dear, are you actually visiting this website regularly, if so afterward you will without doubt take
    good experience.

Leave a Reply