نوشتن در Log File با استفاده از Windows Service در سی شارپ و VB.Net

Windows Service

در این مقاله ما به همراه مثال، به شما نحوه ایجاد یک Windows Service ساده را در زبان C# و VB.Net آموزش خواهیم داد. این Windows Service از دو حالت پشتیبانی خواهد کرد.

حالت بازه (Interval): زمانی که ویندوز سرویس بعد از کمی تاخیر کار یا وظیفه (task) مهمی را در فواصل زمانی منظم اجرا می کند.

حالت روزانه (Daily): زمانی که ویندوز سرویس در بعضی از ساعات روز یک کار خاصی را اجرا می کند.

ایجاد یک پروژه Windows Service:

در قدم اول یک پروژه جدید از نوع Windows Service به صورت زیر ایجاد کنید.

 

اضافه کردن فایل App.Config

در مرحله ی بعد باید یک فایل پیکربند اپلیکیشن (App.Config file) اضافه کنید. از آن برای کنترل کردنWindows Service و استفاده از دیگر حالت های آن استفاده می شود.

 

بعد از اضافه کردن فایل، باید تنظیمات اپلیکیشن AppSettings زیر را در فایل App.Config کپی کنید.

<?xmlversion="1.0"encoding="utf-8" ?>
<configuration>
    <appSettings>
        <add key ="Mode" value ="Daily"/>
        <!-- <add key ="Mode" value ="Interval"/>-->
        <add key ="IntervalMinutes" value ="1"/>
        <add key ="ScheduledTime" value ="18:41"/>
    </appSettings>
</configuration>

در زیر در مورد هر AppSettings توضیح داده شده است.

حالت (Mode): برای تنظیم کردن حالت استفاده می شود. دو نوع از آن وجود دارد، روزانه (Daily) و بازه (Interval).

IntervalMinutes: وقتی که روی حالت بازه (Interval) تنظیم شده باشد از آن استفاده می کنیم. که شامل مقادیر Interval (فاصله) در دقیقه می شود بعد از اینکه ویندوز سرویس یک وظیفه (task) را اجرا کرد. به عبارت دیگر همان مقادیر تاخیر می باشد.

ScheduledTime (زمان برنامه ریزی شده): از این وضعیت برای زمانی که روی حالت روزانه تنظیم شده باشد استفاده می کنیم. از آن برای آگاه ساختن ویندوز سرویس برای انجام دادن وظایف استفاده می شود. مقدار آن روی قالب زمانی ۲۴ ساعت تنظیم شده است.

Timer Configuration (تنظیمات زمان سنج)

کد زیر باید در Service.cs جای گذاری شود. ما از کلاس زمان سنج که به System.Threading متعلق می باشد به منظوره اجرای ویندوز سرویس در فواصل معین و منظم استفاده می کنیم.

این زمان سنج یک روش Callback دارد که ئقتی زمان انجام به پایان برسد به صورت خودکار اجرا می شود.

حالا شروع به جای گزاری namespace های زیر کنید.

C#

using System.IO;
using System.Threading;
using System.Configuration;

VB.Net

Imports System.IO
Imports System.Threading
Imports System.Configuration

در زیر درباره کلاس ویندوز سرویس با کنترل کننده رخداد های OnStart و OnStop توضیح داده شده است.

زمانی که ویندوز سرویس شروع به فراخواندن متود ScheduleService کرد که در ابتدا توضیح داده شد، یک ScheduledTime متغیر وجود دارد که روی هر دو حالت تنظیم شده است.

وقتی که حالت روی Daily تنظیم شده باشد، آنگاه ScheduledTime از AppSettings خوانده می شود. اگر زمان برنامه ریزی شده (scheduled time) سپری شد، به روز بعد در همان ساعت بروز خواهد شد.

وقتی که حالت روی Interval تنظیم شده باشد، آنگاه IntervalMinutes از AppSettings خوانده می شود و زمان برنامه ریزی شده با اضافه کردن IntervalMinutes به زمان فعلی محاسبه می شود.

در نهایت زمان سنج برای اجرای scheduled time تنظیم می شود. وقتی زمان برنامه ریزی شده به پایان رسید، متود Callback زمان سنج اجرا می شود که اطلاعات و زمان فعلی را روی یک فایل متنی ثبت می کند.

C#

public partial class Service1 : ServiceBase
{
    public Service1()
    {
        InitializeComponent();
    }
 
