Angella Andrea - Italian Blog

Infinita passione per lo sviluppo software !
posts - 133, comments - 216, trackbacks - 9

My Links

News

MIT OpenCourseWare: I'm invested Wikipedia Affiliate Button


Sto leggendo:

Archives

Post Categories

Siti web realizzati

Siti web tecnici

[70-536] - Creating Windows Services - parte 1 di 2


Area di riferimento

- Implementing service processes, threading, and application domains in a .NET Framework application
   - Implement, install, and control a service
      - Inherit from ServiceBase class
      - ServiceInstaller and ServiceProcessInstaller class
      - SessionChangeDescription structure and SessionChangeReason enumeration



Servizi di Windows

I servizi di Windows sono processi che vengono eseguiti in background e non hanno interfaccia grafica. I servizi rappresentano un modo ideale per implementare applicazioni che devono essere costantemente in esecuzione e che non necessitano dell'intervento dell'utente. Esempi classici sono le applicazioni server come Microsoft SQL Server.

I servizi possono essere eseguiti all'avvio del sistema operativo (anche prima del log on) oppure possono essere avviati/fermati manualmente. In Windows XP e Vista è possibile gestire i servizi di sistema da "Pannello di Controllo" -> "Strumenti di amministrazione" -> "Servizi" oppure si può utilizzare il comando net start "servizio" e net stop "servizio":

Servizi Vista

Vediamo come la realizzazione di servizi si differenzia dalla realizzazione di normali applicazioni:

  • Non è posibile lanciare il servizio all'interno dell'IDE ma questo deve essere installato e avviato
  • Il debugging è più complicato
  • Eventuali errori dovranno essere segnalati nell'Event Log di Window piuttosto che tramite una interfaccia grafica
  • Il contesto di sicurezza in cui sono eseguiti i servizi è generalmente diverso rispetto a quello dell'account utente. E' importante lanciare un servizio con i minori privilegi possibili in modo da minimizzare i danni che potrebbe provocare.

All'interno dell'IDE Microsoft Visual Studio 2005 Professional è presente un template che crea automaticamente lo scheletro necessario all'implementazione di un servizio windows.

Il codice generato per l'avvio del servizio è il seguente:

   static class Program
   {
       /// <summary>
       /// The main entry point for the application.
       /// </summary>
       static void Main()
       {
           ServiceBase[] ServicesToRun;

           // More than one user Service may run within the sameprocess. To add
           // another service to this process, change the following line to
           // create a second service object. For example,
           //
           //   ServicesToRun = new ServiceBase[] {new Service1(), new MySecondUserService()};
           //

           
           ServicesToRun = new ServiceBase[] { new Service1() };
           ServiceBase.Run(ServicesToRun);
       }
   }


Il metodo statico Run della classe ServiceBase serve per mandare in esecuzione all'interno di un processo uno o più servizi. Un servizio è un oggetto che deriva dalla classe ServiceBase, che ridefinisce tutti o alcuni dei seguenti metodi:

  • OnStart()

    Si inserisce all'interno di questo metodo il codice di inizializzazione del servizio e generalmente si avvia un timer in quanto è necessario che questo metodo ritorni al sistema operativo.

  • OnStop()

    Contiene le azioni quando viene rischiesta l'interruzione del servizio.

  • OnPause(), OnContinue()

    Questi metodi vengono chiamati per mettere in pausa e ripristinare un servizio. E' necessario impostare a true il flag ServiceBase.CanPauseAndContinue del servizio.

  • OnShutdown()

    Metodo eseguito quando viene inviato il segnale di shutdown al computer. E' necessario impostare a true il flag ServiceBase.CanShutdown del servizio.

  • OnSessionChange()

    La struttura SessionChangeDescription identifica il motivo di una modifica di sessione di Terminal Server come ad esempio il LogOn e il LogOff. Per approfondimenti vedere la documentazione msdn su SessionChangeDescription.

