ASPNL logo (1 kb)
zaterdag 17 mei 2008




Microsoft MVP

.NET Codewise Community
<< vorige | overzicht | volgende >>

WindowsService – Betrouwbaar schedulen

Door Rutger Smit
11 februari 2004

Elke webdeveloper loopt er vroeg of laat wel eens tegen het volgende probleem aan: je wilt dat elke dag/week/maand/interval een bepaald stuk code uitgevoerd wordt. Dikwijls is dit nodig om gegevens te im- of exporteren of om andere batch opdrachten uit te voeren. In deze tutorial gaan we stap voor stap de oplossing voor dit veel voorkomende probleem maken.

Een Windows Service?

Een beetje ‘systeem spitter’ kent het wel: het overzichtsscherm met een lijst van alle services die op de achtergrond op de pc draaien. Een (windows) service is in principe een programma zonder GUI (Graphical User Interface / Voorkant) die hard nodig zijn om het hele systeem te laten draaien. Een goed voorbeeld van zo’n service is een webserver. De webserver is als service geschreven omdat dit programma het ook moet doen als er nog niemand op de computer ingelogd is.
Het voordeel van een service om taken te schedulen is dat het dezelfde opdrachten uit kan voeren als een WebForm (aspx pagina) en soms zelfs meer en/of beter.

Aan de slag!

Was het in C++ nog een behoorlijke klus om een soepel draaiende service te bouwen, in VisualStudio.NET en C# bouw je zonder al te veel moeite een eigen service. Als we Visual Studio.NET (VS.NET) geopend hebben kiezen we voor New Project en noemen het nieuwe project SchedulePlus. VS.NET maakt nu een aantal bestanden aan die we nodig hebben als basis van de service.

Het eerste wat we nu doen is het aanpassen van ServiceName, dit doe je in het Properties dialog. Daarna klikken we op de link die daar onder staat: Add Installer. Deze hebben we nodig om de service op een machine te kunnen registreren.

Er komen nu twee items bij: serviceProcessInstaller1 en serviceInstaller1. Van de eerste passen we het account aan waaronder de service uiteindelijk moet gaan draaien. In deze tutorial ga ik er van uit dat deze op een Windows 2000 Server gaat draaien, daarom kiezen we voor het account LocalSystem. Van serviceInstaller1 is het belangrijk dat we StartupType aanpassen. Deze zetten we op Automatic omdat we natuurlijk wel willen dat de service wordt gestart tijdens het opstarten van de server.

Als we nu naar de CodeView van Service1.cs gaan dan zien we daar al een hele lap code staan. Stoor je er niet aan en laat het lekker staan. Alleen in private void InitializeComponent() zetten we wat extra zaken. We voegen toe:

timer = new Timer(604800000); // = 1 week
timer.Elapsed += new ElapsedEventHandler( this.ServiceTimer_Tick );

Om gebruik te kunnen maken van deze timer moeten we bovenaan de System.Timers namespace importeren en buiten InitializeComponent wel even de volgende regel toevoegen:

private Timer timer=null;

De time dient uiteraard wel gestart te worden op het moment dat de service opgestart wordt. Dit gebeurt in de protected override void OnStart(string[] args) VS.NET heeft die al voor je aangemaakt. Zet het start command hier in:

this.timer.Start();

De eerste regel is een nieuwe ServiceController en de tweede en derde regel maakt een nieuwe time aan. In deze tutorial ga ik er van uit dat we één keer per week een bepaalde method aan willen roepen die het een en ander voor ons doet. Het getal 604800000 staat voor precies 1 week. De parameter van het Timer object wordt uitgedrukt in milliseconden. Op de laatste regel wordt een event aan het time object toegevoegd. Het Elapsed event wordt uitgevoerd op het moment dat de timer volledig afgeteld heeft (als hij dus op 0 staat). De method die dan uitgevoerd wordt heet ServiceTime_Tick en die ziet er alsvolgt uit:

private void ServiceTimer_Tick(object sender, System.Timers.ElapsedEventArgs e)
{
   WriteLog("Starting tasks");
   RunTasks();
}

Wat er in deze method gebeurt is heel simpel. Elke keer als de timer op 0 komt te staan dan voert hij de method RunTasks uit. In deze method kunnen we allerlei opdrachten uitvoeren die we normaliter in een asp(x) pagina uit zouden laten voeren.

De method WriteLog heb ik er aan toegevoegd om te loggen wat mijn service zoals doet. Het vraagt één argument en dat is een string, een bericht dat je wilt loggen. De WriteLog method ziet er als volgt uit:

public void WriteLog(string logtxt)
{
   StreamWriter logger = File.AppendText("C:\\servicelog.txt");
   logger.WriteLine("{0} {1}\t{2}",DateTime.Now.ToLongTimeString(),DateTime.Now.ToShortDateString(),logtxt);
   logger.Close();
}

Als we dit project nu gaan compilen en het niet met errors komt dan heben we in de, afhankelijk van je instellingen, in de dir Debug een SchedulePlus.exe staan. Aan te raden is om tijdens het ontwikkelen onder de Debug configuratie te compilen en indien alles goed werkt VS.NET op Release te zetten. De SchedulePlus.exe zal dan uiteraard in de dir Release staan.

Het programma installeren

Het installeren van de executable doen we vanaf de VS.NET command prompt (start > Programs > Microsoft Visual Studio .NET > Visual Studio .NET Tools > Visual Studio .NET Command Prompt)

Typ op de commandline de volgende opdracht: installutil D:\Pad\Naar\Project\bin\Debug\SchedulePlus.exe

Om een geïnstalleerde service te uninstallen gebruik je switch /u (wel eerst service stoppen) D:\Pad\Naar\Project\bin\Debug\SchedulePlus.exe /u

Er komt nu een boel info langs en binnen een seconde is de service op de computer geïnstalleerd. Open nu je Services window en zie daar:

Omdat we de service zojuist geïnstalleerd hebben moeten we hem de eerste keer nog even een zetje geven, maar de volgende keer als de pc opstart dan zal de SchedulePlus service automatisch opstarten. Op het moment dat je de service opnieuw wilt compilen dien je wel eerst de service te stoppen. Dit is nodig omdat zolang de service gestart (op gepauzeerd) is, de SchedulePlus.exe in gebruik is en dus niet overschreven kan worden door de compiler.

NB: de code die je in RunTasks() kunt zetten behandel ik niet in deze tutorial maar in principe kun je hier al je acties kwijt die je wilt uitvoeren. Dit kan varieren van het runnen van een stored procedure tot het opvragen van een url dmv een HttpWebRequest.

<< vorige | ^ naar boven | overzicht | volgende >>
copyright 2000-2007 ASPNL