    protected override void OnStart(string[] args)
    {
        this.WriteToFile("Simple Service started {0}");
        this.ScheduleService();
    }
 
    protected override void OnStop()
    {
        this.WriteToFile("Simple Service stopped {0}");
        this.Schedular.Dispose();
    }
 
    private Timer Schedular;
 
    public void ScheduleService()
    {
        try
        {
            Schedular = new Timer(new TimerCallback(SchedularCallback));
            string mode = ConfigurationManager.AppSettings["Mode"].ToUpper();
            this.WriteToFile("Simple Service Mode: " + mode + " {0}");
 
            //Set the Default Time.
            DateTime scheduledTime = DateTime.MinValue;
 
            if (mode == "DAILY")
            {
                //Get the Scheduled Time from AppSettings.
                scheduledTime = DateTime.Parse(System.Configuration.ConfigurationManager.AppSettings["ScheduledTime"]);
                if (DateTime.Now > scheduledTime)
                {
                    //If Scheduled Time is passed set Schedule for the next day.
                    scheduledTime = scheduledTime.AddDays(1);
                }
            }
 
            if (mode.ToUpper() == "INTERVAL")
            {
                //Get the Interval in Minutes from AppSettings.
                int intervalMinutes = Convert.ToInt32(ConfigurationManager.AppSettings["IntervalMinutes"]);
 
                //Set the Scheduled Time by adding the Interval to Current Time.
                scheduledTime = DateTime.Now.AddMinutes(intervalMinutes);
                if (DateTime.Now > scheduledTime)
                {
                    //If Scheduled Time is passed set Schedule for the next Interval.
                    scheduledTime = scheduledTime.AddMinutes(intervalMinutes);
                }
            }
 
            TimeSpan timeSpan = scheduledTime.Subtract(DateTime.Now);
            string schedule = string.Format("{0} day(s) {1} hour(s) {2} minute(s) {3} seconds(s)", timeSpan.Days, timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds);
 
            this.WriteToFile("Simple Service scheduled to run after: " + schedule + " {0}");
 
            //Get the difference in Minutes between the Scheduled and Current Time.
            int dueTime = Convert.ToInt32(timeSpan.TotalMilliseconds);
 
            //Change the Timer's Due Time.
            Schedular.Change(dueTime, Timeout.Infinite);
        }
        catch(Exception ex)
        {
            WriteToFile("Simple Service Error on: {0} " + ex.Message + ex.StackTrace);
 
            //Stop the Windows Service.
            using (System.ServiceProcess.ServiceController serviceController = new System.ServiceProcess.ServiceController("SimpleService"))
            {
                serviceController.Stop();
            }
        }
    }
 
    private void SchedularCallback(object e)
    {
        this.WriteToFile("Simple Service Log: {0}");
        this.ScheduleService();
    }
 
