Wednesday 15 July 2009

Breve guida alla creazione di servizi windows con Visual Studio

Questo post è una rielaborazione di una guida che ho preparato per dei colleghi: si tratta di indicazioni sulla creazione di servizi Windows usando Visual Studio e il framework .NET (2.0 e superiori). Niente di speciale rispetto a quanto già disponibile in rete, solo che è in italiano e risponde perlomeno pienamente alle ...mie esigenze.

Creazione di uno scheletro di servizio

Lanciare VS2005/2008 e creare una nuova soluzione C# o VBNET
di tipo “Windows service”

- viene creato uno scheletro di classe che eredita da ServiceBase

- il metodo OnStop viene chiamato allo stop del servizi

- il metodo OnStart all’avvio

- per cambiare nome al servizio modificare i vari riferimenti al namespace e ai nomi delle classi

- attenzione anche al codice nomeservizio.designer.cs per il nome passato poi all’eventuale event logger; il nome del servizio è definito in più punti.

Così com’è il servizio non è installabile. Andare in design mode sulla classe derivata da ServiceBase e fare tasto destro e sceglire “add installer”.

Viene aggiunta al progetto un’altra classe che deriva dall’oggetto Installer ed ha una direttiva di compilazione specifica, con due componenti serviceprocessinstaller e serviceinstaller. Modificarne le proprietà per cambiare nome, nome esteso, e account di default per l’installazione alservizio (ricordo che i servizi di windows hanno un nome sintetico usato ad esempio dai comand NET START o sc da prompt e un nome esteso visibile ad esempio in pannello di controllo servizi; l’account è l’utente con i permessi del quale è eseguito il servizio)

A questo punto si può installare il servizio in windows con
l’utility installutil.exe inserita nel dotnet framework (se non è nel path andare in c:\windows\Microsoft.net\Framework\ per trovarla.

Installutil.exe
nomeseguibile.exe
per installare

Installutil.exe
/u nomesegubile.exe
per disinstallare


E’ anche possibile aggiungere un progetto di installazione alla soluzione (solution = gruppo di progetti in VS.NET) ma è più laborioso, installutil inoltre è più adatto all’attività di sviluppo.

Debugging

Per quanto riguarda il debug: non si può debuggare direttamente un servizio come un normale programma. E’ necessario compilare, INSTALLARE, poi scegliere l’opzione ‘Attach process’ dal debugger di Visual Studio per agganciarsi al processo del servizio in esecuzione. Si tratta di settare uno o più breakpoint: una volta che il codice del servizio installato arriva, pur senza essere stato lanciato dal debugger, al punto del breakpoint, inizia l’esecuzione controllata. Dopo ogni modifica al sorgente bisogna disinstallare, reinstallare, far ripartire il servizio e rifare l’attach del processo. Per modifiche non sostanziali sembra possibile evitare di disinstallare e
reinstallare il servizio con InstallUtil. E’ comunque consigliabile testare prima il grosso del codice in un’applicazione convenzionale separata.

Comandi utili per controllare i servizi da prompt:

NET STOP nomesintetico

NET START nomesintetico

Sc stop nomesintetico

Sc start nomesintetico

Sc query nomesintetico

Sc query

L’ultimo comando lista tutti i servizi in esecuzione, il penultimo da informazioni solo sul servizio specificato.Il comando sc.exe è più recente del comando NET e consente di visualizzare più informazioni sul servizio, oltre a disporre di molte altre opzioni.

Note sulla programmazione dei servizi (in dotnet)

Non usare time di tipo System.Windows.Forms.Timer, ma timer di tipo System.Timer (sulla copia di Visual Studio che uso io questo tipo di timer non è presente di default sulla palette Components, però si può aggiungere facendo tasto destro Add.. sul titolo della palette stessa). I primi compilano senza problemi, ma non fanno mai scattare l’evento. Esistono anche timer di tipo System.Threading.Timer che non si possono aggiungere a design time e presentano altre problematiche.

All’avvio e all’arresto di un servizio viene generato automaticamente un evento in Visualizzatore Eventi/Applicazioni con il nome sintetico con cui è stato creato il servizio stesso. Anche eventuali eccezioni a runtime vengono loggate nella medesima destinazione. Per scrivere nel log
usare i normali componenti System.Diagnostics.EventLog settando la proprietà Log ad ‘Application’ e la proprietà Source al nome del servizio.

Per fermare il servizio dall’interno (p.es. per un errore trappato) usare this.Stop() dalla classe principale (equivale a chiamare ServiceBase.Stop() ). Verrà ovviamente eseguito il codice dell’evento OnStop

Interoperabilità col mondo COM/VB6

E’ possibile tranquillamente usare ADO (basta un riferimento a Microsoft ADO 2.x ) da un servizio dotnet. Viene creata in questo modo una dll chiamata Interop.ado.dll che deve sempre accompagnare l’eseguibile del servizio stesso.

E’ possibile usare dll visual basic da servizi dotnet sia in early che in late binding, non dovrebbero però interagire col destkop, così come del resto il servizio stesso.

I servizi in dotnet possono tranquillamente essere multithreaded – nella classe generata da VS esiste già del codice relativo da commentare, questo però è da evitare se si chiamano dll VB6/ActiveX (per il tipo di modello di threading usato da queste ultime le variabili globali – le c.d. variabili di modulo) rimangono in comune tra tutte le instanziazioni della dll stesa.

I servizi dotnet supportano la registration free COM, ovvero i file .manifest per gestire dll activex localmente, senza registrazione.


No comments:

Post a Comment