All'interno di questi metodi è possibile inserire qualsiasi codice che rispetti i privilegi posseduti dal processo.
Ecco un esempio di un servizio che ogni 10 secondi esegue una qualche azione:

   public partial class Service1 : ServiceBase
   {
       private Timer _timer;

       public Service1()
       {
           InitializeComponent();

           // Imposto il nome del servizio
          
this.ServiceName = "MioServizio";

                // Imposto che il servizio può essere messo in pausa e gestire lo shutdown

           this.CanPauseAndContinue = true;
           this.CanShutdown = true;
      

                    _timer = new Timer(10000);
           _timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);

       }
       protected override void OnStart(string[] args)
       {
           _timer.Start();

       }
       protected override void OnStop()
       {
           _timer.Stop();
       }
       protected override void OnPause()
       {
           _timer.Stop();
       }
       protected override void OnContinue()
       {
           _timer.Start();
       }
       protected override void OnShutdown()
       {
           _timer.Stop();
       }
       void _timer_Elapsed(object sender, ElapsedEventArgs e)
       {
           // Codice da eseguire periodicamente...           
       }
   }


Per offrire la possibilità di installare un servizio il .NET Framework fornisce le classi ServiceInstaller e ServiceProcessInstaller. La classe ServiceInstaller mantiene le informazioni sul servizio mentre la classe ServiceProcessInstaller mantiene le impostazioni relative al contesto di sicurezza in cui sarà eseguio il servizio. Grazie a Visual Studio tutto il codice necessario può essere generato cliccando "Add Installer" dopo aver fatto click con il tasto destro del mouse nella modalità design view del servizio.

Basta solamente impostare le seguenti cose:

  • StartType di ServiceInstaller a "Automatic", "Manual" o "Disabled"
    In questo modo si specifica se il servizio dovrà essere avviato automaticamente all'avvio del sistema oppure no.
  • Description e DisplayName di ServiceInstaller
  • Account di ServiceProcessInstaller a "LocalService", "NetworkService", "LocalSystem" o "User"
    Con questa proprietà si specifica il contesto di sicurezza entro il quale opererà il servizio.
  • Nelle proprietà del progetto impostare lo "Startup Object" cioè la classe Program

Il codice generato dal designer è il seguente:

    [RunInstaller(true)]
    public partial class ProjectInstaller : Installer
    {
        public ProjectInstaller()
        {
            InitializeComponent();
        }
    }

    partial class ProjectInstaller
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }
        #region Component Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.serviceProcessInstaller1 = new System.ServiceProcess.ServiceProcessInstaller();
            this.serviceInstaller1 = new System.ServiceProcess.ServiceInstaller();
            //
            // serviceProcessInstaller1
            //
            this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
            this.serviceProcessInstaller1.Password = null;
            this.serviceProcessInstaller1.Username = null;
            //
            // serviceInstaller1
            //

            this.serviceInstaller1.DisplayName = "MioServizio";
            this.serviceInstaller1.ServiceName = "MioServizio";

            //
            // ProjectInstaller
            //

            this.Installers.AddRange(new System.Configuration.Install.Installer[] {
            this.serviceProcessInstaller1,
            this.serviceInstaller1});
        }

        #endregion

        private System.ServiceProcess.ServiceProcessInstaller serviceProcessInstaller1;
        private System.ServiceProcess.ServiceInstaller serviceInstaller1;
    }


A questo punto è possibile utilizzare l'utility InstallUtil.exe presente nella directory C:\Windows\Microsoft.NET\Framework\v2.0.50727 (che consiglio di inserire nella variabile di ambiente PATH) per installare/disinstallare manualmente il servizio dalla linea di comando.

Per installare il servizio di nome "MioServizio":

InstallUtil MioServizio.exe

Per disinstallare il servizio di nome "MioServizio":

InstallUtil /u MioServizio.exe

Print | posted on domenica 30 dicembre 2007 22:21 | Filed Under [ Exam 70-536 Application Development Foundation ]

Comments have been closed on this topic.

Powered by:
Powered By Subtext Powered By ASP.NET