Selber im Service

Dienste programmieren mit .NET

Windows Dienste gibt es schon seit Windows NT 3.1 und diese Programme gibt es auch in Windows 2000 XP und 2003. Bei Diensten handelt es sich um eine praktische Einrichtung, denn die Programme können auch laufen ohne das eine Person am Rechner angemeldet ist: Der Rechner bietet dann eben einen Dienst an den andere Rechner nutzen können.

Dafür haben Dienste auch ihre Probleme – nicht zuletzt das Problem dass sie relativ kompliziert zu programmieren, zu debuggen und zu installieren sind. NET und das Visual Studio machen die Entwicklung von Diensten aber ganz erheblich leichter als das mit der Win32 API der Fall ist. Fallstricke gibt es aber immer noch in ausreichenden Mengen.

Bevor es an die Entwicklung des ersten eigenen Dienstes geht bedarf es jedoch einiger Hintergrundinformationen über Dienste. Ein Dienst ist ein Programm das zum Startzeitpunkt des Rechners automatisch gestartet werden kann und das so lange läuft wie der Rechner eingeschaltet ist. Dazu muss kein Anwender angemeldet sein - das Programm läuft in einem speziellen Windows-Kontext. Dabei werden entweder Anmeldedaten eines Benutzeraccounts verwendet oder das Programm läuft unter dem lokalen Systemaccount.

Das hat verschiedenen Konsequenzen, unter anderem dass ein Dienst nicht einfach gestartet und benutzt werden kann. Vielmehr unterliegt die Kontrolle der Dienste dem Service-Control Manager, einer der zentralen Windows Komponenten. Um ein Programm das einen Dienst implementiert zu starten, muss das Programm auf dem Rechner erst korrekt installiert werden. Korrekt bedeutet in diesem Zusammenhang dass das Programm dem Service Control Manager bekannt gemacht werden muss. Für Dienste die mit der .NET Klassenbibliothek entwickelt wurden gibt es dazu das spezielle InstallUtil.exe Werkzeug. Mit diesem Programm kann man einen Dienst auf dem eigenen Rechner installieren.

Dienste und deren Modi

Ist das geschehen, muss der Dienst auch noch in den Betriebsmodus versetzt werden. Dienste können sich in verschiedenen Modi befinden: Sie können angehalten, gestoppt und gestartet werden. Es gibt auch noch ein paar Zwischenmodi, die vorerst aber nicht von Bedeutung sind. Ferner muss man für einen Dienst festlegen, wie und ob er gestartet werden kann, denn nur weil der Service-Control Manager einen Dienst kennt bedeutet das noch nicht, dass der Dienst auf einem Rechner verwendet werden darf oder kann.

Der Startmodus, der Status eines Dienstes und die zu verwendenden Account-Daten für den Dienst werden beim installieren des Dienstes festgelegt. Nachträglich werden diese Einstellungen im Applet Dienste in der Systemsteuerung eingestellt.


Dienste konfiguriert man mit dem passenden Applet aus der Systemsteuerung bzw. der Computerverwaltung.



Wird ein Rechner nie oder nur sehr selten neu gestartet bedeutet das, dass ein laufender Dienst sehr lange betrieben wird: Das bedeutet auch dass ein Dienst gegen kleinere Programmfehler potentiell anfälliger ist als ein normales Anwendungsprogramm. Liegt in einem Dienst beispielsweise ein Speicherleck vor, kann durch ein kleines Leck im Laufe der Zeit eine ganze Menge Speicher verloren gehen. Nachdem der Dienst nicht wie ein Anwendungsprogramm hin und wieder beendet wird, wird der Speicher auch nie wieder freigegeben: Irgendwann wird der Dienst deswegen versagen. Natürlich kann ein Dienst auch aus anderen Gründen versagen . zum Beispiel durch einen ganz normalen Programmfehler der sich erst nach einiger Zeit oder durch das eintreten besonderer Umstände bemerkbar macht. Bei Diensten passiert dann das gleiche wie bei normalen Programmen: Sie stürzen ab.

Nun ist der Sinn eines Dienstes aber der dass der Dienst verfügbar ist, und zwar immer. Darum sieht der Service Control Manager eine Möglichkeit vor einen abgestürzten Dienst neu zu starten oder eine sonstige Aktion durchzuführen. An sonstigen Aktionen stehen zwei zur Verfügung: Neben dem Neustart des Dienstes kann man ein beliebiges Programm starten oder den Computer neu booten lassen. So ist es zum Beispiel möglich einen Administrator per eMail auf einen abgestürzten Dienst hinzuweisen.

Ein Windows-Dienst der auf der .NET Service Klasse basiert hat mindestens zwei Methoden: OnStart() und OnStop(). OnStart() wird aufgerufen wenn der Dienst gestartet wird . im Falle eines Autostart-Dienstes also wenn der Rechner gestartet wird.

Der Service Control Manager kümmert sich darum dass die OnStart() Methode des Dienstes aufgerufen wird wenn der Dienst gestartet werden soll und dass die OnStop() Methode aufgerufen wird wenn der Dienst beendet werden muss: Wie aber stellt man dann den eigentlichen Dienst zur Verfügung? Im OnStart() kann man das nicht tun, denn dann würde die Methode nicht terminieren und der Service-Control Manager würde das als ein Fehlschlagen des Dienste-Starts interpretieren. In OnStop() hingegen ist es zu spät noch irgendwelche Aktionen durchzuführen, da es wenig Sinn macht, die Dienste erst anzubieten wenn der Rechner gerade dabei ist heruntergefahren zu werden.

Anderer Code wird aber nicht aufgerufen . ein Dienst hat keine main() Funktion oder einen ähnlichen Eintrittspunkt. Alles was es gibt ist OnStart(). Man braucht also nun einen Weg um in dieser Methode Code auszuführen der dann dauerhaft läuft bis er in der OnStop() Methode angehalten wird. Die Lösung: Man braucht einen zusätzlichen Thread der in OnStart() begonnen und in OnStop() beendet wird.