1
votes

I have created a timer job with following code:

namespace EmployeeDemo
{
    class DeleteEmployees : SPJobDefinition
    {
        public DeleteEmployees() : base() { }

        public DeleteEmployees(string jobName, SPWebApplication webapp)
            : base(jobName, webapp, null, SPJobLockType.ContentDatabase)
        {
            this.Title = "Delete Employees Timer Job";
        }

        public override void Execute(Guid targetInstanceId)
        {
            // Code
        }
    }
}

I then created a Site scoped feature. In its event receiver, on deactivation, I have the following code:

const string timerJobName = "Delete Employees Timer Job";
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
    DeleteJob(properties.Feature.Parent as SPSite);
}
private void DeleteJob(SPSite site)
{
    foreach (SPJobDefinition job in site.WebApplication.JobDefinitions)
    {
        if (job.Name == timerJobName)
        {
            job.Delete();
        }
    }
}

But it throws me error. From debugging I understand that the error is thrown on the line job.Delete();. The error is:

Object reference not set to an instance of an object.

This is kind of confusing to me as the statement job.Name executes flawlessly and even gets me the right timer job object. But while trying to delete the job it throws me error.

I found this question with similar problem as mine but the suggestions didn't not work for me. From this discussion I tried by writing deletion code in SPSecurity.RunWithElevatedPrivileges but it still didn't work for me.

Anyone knows why this happens and how to resolve this?

Update 1

A little more details.

NullReferenceException was unhandled by user code

Object reference not set to an instance of an object.

Here's the stack trace

   at Microsoft.SharePoint.Administration.SPConfigurationDatabase.DeleteObject(Guid id)
   at Microsoft.SharePoint.Administration.SPConfigurationDatabase.Microsoft.SharePoint.Administration.ISPPersistedStoreProvider.DeleteObject(SPPersistedObject persistedObject)
   at Microsoft.SharePoint.Administration.SPPersistedObject.Delete()
   at Microsoft.SharePoint.Administration.SPJobDefinition.Delete()
   at EmployeeDemo.Features.DeleteEmpFeature.DeleteEmpFeatureEventReceiver.DeleteJob(SPSite site)
   at EmployeeDemo.Features.DeleteEmpFeature.DeleteEmpFeatureEventReceiver.FeatureDeactivating(SPFeatureReceiverProperties properties)
   at Microsoft.SharePoint.SPFeature.DoActivationCallout(Boolean fActivate, Boolean fForce)
1
If exception is really throwed by job.Delete() then it should be thrown somewhere inside Delete method. Just because if job is null - exception will be thrown one line before, at job.Name. So you have to look into Delete method which you haven't shown to us. - Andy Korneyev
@AndyKorneyev: The Delete() method is of the SPJobDefinition class. It is from SharePoint API so I suppose I cannot see the source code for it, or can I? - Naveen
Well, actually you can. For example, by using .NET Reflector or other similar tool. But before exploring that source - make sure it is exactly job.Delete throws exception, not some line before (maybe some part of site.WebApplication.JobDefinitions?). For me it is very unlikely that some Microsoft API method will throw NullReferenceException without any observable reason. - Andy Korneyev
To expand on Andy's comments: your question, if you believe it is not simply a dupe of the canonical NullReferenceException question, needs to include more details. At a minimum, you need to provide complete details about the exception itself: name of the exception, and complete stack trace, in addition to the message (which you've already provided and from which we can infer the actual exception, but you should provide that anyway). - Peter Duniho
@PeterDuniho: I have added the error details as you had asked. - Naveen

1 Answers

0
votes

To delete the job use powershell:

$jobToDelete = Get-SPTimerJob -WebApplication "http://intranet" -Identity "YourJobName"
$jobToDelete.Delete()

then run:

iisreset /noforce

In the configuration database you need to grant those permission to let deletion work:

use [Sharepoint_Config]
GO
GRANT EXECUTE ON [dbo].[proc_putObjectTVP] TO [WSS_Content_Application_Pools]
GRANT EXECUTE ON [dbo].[proc_putObject] TO [WSS_Content_Application_Pools]
GRANT EXECUTE ON [dbo].[proc_putDependency] TO [WSS_Content_Application_Pools]
GRANT EXECUTE ON [dbo].[proc_putClass] TO [WSS_Content_Application_Pools]
GRANT EXECUTE ON [dbo].[proc_getNewObjects] TO [WSS_Content_Application_Pools]
GRANT EXECUTE ON [dbo].[proc_dropObject] TO [WSS_Content_Application_Pools]
GO