آی تی نرد

اشتراک اطلاعات و تجربیات در زمینه ی توسعه ی دات نت و البته شیرپوینت

نکات برنامه نویسی Timer Job ها در شیرپوینت

در شیرپوینت برخی از کارهای اساسی و سنگین که نیاز به اجرا شدن دوره ای و یا به دلیل طولانی بودن فرایند و پردازش می بایست باعث متوقف شدن محیط اصلی شیرپوینت نشوند از طریق سرویس ویندوزی به نام SharePoint Timer به صورت زمانبندی شده اجرا و پردازش می شوند.

شیرپوینت با فراهم کردن آبجکت مدلی شرایط ایجاد و کار با این سرویس را مهیا نموده است. به این صورت که میتوان از طریق این آبجکت مدل نمونه های جدید زمانبندی شده ای از این سرویس را ایجاد کرد که به اصطلاح فنی به ان Job گفته میشود.

جاب ها در سطح Web Application تعریف و ایجاد میشوند و مدیریت آنها تنها از طریق سنترال ادمین و با دسترسی مدیر فارم امکان پذیر می باشد. برای ایجاد و مدیریت نمونه ی جدید جاب از طریق آبجکت مدل مهیا شده می بایست شرایط زیر حتما فراهم شده باشد:

  • اجرای این کدها در سروری که شیرپوینت در ان نصب می باشد.
  • کدها یا آبجکت مدل مورد نظر می بایست ابتدا حتما در GAC قرار داشته باشند.
  • ایجاد نمونه ی جدید جاب با دسترسی کاربر مدیر فارمی که بتواند در حالت نرمال و از طریق سنترال ادمین جاب ها را مدیریت کند.
  • یکی بودن Application Pool محیطی که در ان قرار هست جاب اجرا یا ایجاد شود با سنترال ادمین. برای مثال App Pool سایت کالکشن ایکس با سنترال ادمین یکی باشد.(که البته این کار از نظر توپولوژی و استاندارد های شیرپوینت مشکل دارد.)

البته باید اعتراف کرد که فراهم کردن این شرایط مقداری مشکل و باعث کاهش میزان استفاده از این جاب ها می شود.

معمولا در راهکارهایی که در سطح فارم نوشته میشوند و برای رفع نیاز اجرای دوره ای فرایندی که می بایست در پیش زمینه ی شیرپوینت اچرا شود استفاده میشود.

تمام این راهکارها که می بایست از طریق مدیر فارم نصب و دیپلوی بشند می بایست Feature یا ویژگی انها نیز در سطوح مختلف سایت و یا مجموعه سایت فعال یا غیر فعال شوند که در این حالت در صورتی که از این جاب ها استفاده شده باشد به احتمال قریب به یقین با توجه به شرایطی که قبلا گفته شد با مشکل دسترسی مواجه خواهد شد.

اما شاید بپرسید پس با وجود این شرایط سخت و پیچیده پس چرا باید از این جاب ها استفاده کرد. ابتدا اجازه بدید بگم چرا این شرایط برای استفاده از این موارد به وجود امده است.

ابتدا از خود سرویس شروع کنیم این سرویس که مسئول اجرا و مدیریت شروع و اغاز این جابها می باشد در سرور شیرپوینت قرار دارد و کاربری که این سرویس با ان شروع میشود به دیتابیس تنظیمات شیرپوینت دسترسی ویرایش دارد بنابراین میتواند اطلاعات جاب ها را از انجا بخواند و یا تغییر دهد.

در نتیجه این موضوع باعث می شود که کدهایی که در این محیط اجرا میشوند هم می بایست دسترسی مورد نیاز را به این دیتابیس داشته باشند تا این سرویس بتواند این کدها را اجرا کند. خب خود این کدها با استفاده از حافظه ی مربوط به محیطشان که برای مثال همان Application Pool یک مجموعه سایت می باشد شناسایی و Authorize خواهند شد. بنابراین کاربری که این Application Pool را اجرا میکند نیز می بایست دسترسی لازمه را برای ویرایش این دیتابیس داشته باشد.

حالا شاید بپرسید پس چرا می بایست Application Pool ها یکی باشند خب این به این دلیل است که شیرپوینت تنظیمی دارد که این مورد را شناسایی میکند و مانع ان میشود که البته همونطور که گفتم این یک تنظیم می باشد و میتوان ان را با استفاده از پاورشل شیرپوینت تغییر داد.

خب در نهایت برای مهیا سازی این شرایط بعد از نوشتن راهکار مورد نیازی که در ان از جاب استفاده شده است یا ان را ایجاد می کند تنها انجام دادن دو کار کفایت میکند:

  1.  تنظیم اشاره شده را از طریق پاورشل غیرفعال کرد.
  2. ویژگی یا فیچر راهکار را هم از طریق پاورشل فعال و یا غیر فعال کرد.

با انجام این دوکار که معمولا برای راهکارها صورت نمیپذیرد می توان از این قابلیت شیرپوینت بهره ی کامل را برد. برای فعال سازی فیچر میتونید از دستور پاورشل شیرپوینتی زیر استفاده کنید:

Enable-spfeature -identity 8cc7fa2e-937e-41db-add7-e6647d33f7ed -url http://homelab:82

حال با دانستن این پیش شرط ها و نحوه ی برطرف کردن انها بهتر هست در مورد ایجاد و حذف انها مقداری توضیح بدم.