    private void WriteToFile(string text)
    {
        string path = "C:\\ServiceLog.txt";
        using (StreamWriter writer = new StreamWriter(path, true))
        {
            writer.WriteLine(string.Format(text, DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt")));
            writer.Close();
        }
    }
}

VB.Net

Public Class Service1
 
    Protected Overrides Sub OnStart(ByVal args() As String)
        Me.WriteToFile("Simple Service started at " + DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt"))
        Me.ScheduleService()
    End Sub
 
    Protected Overrides Sub OnStop()
        Me.WriteToFile("Simple Service stopped at " + DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt"))
        Me.Schedular.Dispose()
    End Sub
 
    Private Schedular As Timer
 
    Public Sub ScheduleService()
        Try
            Schedular = New Timer(New TimerCallback(AddressOf SchedularCallback))
            Dim mode As String = ConfigurationManager.AppSettings("Mode").ToUpper()
            Me.WriteToFile((Convert.ToString("Simple Service Mode: ") & mode) + " {0}")
 
            'Set the Default Time.
            Dim scheduledTime As DateTime = DateTime.MinValue
 
            If mode = "DAILY" Then
                'Get the Scheduled Time from AppSettings.
                scheduledTime = DateTime.Parse(System.Configuration.ConfigurationManager.AppSettings("ScheduledTime"))
                If DateTime.Now > scheduledTime Then
                    'If Scheduled Time is passed set Schedule for the next day.
                    scheduledTime = scheduledTime.AddDays(1)
                End If
            End If
 
            If mode.ToUpper() = "INTERVAL" Then
                'Get the Interval in Minutes from AppSettings.
                Dim intervalMinutes As Integer = Convert.ToInt32(ConfigurationManager.AppSettings("IntervalMinutes"))
 
                'Set the Scheduled Time by adding the Interval to Current Time.
                scheduledTime = DateTime.Now.AddMinutes(intervalMinutes)
                If DateTime.Now > scheduledTime Then
                    'If Scheduled Time is passed set Schedule for the next Interval.
                    scheduledTime = scheduledTime.AddMinutes(intervalMinutes)
                End If
            End If
 
            Dim timeSpan As TimeSpan = scheduledTime.Subtract(DateTime.Now)
            Dim schedule As String = String.Format("{0} day(s) {1} hour(s) {2} minute(s) {3} seconds(s)", timeSpan.Days, timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds)
 
            Me.WriteToFile((Convert.ToString("Simple Service scheduled to run after: ") & schedule) + " {0}")
 
            'Get the difference in Minutes between the Scheduled and Current Time.
            Dim dueTime As Integer = Convert.ToInt32(timeSpan.TotalMilliseconds)
 
            'Change the Timer's Due Time.
            Schedular.Change(dueTime, Timeout.Infinite)
        Catch ex As Exception
            WriteToFile("Simple Service Error on: {0} " + ex.Message + ex.StackTrace)
 
            'Stop the Windows Service.
            Using serviceController As New System.ServiceProcess.ServiceController("SimpleService")
                serviceController.[Stop]()
            End Using
        End Try
    End Sub
 
    Private Sub SchedularCallback(e As Object)
        Me.WriteToFile("Simple Service Log: " + DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt"))
        Me.ScheduleService()
    End Sub
 
    Private Sub WriteToFile(text As String)
        Dim path As String = "C:\ServiceLog.txt"
        Using writer As New StreamWriter(path, True)
            writer.WriteLine(String.Format(text, DateTime.Now.ToString("dd/MM/yyyy hh:mm:ss tt")))
            writer.Close()
        End Using
    End Sub
End Class

اضافه کردن Installer (برنامه نصب) به ویندوز سرویس

زمانی که ویندوز سرویس آماده شد باید Installer را به ویندوز سرویس خود اضافه کنیم.

تضاویر زیر روش اضافه کردن آن به ویندوز سرویس می باشند.

روی Service1.cs کلیک راست کنید سپس روی View Designer در context menu کلیک کنید.

 

زمانی که View Designer نمایش داده شد، باید کلیک راست کنید و Add Installer را انتخاب کنید.

 

تنظیم کردن اسم و StartType ویندوز سرویس

با انجام اعمال بالا یک Installer به نام ProjectInstaller اضافه می شود. حالا نیاز دارید که ProjectInstaller.Designer را باز کرده و به دنبال متود InitializeComponent بگردید.

در این روش ما ServiceName ویندوز سرویس را اضلاح می کنیم و هم چنین StartType آن را روی حالت اتوماتیک تنظیم می کنیم، در نهایت ویندوز سرویس به صورت اتوماتیک اجرا می شود.

C#

private void InitializeComponent()
{
    this.serviceProcessInstaller1 = new System.ServiceProcess.ServiceProcessInstaller();
    this.serviceInstaller1 = new System.ServiceProcess.ServiceInstaller();
    //
    // serviceProcessInstaller1
    //
    this.serviceProcessInstaller1.Password = null;
    this.serviceProcessInstaller1.Username = null;
    //
    // serviceInstaller1
    //
 
    //Set the ServiceName of the Windows Service.
    this.serviceInstaller1.ServiceName = "SimpleService";
 
    //Set its StartType to Automatic.
    this.serviceInstaller1.StartType = System.ServiceProcess.ServiceStartMode.Automatic;
 
    //
    // ProjectInstaller
    //
    this.Installers.AddRange(new System.Configuration.Install.Installer[] {
    this.serviceProcessInstaller1,
    this.serviceInstaller1});
}

VB.Net

Private Sub InitializeComponent()
    Me.ServiceProcessInstaller1 = New System.ServiceProcess.ServiceProcessInstaller()
    Me.ServiceInstaller1 = New System.ServiceProcess.ServiceInstaller()
    '
    'ServiceProcessInstaller1
    '
    Me.ServiceProcessInstaller1.Password = Nothing
    Me.ServiceProcessInstaller1.Username = Nothing
    '
    'ServiceInstaller1
    '
    'Set the ServiceName of the Windows Service.
    Me.ServiceInstaller1.ServiceName = "SimpleService"
 
    'Set its StartType to Automatic.
    Me.ServiceInstaller1.StartType = System.ServiceProcess.ServiceStartMode.Automatic
 
    '
    'ProjectInstaller
    '
    Me.Installers.AddRange(New System.Configuration.Install.Installer() {Me.ServiceProcessInstaller1, Me.ServiceInstaller1})
End Sub

تنظیم کردن ویندوز سرویس روی حالت اجرای خودکار بعد از نصب

بعد از نصب، ویندوز سرویس باید از طریق Services section (بخش خدمات) مدیریت کامپیوتر به صورت دستی شروع شود.

می توانیم ویندوز سرویس را به صورت خودکار بعد از نصب آن با استفاده از AfterInstall اجرا کنیم.

لازم است که شما کلاس ProjectInstaller را باز کنید و کنترل کننده رخداد های AfterInstall را لغو کنید و کد را اضافه کنید تا ویندوز سرویس اجرا شود.

C#

[RunInstaller(true)]
public partial class ProjectInstaller : System.Configuration.Install.Installer
{
    public ProjectInstaller()
    {
        InitializeComponent();
    }
 
    protected override void OnAfterInstall(IDictionary savedState)
    {
        base.OnAfterInstall(savedState);
 
        //The following code starts the services after it is installed.
        using (System.ServiceProcess.ServiceController serviceController = new System.ServiceProcess.ServiceController(serviceInstaller1.ServiceName))
        {
            serviceController.Start();
        }
    }
}

VB.Net

Public Class ProjectInstaller
    Public Sub New()
        MyBase.New()
        'This call is required by the Component Designer.
        InitializeComponent()
        'Add initialization code after the call to InitializeComponent
    End Sub
 
    Protected Overrides Sub OnAfterInstall(savedState As IDictionary)
        MyBase.OnAfterInstall(savedState)
 
        'The following code starts the services after it is installed.
        Using serviceController As New System.ServiceProcess.ServiceController(ServiceInstaller1.ServiceName)
            serviceController.Start()
        End Using
    End Sub
End Class

نصب کردن ویندوز سرویس با استفاده از InstallUtil.exe

وقتی تمام فرآیندها به کامل شدند، می توانیم ویندوز سرویس را ایجاد کینم. هنگامی که ویندوز سرویس ساخته شد باید فایل EXE را در پوشه Debug پروژه پیدا کنید.

تذکر: بهتر است که از نسخه Release فایل EXE به جای نسخه Debug استفاده کنید.

برای پیدا کردن آن، روی پروژه کلیک راست کنید . Open Folder in Windows Explorer را انتخاب کنید. حالا به Bin <= پوشه Debug حرکت کنید و به دنبال فایل EXE با همان نام پروژه بگردید.

 

حالا آدرس رو در فایل متنی Notepad کپی و آن را ذخیره کنید.

InstallUtil Syntax

InstallUtil /i <Path of Windows Service EXE file>

مثال:

InstallUtil /i C:\Users\Mudassar\Projects\WindowsService\bin\Debug\WindowsService.exe

حالا Programs => Microsoft Visual Studio 2010 => Visual Studio Tools => Visual Studio Command Prompt (2010) را باز کنید.

InstallUtil را از Notepad کپی کنید و در پنجره command prompt، کلیک کنید و آن را Paste کنید و یک دکمه را فشار دهید.

 

حالا برنامه نصب از شما اجازه ورود (Logon permissions) برای اجرای ویندوز سرویس می خواهد و از این جهت باید نام کاربری و رمز عبور کاربری که مجوز دارد را وارد کنید.

 

بعد از نصب صحیح و کامل پیام زیر را دریافت می کنید.

 

می توانید ویندوز سرویس را در پنجره Services پیدا کنید. برای باز کردن ویندوز سرویس در Run Command، services.msc را تایپ کنید.

 

حذف کردن ویندوز سرویس با استفاده از InstallUtil.exe

نحوه حذف کردن آن کاملا شبیه به نصب کردن آن می باشد.

InstallUtil Syntax

InstallUtil /u <Path of Windows Service EXE file>

مثال:

InstallUtil /u C:\Users\Mudassar\Projects\WindowsService\bin\Debug\WindowsService.exe

و بعد از پاک سازی موفقیت آمیز پیام زیر را دریافت خواهید کرد.

 

موفق باشید !

  • پسورد: www.mspsoft.com
فاطمه زکایی

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

نوشته‌های مرتبط

دیدگاه‌ها

*
*

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