Come abbiamo visto nel precedente articolo, i Servizi di Windows consentono di lasciare un applicazione attiva anche se nessun utente ha effettuato il login sul computer, ma proprio per questa loro caratteristica non hanno (né possono avere) un interfaccia utente.
In questo articolo vedremo come realizzare un applicazione che funga da interfaccia di uno o più servizi: l’idea ispiratrice è il Microsoft Sql Server Service Manager, quella piccola applicazione ben conosciuta a chi ha installato Microsoft Sql Server 2000 e che risiede nella tray-bar per mostrarci lo stato dei servizi legati a Sql Server o permetterci di stopparli, riavviarli o metterli in pausa.
Al cuore di tutto c’è la classe ServiceController che appartiene alla namespace System.ServiceProcesses. Occorre innanzitutto creare una variabile di questo tipo (per comodità riprendo i valori dell’articolo precedente):
Dim controller As New ServiceController controller.ServiceName = "tmFirst" controller.MachineName = "." ' indica il computer locale
A questo punto abbiamo a disposizione tutte le proprietà del servizio; ma non solo, abbiamo a disposizione anche i metodi Start, Stop, Pause e Continue che – rispettivamente – avviano, fermano, mettono in pausa e riavviano il servizio. Diventa perciò sufficiente agganciare una riga tipo
controller.Start
all’handler di un evento qualsiasi come un click di una voce di menu o di un pulsante.
Volendo perciò realizzare un applicazione che controlli un solo servizio, potremmo realizzare un applicazione residente nella tray-bar cui venga legato un menu con le classiche voci “Avvia”, “Ferma”, “Pausa”, “Continua”: al click su una di queste voci, viene creata una variabile ServiceController cui vengono impostate le proprietà MachineName e ServiceName, infine invocato il metodo Start o Stop o Pause o Continua.
Private Sub mnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnStart.Click
Dim controller As New ServiceController
controller.MachineName = "."
controller.ServiceName = "tmFirst"
controller.Start
End Sub
Private Sub mnStop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnStop.Click
Dim controller As New ServiceController
controller.MachineName = "."
controller.ServiceName = "tmFirst"
If controller.CanStop
controller.Stop
End If
End Sub
Private Sub mnPause_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnPause.Click
Dim controller As New ServiceController
controller.MachineName = "."
controller.ServiceName = "tmFirst"
If controller.CanPauseAndContinue
controller.Pause
End If
End Sub
Private Sub mnContinue_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnContinue.Click
Dim controller As New ServiceController
controller.MachineName = "."
controller.ServiceName = "tmFirst"
If controller.CanPauseAndContinue
controller.Continue
End If
End Sub
Come possiamo notare, è buona norma verificare che il servizio possa essere fermato prima di invocare il metodo Stop; analogamente è bene verificare che il servizio possa essere messo in pausa e riavviato (ovviamente le due operazioni “vanno a braccetto”) prima di tentare di metterlo effettivamente in pausa o riavviarlo.
A questo punto potremmo raffinare ulteriormente il programma, abilitando i menu item a seconda dello stato attuale del servizio e delle varie probabilità CanStop e CanPauseAndContinue:
Private Sub EnableMenuItems()
Dim controller As New ServiceController
controller.MachineName = "."
controller.ServiceName = "tmFirst"
Select Case controller.Status
Case ServiceControllerStatus.Paused, ServiceControllerStatus.PausePending
mnStart.Enabled = False
mnPause.Enabled = False
mnStop.Enabled = False
mnContinue.Enabled = True
Case ServiceProcess.ServiceControllerStatus.Stopped, ServiceProcess.ServiceControllerStatus.StopPending
mnStart.Enabled = True
mnPause.Enabled = False
mnStop.Enabled = False
mnContinue.Enabled = False
Case Else
mnStart.Enabled = False
mnPause.Enabled = controller.CanPauseAndContinue
mnStop.Enabled = controller.CanStop
mnContinue.Enabled = controller.CanPauseAndContinue
End Select
End Sub