Tuesday 6 September 2011

Creating a Timer job with Visual Studio 2010 for Sharepoint 2010


A timer job runs in a specific Windows service for SharePoint Server. Timer jobs also perform infrastructure tasks for the Timer service, such as clearing the timer job history and recycling the Timer service; and tasks for Web applications, such as sending e-mail alerts. A timer job contains a definition of the service to run and specifies how frequently the service is started. The SharePoint 2010 Timer service (SPTimerv4) runs timer jobs. Many features in SharePoint Server rely on timer jobs to run services according to a schedule.
After reading this nice definition coming from Microsoft we can guess what a timer jobs does. I prefer to understand a timer job with this definition:
image
What we are going to do here it is basically, expand the options of timer jobs in Sharepoint 2010, and have flexibility to work with some of our code.
As usual we will go step by step, in order to do something useful.
- Step 1Open Visual Studio 2010->New project-> Sharepoint –>2010 –> Empty Sharepoint Project. Call the project netsourcecodeTimerJob and click on OK. Now select “Deploy as farm solution” and click on Finish.
- Step 2
Rename Feature1 to netsourcecodeFeature, double click and in the title type “TimerJob Feature”, select “Site” as Scope.
image
- Step 3Right click on netsourcecodeFeature and “Add Event Receiver”. Now just copy the code below:
  private const string _netsourcecodeTimerJobNAME = "netsourcecodeTimerJob";

        public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            SPSite _sSite = properties.Feature.Parent as SPSite;

            // make sure the job isn't already registered

            foreach (SPJobDefinition _jJobDefinition in _sSite.WebApplication.JobDefinitions)
            {
                if (_jJobDefinition.Name == _netsourcecodeTimerJobNAME) _jJobDefinition.Delete();
            }

            CopyPageTimerJob _cCopyTimer = new CopyPageTimerJob(_netsourcecodeTimerJobNAME, _sSite.WebApplication);

            SPMinuteSchedule _sMinuteSchedule = new SPMinuteSchedule();

            _sMinuteSchedule.BeginSecond = 0;
            _sMinuteSchedule.EndSecond = 59;
            _sMinuteSchedule.Interval = 30;
                  
            _cCopyTimer.Schedule = _sMinuteSchedule;
            _cCopyTimer.Update();

        }

        // Uncomment the method below to handle the event raised before a feature is deactivated.

        public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
        {
            SPSite site = properties.Feature.Parent as SPSite;

            // delete the job

            foreach (SPJobDefinition _jJobDefinition in site.WebApplication.JobDefinitions)
            {

                if (_jJobDefinition.Name == _netsourcecodeTimerJobNAME)  _jJobDefinition.Delete();

            }

        }      

- Step 4The class we are going to add overwrites SPJobDefinition and the Execute() method, it only copy home.aspx pages with ticks names. Right click in your project and add a new class, call it CopyPageTimerJob.cs. Remove everything from the class and copy this code (Dont forget to set YOUR server and site collection in this line using (SPSite _site = new SPSite(@”http://xxxYOUR_SERVERxxx/sites/testsite”)) ) :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Publishing;
using Microsoft.SharePoint.Administration;

namespace netsourcecodeTimerJob
{
    class CopyPageTimerJob : Microsoft.SharePoint.Administration.SPJobDefinition
    {
         public CopyPageTimerJob(): base()
        {

        }

        public CopyPageTimerJob(string jobName, SPService service, SPServer server, SPJobLockType targetType)
            : base(jobName, service, server, targetType)
        {

        }

        public CopyPageTimerJob(string jobName, SPWebApplication webApplication)
            : base(jobName, webApplication, null, SPJobLockType.ContentDatabase)
        {

            this.Title = "Copy Page Timer Job";

        }

        public override void Execute(Guid contentDbId)
        {

            using (SPSite _site = new SPSite(@"http://xxxYOUR_SERVERxxx/sites/testsite"))
            {
                using (SPWeb _web = _site.OpenWeb())
                {
                    SPList list = _web.Lists["Site Pages"];

                    SPListItem sourceItem = null;

                    foreach (SPListItem item in list.Items)
                    {
                        if (item.Name.Equals("Home.aspx", StringComparison.OrdinalIgnoreCase))
                        {
                            sourceItem = item;
                            break;
                        }
                    }
                    string destinationUrl = _site.Url + @"/" + sourceItem.Url.Replace(sourceItem.Name, string.Empty) + DateTime.Now.Ticks.ToString()+".aspx";
                    sourceItem.CopyTo(destinationUrl);
                }
            }
         }
    }
}


- Step 5Deploy your solution, now if you go to Central Administration->Timer Jobs->Review job definitions your timer job should be there.

- Step 6
Re-start IIS (Go to Start type cmd.exe, and then type IISReset)

Note: If you get this error:Error    3    Error occurred in deployment step 'Add Solution': Failed to load receiver assembly "netsourcecodeTimerJob, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8d9872f435f80219" for feature "netsourcecodeTimerJob_netsourcecodeFeature" (ID: f59401ae-9c0a-44b3-8c84-a61e4a11291c).: System.IO.FileNotFoundException: Could not load file or assembly 'netsourcecodeTimerJob, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8d9872f435f80219' or one of its dependencies. The system cannot find the file specified.
File name: 'netsourcecodeTimerJob, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8d9872f435f80219'
   at System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
   at System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)
   at System.Reflection.Assembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)
   at System.Reflection.Assembly.Load(String assemblyString)
   at Microsoft.SharePoint.Administration.SPFeatureDefinition.get_ReceiverObject()



 



I have attached the source code in MegaUpload: Download

No comments: