0

I have created a custom timerjob in visual studio. I have deployed this timerjob on my sharepoint 2010 portal. It is scheduled every night at 02:00 a clock. When I start this timerjob manual from central admin I follow it with the "timer job status" page in central admin. I refresh the page till the progress is 100 %. After this I see that the timer job is started again.

What can I do to fix this? Is this normal?

I have activated this feature on 2 webapplications.

This is the code of my feature even receiver:

public override void FeatureActivated(SPFeatureReceiverProperties properties)
    {

    base.FeatureActivated(properties);

        var webApplication = properties.Feature.Parent as SPWebApplication;
        if (webApplication == null)
        {
            throw new ArgumentNullException("WebApplication");
        }

        DeleteJob(webApplication.JobDefinitions);

        var jobDefinition = new ProcessADProfileFieldsCustomJobDefinition(webApplication)
        {
            Schedule = new SPDailySchedule
            {
                BeginHour = 2, 
                BeginMinute = 0,
                BeginSecond = 0,
                EndHour = 2, 
                EndMinute = 0,
                EndSecond = 0
            }
        };

        jobDefinition.Update();
    }

This is the execute method:

public class ProcessADProfileFieldsCustomJobDefinition : SPJobDefinition
{
    /// <summary>
    ///   The Internal Name of the Job Definition.
    /// </summary>
    public const string JobName = "ProccessADProfileFieldsCustomJob";

    /// <summary>
    ///   The Feature ID of the Profile Translation Lists Template Feature.
    /// </summary>
    public static readonly Guid ProfileTranslationListsDefinitionFeatureId = new Guid("51500552-fea0-4004-a640-ca5c4e8e23c0");

    /// <summary>
    /// </summary>
    public ProcessADProfileFieldsCustomJobDefinition()
    {
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="ProcessADProfileFieldsJobDefinition"/> class and provides parameters for specifying key objects.
    /// </summary>
    /// <param name="webApplication">
    /// Specifies an <see cref="SPWebApplication"/> object instance.
    /// </param>
    public ProcessADProfileFieldsCustomJobDefinition(SPWebApplication webApplication)
        : base(JobName, webApplication, null, SPJobLockType.Job)
    {
    }

    /// <summary>
    ///   Gets a localized description of the job definition.
    /// </summary>
    public override string Description
    {
        get
        {
            return "The Profile import job to set AD field to SharePoint Profiles.";
        }
    }

    /// <summary>
    ///   Gets the localized name of the job definition.
    /// </summary>
    public override string DisplayName
    {
        get
        {
            return "Process AD ProfileFields Custom Job";
        }
    }


    /// <summary>
    /// </summary>
    /// <param name="targetInstanceId">
    /// </param>
    [SharePointPermission(SecurityAction.LinkDemand, ObjectModel = true)]
    [PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
    public override void Execute(Guid targetInstanceId)
    {
        try
        {
            var webApplication = this.Parent as SPWebApplication;
            if (webApplication == null)
            {
                return;
            }

            foreach (var site in webApplication.Sites.ToList())
            {
                try
                {
                    if (site.Features[ProfileTranslationListsDefinitionFeatureId] != null)
                    {
                        this.ProcessProfiles(site);
                    }
                }
                finally
                {
                    if (site != null)
                    {
                        site.Dispose();
                    }
                }
            }
        }
        catch (Exception ex)
        {
            DiagnosticsService.LogError(ex, "Exception in AD profile fields job.", 0, DiagnosticsCategory.Jobs);
            throw;
        }
    }

There is also this method:

private void ProcessProfiles(SPSite site)
        {
            var profileManager = new UserProfileManager(SPServiceContext.GetContext(site));

            var taxonomySession = new TaxonomySession(site);

            var count = profileManager.Count;
            long counter = 0;



            this.UpdateProgress(0);

            foreach (UserProfile profile in profileManager)
            {
                if (profile != null)
                {
                    UpdateProfile(taxonomySession, profile, site);
                }

                counter++;

                // update progress
                var percentage = (counter / (float)count) * 100;
                this.UpdateProgress(Convert.ToInt32(percentage));
            }

            this.UpdateProgress(100);
        }
0

Since you are running this on multiple web applications change the SPJobLockTime in your definition to None. You don't want it to lock the Job from running if you are running it in multiple places. This may be the culprit as you are preventing the multiple instances from running.

  • for your information. I have a farm with 2 front end, 2 app, 2 content servers. Do I still need to set it on None? – Ola Nov 13 '13 at 17:14
  • Yes. You don't need to lock the job. – John Chapman Nov 13 '13 at 17:56
  • I have added a new piece of code which is running in my timer job. Is this maybe also the problem? – Ola Nov 13 '13 at 18:45
  • I have changed it from SPJobLockTime to None. But this didnt fix my problem. The only differance is that I see now foreach farm server an instance of this timer job. But they are still starting again after they are finishing. See the last method. I see some dynamics progress. Is this code OK? – Ola Nov 13 '13 at 21:41
0

The timer is working twice because it is associated with 2 content database. Every Site Collection (SPSite) has a property that gives you the Content Database, and every time a Timer Job is called (targeting a Content Database) the Content Database GUID for which it is running is passed in , use the same for validation. Also you should use SPJobLockType.Job instead of SPJobLockType.ContentDatabaseJob in the Jobs constructor.

SPJobLockType.ContentDatabaseJob executes for every DB, the other only once per machine

0

I have found the problem. The timer job was not looping. This code was the problem:

foreach (var site in webApplication.Sites.ToList())
            {
                try
                {
                    if (site.Features[ProfileTranslationListsDefinitionFeatureId] != null)
                    {

I was thinking this site collection feature was only activated on the top level site collection. But after doing some investigation I found several sub site collection where this feature was activated. I have deactivate this feature on all sub site collections.

  • Once again, there is no such thing as a sub site collection :) – Robert Lindgren Nov 14 '13 at 18:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.