# دریافت زمانبندی شده به روز رسانی‌های آنتی ویروس Symantec به کمک کتابخانه‌های Quartz.NET و Html Agility Pack

در این رابطه آقای راد در دو قسمت به صورت مختصر و مفید این کتابخانه قدرتمند رو همراه با ارائه چندین مثال کاربردی معرفی کردند: قسمت اول قسمت دوم در تکمیل قسمت‌های فوق بنده می‌خوام مثالی رو در این رابطه 

- Published: 2013-06-24
- Language: fa
- Tags: DNTips
- Canonical: https://sirwan.info/blog/fa/dntips-1395

---

> این نوشته نخستین بار در [دات‌نت تیپس](https://www.dntips.ir/post/1395) منتشر شده است.

<div class="postBody">در این رابطه آقای راد در دو قسمت به صورت مختصر و مفید این کتابخانه قدرتمند رو همراه با ارائه چندین مثال کاربردی معرفی کردند:<br/><a href="https://www.dntips.ir/post/997">قسمت اول</a><br/><a href="https://www.dntips.ir/post/999">قسمت دوم</a><br/>
در تکمیل قسمت‌های فوق بنده می‌خوام مثالی رو در این رابطه براتون بذارم، هدف از ارائه این مثال اتوماتیک سازی یک فرآیند روتین می‌باشد، به این صورت که در جایی که بنده مشغول به کار هستم یک سری لایسنس آنتی ویروس برای کلاینت‌ها در یک شبکه با مقیاس متوسط تهیه گردیده است، حال یک نسخه رایگان نیز برای کاربرانی که قصد دارند آنتی ویروس را برای سیستم شخصی خود نصب کنند نیز موجود می‌باشد که نیاز به آپدیت دارد معمولا آپدیت‌ها هر چند روز یکبار یا هر هفته در دو نسخه 64 و 32 بیتی ارائه می‌شوند، روال معمول برای دریافت آپدیت مراجعه به سایت و دانلود نسخه‌های مربوطه میباشد.<br/><hr/>حال توسط کتابخانه قدرتمند <a href="http://quartznet.sourceforge.net/">Quartz.NET</a>  این فرآیند روتین را به صورت اتوماتیک می‌خواهیم انجام دهیم، استفاده از کتابخانه ذکر شده سخت نیست همانطور که در دو مطلب قبلی مرتبط ذکر گردیده، تنها پیاده سازی چندین اینترفیس است و بس.<br/><br/><div align="left" dir="ltr">
<pre language="CSharp" name="code">namespace SymantecUpdateDownloader&#10;{&#10;    using System;&#10;    using System.IO;&#10;    using Quartz;&#10;    using Quartz.Impl;&#10;    using System.Globalization;&#10;    public class TestJob : IJob&#10;    {&#10;        public void Execute(IJobExecutionContext context)&#10;        {&#10;            new Download().Scraping();&#10;        }&#10;    }&#10;    public interface ISchedule&#10;    {&#10;        void Run();&#10;    }&#10;    public class TestSchedule : ISchedule&#10;    {&#10;        public void Run()&#10;        {&#10;            &#10;            DateTimeOffset startTime = DateBuilder.FutureDate(2, IntervalUnit.Second);&#10;&#10;            IJobDetail job = JobBuilder.Create&lt;HelloJob&gt;()&#10;                                       .WithIdentity("job1")&#10;                                       .Build();&#10;&#10;            ITrigger trigger = TriggerBuilder.Create()&#10;                                             .WithIdentity("trigger1")&#10;                                             .StartAt(startTime)&#10;                                             .WithDailyTimeIntervalSchedule(x =&gt; x.OnEveryDay().StartingDailyAt(new TimeOfDay(7, 0)).WithRepeatCount(0))&#10;                                             .Build();&#10;&#10;            ISchedulerFactory sf = new StdSchedulerFactory();&#10;            IScheduler sc = sf.GetScheduler();&#10;            sc.ScheduleJob(job, trigger);&#10;&#10;            sc.Start();&#10;        }&#10;    }&#10;}</pre>
</div>
در این کد که همانند کدهای پیشنیازهای مطلب است، در خط 33 از متد WithDailyTimeIntervalSchedule استفاده شده است و همانطور که مشخص است وظیفه تعیین شده و هر روز ساعت 7 اجرا میشود.<br/>
مورد بعدی عملیات دانلود فایل می‌باشد که در ادامه مشاهده خواهید کرد، <a href="https://www.symantec.com/security_response/definitions/download/detail.jsp?gid=savce">صفحه ایی</a>  که لینک فایل‌های دانلود را ارائه داده است دو نسخه مد نظر ما را در ابتدا لیست کرده است و با استفاده از web scrapingمی توانیم موارد تعیین شده را استخراج کنیم برای این منظور از کتابخانه <a href="http://htmlagilitypack.codeplex.com/">htmlagilitypack </a>استفاده میکنیم، تطبیق دو مورد(لینک) اول جهت دریافت نسخه‌های 32 و 64 بیتی به کمک Regular Expression میسر است و همانطور که در شکل زیر مشاهده میکنید از سمت چپ تاریخ به صورت 8 رقم، سه رقم قسمت دوم و ارقام و حروف قسمت سوم است به اضافه پسوند فایل مشخص است :<br/><p><img src="/img/dntips/e9d7c9adfcaf42ce2a3f.png" style="display: block; margin-left: auto; margin-right: auto; cursor: default;"/></p><br/><div align="left" dir="ltr">
<pre language="CSharp" name="code">public class Download&#10;    {&#10;        static WebClient wc = new WebClient();&#10;        static ManualResetEvent handle = new ManualResetEvent(true);&#10;        &#10;        private DateTime myDate = new DateTime();&#10;        public void Scraping()&#10;        {&#10;            using (WebClient client = new WebClient())&#10;            {&#10;                client.Encoding = System.Text.Encoding.UTF8;&#10;                var doc = new HtmlAgilityPack.HtmlDocument();&#10;                ArrayList result = new ArrayList();&#10;                doc.LoadHtml(client.DownloadString("https://www.symantec.com/security_response/definitions/download/detail.jsp?gid=savce"));&#10;                var tasks = new List&lt;Task&gt;();&#10;                foreach (var href in doc.DocumentNode.Descendants("a").Select(x =&gt; x.Attributes["href"]))&#10;                {&#10;                    if (href == null) continue;&#10;                    string s = href.Value;&#10;                    Match m = Regex.Match(s, @"http://definitions.symantec.com/defs/(\d{8}-\d{3}-v5i(32|64)\.exe)");&#10;                    if (m.Success)&#10;                    {&#10;                        Match date = Regex.Match(m.Value, @"(\d{4})(\d{2})(\d{2})");&#10;                        Match filename = Regex.Match(m.Value, @"\d{8}-\d{3}-v5i(32|64)\.exe");&#10;                        int year = Int32.Parse(date.Groups[0].Value);&#10;                        int month = Int32.Parse(date.Groups[1].Value);&#10;                        int day = Int32.Parse(date.Groups[3].Value);&#10;&#10;                        myDate = new DateTime(&#10;                                Int32.Parse(date.Groups[1].Value),&#10;                                Int32.Parse(date.Groups[2].Value),&#10;                                Int32.Parse(date.Groups[3].Value));&#10;                        if (myDate == DateTime.Today)&#10;                        {&#10;                            tasks.Add(DownloadUpdate(m.Value, filename.Value));&#10;                        }&#10;                        else&#10;                        {&#10;                            MessageBox.Show("امروز آپدیت موجود نیست");&#10;                        }&#10;                    }&#10;                }&#10;                DownloadTask = Task.WhenAll(tasks);&#10;            }&#10;        }&#10;        private static Task DownloadTask;&#10;        private Task DownloadUpdate(string url, string fileName)&#10;        {&#10;            var wc = new WebClient();&#10;            return wc.DownloadFileTaskAsync(new Uri(url), @"\\10.1.0.15\SymantecUpdate\\" + fileName);&#10;        }&#10;&#10;    }</pre>
</div>
توضیح کدهای فوق :<br/>
ابتدا توسط متد LoadHtml خط 14 صفحه مورد نظر که حاوی لینک‌ها می‌باشد رو Load میکنیم، سپس توسط یک حلقه foreach خط 16 مقدار خصوصیت href تمام لینک‌های موجود  در صفحه را استخراج میکنیم مثلا مقدار خصوصیت href در لینک‌ها به صورت  زیر می‌باشد :<br/>
 
<br/><div align="left" dir="ltr">
<pre language="CSharp" name="code">http://definitions.symantec.com/defs/20130622-007-v5i32.exe</pre>
</div><br/><div align="left" dir="ltr">
<pre language="CSharp" name="code">http://definitions.symantec.com/defs/20130622-007-v5i64.exe</pre>
</div><br/>
همانطور که مشخص است در دو مورد فوق تنها نام فایل متفاوت می‌باشد، همانطور که بحث شد برای نام فایل‌ها هم می‌توانیم یک Pattern را به صورت زیر داشته باشیم :<br/><div align="left" dir="ltr">
<pre language="CSharp" name="code">(\d{8}-\d{3}-v5i(32|64)\.exe)</pre>
</div>
در خط 20 نیز عملیات تطبیق تمام href‌های موجود در صفحه را توسط Regular Expression فوق تطبیق می‌دهیم، اگر تطبیق با موفقیت انجام پذیرفت باید نام فایل و همچنین تاریخ موجود در نام فایل را نیز توسط دو Regular Expression استخراج کنیم(خط 23 و 24) در ادامه برای جدا کردن مقادیر سال ، ماه ، روز از امکان Groups در RegEx استفاده کرده ایم:<br/><div align="left" dir="ltr">
<pre language="CSharp" name="code">int year = Int32.Parse(date.Groups[0].Value);&#10;int month = Int32.Parse(date.Groups[1].Value);&#10;int day = Int32.Parse(date.Groups[3].Value);</pre>
</div>
در ادامه تاریخ استخراج شده را با تاریخ روز جاری مقایسه می‌کنیم اگر مساوی بود عملیات دانلود فایل‌ها توسط یک <a href="http://msdn.microsoft.com/en-us/library/system.threading.tasks.task.aspx">Task</a> تعریف شده به صورت <a href="http://msdn.microsoft.com/en-us/library/hh159424.aspx">همزمان</a>  بر روی سرور مربوطه دانلود می‌شوند.<br/>
البته لازم به ذکر است که کدهای فوق مسلما نیاز یه Refactoring دارند منتها هدف از ارائه این مثال آشنایی بیشتر با کتابخانه‌های فوق می‌باشد.<br/>
نکته آخر اینکه برنامه فوق به حالت‌های مختلفی می‌تواند اجرا گردد مثل یک برنامه وب  یا یک سرویس ویندوزی و ... ، بهترین حالت یک سرویس ویندوز می‌باشد، ولی در حالت خام در حال حاضر یک ویندوز اپلیکیشن ساده می‌باشد که بر روی سرور RUN شده است که در آینده به صورت یک سرویس ویندوز ارائه خواهد شد.<br/></div>
