In questo articolo vedremo come realizzare un servizio per Windows, tramite il linguaggio VB.Net e C#, con Visual Studio 2015 e Framework 4.6. Questa tecnica di creazione dei linguaggi si può utilizzare dalla versione 2010 in poi, e con qualsiasi versione del Framework.
Si apre Visual Studio, e tramite il linguaggio di proprio interesse, selezioniamo i modelli quelli della categoria “Desktop di Windows” a questo punto selezionare il modello di tipo “Servizio Windows” (figura 1), ed assegnare il nome del progetto e confermare il tutto tramite il pulsante ok.
Figura 1 – La selezione del modello del progetto
Si aprirà una schermata tutta di colore griglio, facciamo doppio click sul file “app.config” e dopo il tag “Configuration” inseriamo il tag “appsettings “ dove andremo a scrivere un parametro che utilizzeremo nel servizio per impostare l’intervallo, l’esempio di codice è qui di seguito.
<appSettings>
<!--in millesecondi / 1 secondo = 1000-->
<add key="INTERVALLOATTIVITA" value="2000" />
</appSettings>
Mentre qui di seguito si riporta il codice completo del file di configurazione “App.Config”.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<!--in millesecondi / 1 secondo = 1000-->
<add key="INTERVALLOATTIVITA" value="2000" />
</appSettings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
</configuration>
Passiamo in visualizzazione codice, del file “Service1” in modo che scriviamo il codice per realizzare il nostro primo servizio.
Nell’evento onstart scriviamo il codice che ci permetterà di scrivere in un file di testo e creare un oggetto di tipo timer, dove tramite l’evento Elaps ad intevalli di tempo, eseguire determinanti frammenti di codice.
Prima di scrivere il codice per l’evento onstart, occorre creare il gestore dell’evento Elapsed, che riguarda l’evento dell’oggetto Timer.
Qui di seguito si riporta il frammento di codice per entrambi i linguaggi.
VB.Net
Sub tempoEsecuzione_Elapsed(sender As Object, e As System.Timers.ElapsedEventArgs)
My.Computer.FileSystem.WriteAllText("D:\Progetti\Servizio\log.txt", "evento Elapsed", True)
End Sub
C#
void tempoEsecuzione_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
File.AppendAllText("D:\\Progetti\\Servizio\\log.txt", "\n" + "evento Elapsed");
}
Qui di seguito si riporta il frammento di codice per entrambi i linguaggi riguarda l’evento Start
VB.Net
Protected Overrides Sub OnStart(ByVal args() As String)
Dim tempoEsecuzione As New System.Timers.Timer
Try
System.Threading.Thread.Sleep(7000)
My.Computer.FileSystem.WriteAllText("D:\Progetti\Servizio\log.txt", vbCrLf & "Evento OnStart", True)
Dim intervallo As String = ConfigurationManager.AppSettings("INTERVALLOATTIVITA").ToString()
My.Computer.FileSystem.WriteAllText("D:\Progetti\Servizio\log.txt", "Intervallo: " & intervallo, True)
tempoEsecuzione.Enabled = True
tempoEsecuzione.Interval = Convert.ToInt32(intervallo)
AddHandler tempoEsecuzione.Elapsed, AddressOf tempoEsecuzione_Elapsed
tempoEsecuzione.Start()
'Codice
Catch ex As Exception
My.Computer.FileSystem.WriteAllText(Environment.CurrentDirectory + "\\Errore.txt", "\n" & "Si è verificato il seguente errore: " & ex.Message, True)
End Try
End Sub
C#
protected override void OnStart(string[] args)
{
System.Timers.Timer tempoEsecuzione = new System.Timers.Timer();
File.AppendAllText("D:\\Progetti\\Servizio\\log.txt", "\n" + "Evento OnStart");
try
{
System.Threading.Thread.Sleep(7000);
string intervallo = ConfigurationManager.AppSettings["INTERVALLOATTIVITA"].ToString();
File.AppendAllText("D:\\Progetti\\Servizio\\log.txt", "Intervallo: " + intervallo);
tempoEsecuzione.Enabled = true;
tempoEsecuzione.Interval = Convert.ToInt32(intervallo);
tempoEsecuzione.Elapsed += tempoEsecuzione_Elapsed;
tempoEsecuzione.Start();
//Codice
}
catch (Exception ex)
{
File.AppendAllText(Environment.CurrentDirectory + "\\Errore.txt", "\n" + "Si è verificato il seguente errore: " + ex.Message);
}
}
Qui di seguito il codice completo della classe Service
VB.Net
Imports System.Configuration
Public Class Service1
Protected Overrides Sub OnStart(ByVal args() As String)
Dim tempoEsecuzione As New System.Timers.Timer
Try
System.Threading.Thread.Sleep(7000)
My.Computer.FileSystem.WriteAllText("D:\Progetti\Servizio\log.txt", vbCrLf & "Evento OnStart", True)
Dim intervallo As String = ConfigurationManager.AppSettings("INTERVALLOATTIVITA").ToString()
My.Computer.FileSystem.WriteAllText("D:\Progetti\Servizio\log.txt", "Intervallo: " & intervallo, True)
tempoEsecuzione.Enabled = True
tempoEsecuzione.Interval = Convert.ToInt32(intervallo)
AddHandler tempoEsecuzione.Elapsed, AddressOf tempoEsecuzione_Elapsed
tempoEsecuzione.Start()
'Codice
Catch ex As Exception
My.Computer.FileSystem.WriteAllText(Environment.CurrentDirectory + "\\Errore.txt", vbCrLf & "Si è verificato il seguente errore: " & ex.Message, True)
End Try
End Sub
Sub tempoEsecuzione_Elapsed(sender As Object, e As System.Timers.ElapsedEventArgs)
My.Computer.FileSystem.WriteAllText("D:\Progetti\Servizio\log.txt", "evento Elapsed", True)
End Sub
Protected Overrides Sub OnStop()
End Sub
End Class
C#
using System.Configuration;
namespace Servizio
{
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
System.Timers.Timer tempoEsecuzione = new System.Timers.Timer();
File.AppendAllText("D:\\Progetti\\Servizio\\log.txt", "\n" + "Evento OnStart");
try
{
System.Threading.Thread.Sleep(7000);
string intervallo = ConfigurationManager.AppSettings["INTERVALLOATTIVITA"].ToString();
File.AppendAllText("D:\\Progetti\\Servizio\\log.txt", "Intervallo: " + intervallo);
tempoEsecuzione.Enabled = true;
tempoEsecuzione.Interval = Convert.ToInt32(intervallo);
tempoEsecuzione.Elapsed += tempoEsecuzione_Elapsed;
tempoEsecuzione.Start();
//Codice
}
catch (Exception ex)
{
File.AppendAllText(Environment.CurrentDirectory + "\\Errore.txt", "\n" + "Si è verificato il seguente errore: " + ex.Message);
}
}
void tempoEsecuzione_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
File.AppendAllText("D:\\Progetti\\Servizio\\log.txt", "\n" + "evento Elapsed");
}
protected override void OnStop()
{
}
}
}
Installazione
Per testare il servizio, non ci resta che avviarlo, come se fosse una semplice applicazione console, che eseguirà il codice, ma per installarlo nel nostro sistema, bisogna utilizzare i comandi del framework.
Aprire il prompt di Visual Studio, in modalità amministratore e scrivere il seguente “installutil PercorsoServizio\NomeServizio.exe” dove percorsoServizio sta ad indicare la cartella in cui si trova, mentre nomeservizio il file eseguibile comprensivo di estenzione, in questo modo permette di installare nel pc il servizio.
Ci verrà visualizzato un messaggio del tipo “ Nessun programma di installazione pubblico con l'attributo RunInstallerAttribute.Yes è stato trovato nell'assembly “
Il messaggio di errore è dovuto al fatto che non abbiamo installato il programma di installazione, per farlo, bisogna andare nella parte “Design” del servizio (quella grigia che abbiamo visto all’inizio) , se ci troviamo nel codice, fare click con il taso destro e selezionare dal menu “Visualizza la finestra di progettazione” a questo punto, tasto destro nella finestra di progettazione e selezionare la voce di menu “Aggiungi programma di installazione” Figura 2.
Figura 2 – La voce di menu
Verranno aggiunti due controlli (figura 3 ) che permettano l’installazione del servizio.
Figura 3 – I controlli aggiunti per effettuare l’installazione del servizio.
Selezioniamo il controllo denominato “ServiceProcessInstaller1” e nella finestra della proprietà “Account” selezioniamo il valore “LocalService” in questo modo verrà impostato il tipo di account per l’esecuzione del servizio.
Selezioniamo il controllo denominato “ServiceInstaller1” e nella finestra delle proprietà, impostiamo per la proprietà “Descriptiont” Un valore, di tipo “Servizio scritto in vb” a questo punto impostiamo la proprietà “DisplayName” che è il nome che verrà visualizzato.
Impostiamo il valore “Primo Servizio”, e compiliamo la soluzione, a questo punto eseguiamo il comando per l’installazione del servizio “installutil Percorso\NomeServizio.exe” mentre per d’installare bisogna aggiungere il parametro /U subito dopo il comando installutil “installutil /U Percorso\NomeServizio.exe”
Ora non ci resta che andare nella finestra dei servizi ed avviare il servizio, per vedere nel file di log, quello che sta scrivendo.
Conclusioni
In questo articolo si è visto come realizzare un semplice servizio per Windows, ed effettuare l’installazione tramite i comandi dal prompt.
Lo sviluppo dei servizi Windows non è semplice, in particolare nella fase di debug che richiede una certa complessità.
L’articolo ha voluto fornire al lettore le basi per questo iniziale approccio ad uno scenario poco utilizzato.