جاب هایی که معمولا برای استفاده در راهکارهای شیرپوینتی نوشته می شوند نیاز دارند که با فعال شدن فیچر مربوط به راهکار نیز ایجاد شوند. و با غیرفعال شدن ان هم حذف شوند.

این جاب ها قابلیت تنظیم شروع و پایان دارند و با فراهم کردن کلاسی که از کلاس SPJobDefinition مشتق میشود امکان تعریف و نوشتن کدهای لازمه را فراهم میکند. میتوان از طریق کد زیر نمونه ی جدید از یک جاب را ایجاد و به لیست جاب های یک Web Application اضافه نمود:

                  NotificationJob testJob = new NotificationJob("test job", site.WebApplication);

                  SPHourlySchedule hourly = new SPHourlySchedule();
                  hourly.BeginMinute = 1;
                  hourly.EndMinute = 59;

                  testJob.Title = "test job";
                  testJob.Schedule = hourly;
                  testJob.Properties.Add("siteurl", site.Url);
                  testJob.Update();

در کد بالا کلاس NotificationJob که نمونه ی جدیدی از ان ایجاد شده است همان کلاسی هست که می بایست از کلاس اصلی جاب یعنی SPJobDefinition مشتق شود. پارامترهای مورد نیاز ان نام جاب و Web Application ی هست که می بایست جاب به ان اضافه شود.

سپس نوبت به زمانبندی جاب میرسد که در این جا به صورت دوره ای و ساعتی در دقیقه ی 1، ساعت اجرا و نهایتا در دقیقه ی 59 هر ساعت متوقف خواهد شد البته در صورت پایان کار ان زودتر متوقف خواهد شد. همچنین در خط 9 همانطور که مشاهده میکنید میتوان مقادیر مختلفی را به صورت پراپرتی به ان پاس داد تا در زمان اجرای جاب از ان ها استفاده کرد، یکی از این مقادیر که خیلی استفاده می شود ادرس سایت و یا وبی هست که راهکار در ان قرار دارد، معمولا برای دسترسی به یک لیست و یا غیره به ان نیاز پیدا خواهد شد.

و در نهایت با فراخوانی متد Update جاب ما ایجاد و به Web application اضافه خواهد شد.

به منظور حذف جاب ایجاد شده هم که معمولا در زمان قبل از ایجاد جاب برای اطمینان از عدم وجود ان و در زمان غیرفعال کردن ویژگی راهکار نوشته می شود هم به صورت زیر می توان نوشت:

                  foreach (SPJobDefinition job in site.WebApplication.JobDefinitions)
                  {
                     if (job.Name.Equals("test job", StringComparison.OrdinalIgnoreCase))
                     {
                        job.Delete();
                        break;
                     }
                  }

در این کد site همان آبجکت SPSite می باشد که در راهکار کاملا در دسترس خواهد بود و مابقی کد هم که کامل ساده و مشخص می باشد.

خب بعد از ایجاد و حذف جاب نوبت به خود کلاس جاب که در اینجا NotificationJob می باشد می رسد:

   public class NotificationJob : SPJobDefinition
   {
      public NotificationJob() : base() { }

      public NotificationJob(string jobName, SPWebApplication webApplication)
         : base(jobName, webApplication, SPServer.Local, SPJobLockType.Job)
      {
         this.Title = jobName;
      }

      public override void Execute(Guid targetInstanceId)
      {
         string siteUrl = this.Properties["siteurl"].ToString();

         using (SPSite site = new SPSite(siteUrl))
         {
            using (SPWeb web = site.OpenWeb())
            {
		     // کد شما در اینجا
            }
         }
      }
   }

این کلاس از یک مند اصلی که Execute نام دارد تشکیل شده است و کدهای موجود در ان هم که کاملا مشخص می باشد و البته یک سازنده هم دارد که می بایست مقادیر مورد نیاز برای اجرای جاب را به سازنده ی اصلی کلاس یعنی سازنده ی کلاس SPJobDefinition پاس داد. این مقادیر هم که البته از نام انها مشخص هست که چی هستند.

در پایان هم باید گفت که در صورت ندانستن اطلاعات کافی از این شرایط و آبجکت مدل ها به احتمال زیاد با مشکلات زیاد مواجه خواهید شد، که خود بنده هم مواجه شدم. فقط نکته ی پایانی رو هم اضافه کنم که برای دیباگ کدهای این کلاس می بایست به پراسس owstimer.exe اتچ کنید و پس از هر تغییر هم میبایست کد جدید کامپایل شود و در GAC قرار گیرد و این سرویس هم ریست شود.

نظرات (2) -

  • mghorbani

    11/13/1392 10:01:46 ب.ظ | پاسخ به این نظر

    اطلاعات کاربردی خوبی در اختیارمون قرار دادی...ممنون.
    فقط سئوالی که برای من پیش اومد این هست که job های زیادی توی شیرپوینت داریم که دارند درست کار میکنند و این در حالی هست که Application Pool هر وب اپلیکیشن ممکنه متفاوت با App Pool وب اپلیکیشن فارم باشه. این موضوع رو چطور میتونی توجیه کنی؟

    • حمید

      11/13/1392 10:24:38 ب.ظ | پاسخ به این نظر

      خب این ارتباط به صورت یک طرفه و از سمت جاب هست و نه از سمت جای دیگه به جاب و ضمن اینکه تمام نمونه های جاب با کاربر سرویس تایمر شیرپوینت اجرا و مشتق میشند. و در واقع مشکل ایجاد و شروع جاب هست و بعد از اون دیگه کار تموم هست و مباحث دسترسی مطرح نیست

Loading