690 likes | 968 Views
Immer zu Diensten. E4 Einen Dienst mit .NET programmieren. Wer bin ich...?. Dipl. Inf. Marcel Gnoth Entwickler, Trainer, MCSD, Autor Geschäftsanwendungen, COM, Datenbanken, Verteilte Informationssysteme www.gnoth.net aktuelle Folien und Beispiele auf der Webseite NTeam GmbH, Berlin
E N D
Immer zu Diensten E4 Einen Dienst mit .NET programmieren Marcel Gnoth – www.gnoth.net
Wer bin ich...? • Dipl. Inf. Marcel Gnoth • Entwickler, Trainer, MCSD, Autor • Geschäftsanwendungen, COM, Datenbanken, Verteilte Informationssysteme • www.gnoth.net • aktuelle Folien und Beispiele auf der Webseite • NTeam GmbH, Berlin • www.nteam.de (MS Server Familie, BI, Entwicklung) • Microsoft Gold Certified Partner Marcel Gnoth – www.gnoth.net
Inhalt I • Die Herausforderung • Viele Wege führen nach Rom • Ein Dienst mit .Net • Debugging eines Dienstes • Das Beispielprojekt • Das Eventlog • Performance Counter • Schlußbemerkungen Marcel Gnoth – www.gnoth.net
Die Herausforderung oder das Problem.............. Marcel Gnoth – www.gnoth.net
Aufgaben für den Hintergrund • ohne Anwenderinteraktion • kein Nutzer angemeldet • vom Anwender unbemerkt • starten automatisch nach dem Booten • Beispiele • Replikation von Daten • Verarbeiten eintreffender Daten • ein Web- oder Datenbankserver Marcel Gnoth – www.gnoth.net
Lösungsansätze • Eine normale Applikation (Exe) starten • aber nicht durch den Anwender, automatisch • diverse Hilfsmittel • durch SQL Server • kann COM Komponenten (CreateObject) instanziieren • kann einen Prozeß starten • andere Hilfsmittel • IIS, ........................... Marcel Gnoth – www.gnoth.net
Was ist ein Dienst? • spezielle Windows Applikation • wird von einem Dienst-Kontroll-Manager gesteuert • Service Control Manager (SCM) • Services.msc • VS.Net • Muß unter Windows registriert werden Marcel Gnoth – www.gnoth.net
Starten eines Dienstes • Manuell • Automatisch • Abhängigkeiten von anderen Diensten • mit einem bestimmtenWindows Konto anmelden Marcel Gnoth – www.gnoth.net
SCM • Services.msc • Konfiguration • Start, Stopp, Pause, Continue Marcel Gnoth – www.gnoth.net
Demo Windows Dienste Marcel Gnoth – www.gnoth.net
Demo Ablauf • Services.msc starten • Eigenschaften des WWW-Publishingdienstes anzeigen • Starten und Stoppen Marcel Gnoth – www.gnoth.net
Wege zum Ziel • Visual C++ (MFC/ATL) • alle Möglichkeiten der Dienstprogrammierung unter Windows • hohe Einarbeitungszeit • Klassisches VB bietet von Hause aus keine Unterstützung Marcel Gnoth – www.gnoth.net
Die Trickkiste • SRVANY.EXE • Windows NT Resource Kit • kommuniziert mit dem SCM • Startet beliebige Standard Applikation als Dienst • Shutdown -> Terminate Process API Call • einfache Notlösung Marcel Gnoth – www.gnoth.net
Die Trickkiste II • NTSVC.OCX • not supported • übernimmt die Kommunikation mit SCM • Applikation wird ein echter Dienst • mit C++ Source Code • Knowledge Base Artikel Q170883 • wenn nicht .Net -> produktivste Wahl Marcel Gnoth – www.gnoth.net
Trickkiste III • VB Applikation • Knowledge Base Artikel Q175948 • nicht zuverlässig • VB-Klassik nicht nur eingeschränkt Thread sicher • Spy Works von DesaWare • professionelles Tool für VB • kostet extra Geld Marcel Gnoth – www.gnoth.net
Wie man einen Dienst programmiert • Debuggen eines Dienstes nicht ganz einfach (siehe unten) • Funktionalität in eine extra Komponente (Dll) • Testen mit normaler Standardanwendung • Dann „Einbau“ in Dienstanwendung Marcel Gnoth – www.gnoth.net
Applikationsdesign • Dienstprojekt (.Net) oder Standardprojekt mit NTSVC.OCX (VB-Klassik) übernimmt nur Dienststeuerung • Start, Stop, .... • ruft Methoden der Komponente auf (DoWork, StopWork...) Marcel Gnoth – www.gnoth.net
Ein Dienst mit .Net Marcel Gnoth – www.gnoth.net
Windows Service Project Template • Neues Projekt in VS.Net, Typ Windows Service • Gerüst bereits fertig • Mehrere Dienste pro Projekt (Exe) möglich • Main Prozedur ist Einsprungspunkt • wird vom SCM aufgerufen <MTAThread()> Shared Sub Main() Dim ServicesToRun() As ServiceProcess.ServiceBase ServicesToRun = New _ ServiceProcess.ServiceBase() {New svcMittwoch()} ServiceProcess.ServiceBase.Run(ServicesToRun) End Sub Marcel Gnoth – www.gnoth.net
Installation eines Dienstes • Dienste müssen im System registriert werdenHKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\BigBrotherSvc • AddInstaller • Designer der Dienstkomponente (Klasse) und F4 • im PropertyWindow -> AddInstaller Marcel Gnoth – www.gnoth.net
Installationskomponente • Neue Komponente ProjectInstaller.vb • enthält zwei weitere Komponenten <RunInstaller(True)> _ Public Class ProjectInstaller Inherits Configuration.Install.Installer Dienstprojekt Dienst Installation BigBrotherSvc ProjectInstaller BusyClerk ServiceProcessInstaller ServiceInstaller Marcel Gnoth – www.gnoth.net
Komponente ProjectInstaller • Komponente ServiceProcessInstaller • für alle Dienste in der Anwendung • Windows Konto für den Dienst • Komponente ServiceInstaller • für jeden Dienst eine eigene • Abhängigkeiten von anderen Diensten • Startart (manuell / automatisch) • Eigenschaften des Service werden kopiert • ändern sich Eigenschaften des Service muß Installer von Hand aktualisiert werden Marcel Gnoth – www.gnoth.net
Installation im System • InstallUtil • sucht im Assembly nach Klassen mit Attribut RunInstaller=True • Log Informationen im Assembly Verzeichnis InstallUtil.exe SimpleService.exe Marcel Gnoth – www.gnoth.net
DEMO Live – Coding Marcel Gnoth – www.gnoth.net
DEMO – Ablauf • Neues Service Projekt • Properties einstellen • Klasse untersuchen • Main • Start Stop • Installer hinzufügen • konfigurieren, Account, Dienstabhängigkeit, Startart • InstallUtil • mit SCM starten und stoppen • Eventviewer zeigen das startet und stoppt Marcel Gnoth – www.gnoth.net
Beschreibung eines Dienstes • Wo verdammt nochmal kann man die Beschreibung eines Dienstes hinterlegen ...? • Funktioniert nicht • Adding a description to a .NET Windows Service, von Andy Hopper • http://www.codeproject.com/dotnet/dotNETSCMDescription.asp <ServiceProcessDescription("Eine Beschreibung")> _ Public Class SonntagService Inherits System.ServiceProcess.ServiceBase End Class Marcel Gnoth – www.gnoth.net
Debbuging eines Dienstes Marcel Gnoth – www.gnoth.net
Debugging • nicht so einfach, da Dienst vom SCM kontrolliert wird • Kompilieren und Dienst über SCM starten (Prozeß wird gestartet) • Debugger zuordnen (attach) • aktuelle Arbeit des Dienstes wird unterbrochen • OnStart und Sub Main können nicht debuggt werden, da vom SCM beim Starten des Prozesses aufgerufen, bevor Debugger zugeordnet wird Marcel Gnoth – www.gnoth.net
Debugger dem Prozeß hinzufügen • Menu Debug -> Processes Marcel Gnoth – www.gnoth.net
Debugger dem Prozeß hinzufügen • Attach... • BreakPointssetzen Marcel Gnoth – www.gnoth.net
OnStart Debuggen – Trick 17 • einen zweiten Dummy-Service dem Projekt hinzufügen • Über SCM den DummyDienst starten • dann Debugger attachen • BreakPoint in Startmethode des eigentlichen Dienstes • und über SCM starten! • Main kann so nicht debuggt werden Marcel Gnoth – www.gnoth.net
DEMO Debuggen eines Dienstes Marcel Gnoth – www.gnoth.net
Demo Ablauf • Debuggen des einfachen Dienstes • Hinzufügen des Dummydienstes • Debuggen der Start – Methode Marcel Gnoth – www.gnoth.net
Das Beispielprojekt Ein kleiner Beispieldienst Marcel Gnoth – www.gnoth.net
Die BigBrother Solution • BigBrotherSvc – Dateien • BigBrotherSvc : start stop, etc. • BusyClerk: Arbeiterklasse • ProjectInstaller: Installieren imSystem • ServiceController – Datei • frmController für Dienststeuerung Marcel Gnoth – www.gnoth.net
Das Testprojekt: ServiceController • Standard Applikation • Listet alle Dienste auf • Startet und stoppt Dienste • Versendet Commandos • Versendet MSMQ – Messages Marcel Gnoth – www.gnoth.net
Das Testprojekt • Timer – Steuerelement • Interval wird über UpDown Steuerelement eingestellt • Im Timer – Ereignis wird der Status des ausgewählten Dienstes abgefragt • Automatisches generieren von MSMQ Nachrichten durch Timer – Steuerelement • Checkbox • Timer – Ereignis Marcel Gnoth – www.gnoth.net
Komponente ServiceController • Referenz auf System.ServiceProcess Namespace • Steuerung eines Dienstes • Status abfragen (Running, Paused, Stopped, ...Pending) • Starten, Stoppen, ... eines Dienstes • Liste aller Dienste Dim xServices(), xSrv As ServiceProcess.ServiceController Dim i As Integer xServices = xSrv.GetServices() Me.lstServices.Items.Clear() For i = 0 To xServices.Length - 1 Me.lstServices.Items.Add(xServices(i).ServiceName) Next Marcel Gnoth – www.gnoth.net
CustomCommand • Senden einer Zahl an den Dienst • 0 – 127 vom System reserviert • 128 – 255 können vom Dienst entsprechend der Anwendungslogik interpretiert werden • Im Beispiel: 128 ^= PerformanceCounter zurücksetzen Dim xSrv As ServiceProcess.ServiceController xSrv = CType(xServices(lstServices.SelectedIndex), _ ServiceProcess.ServiceController) Try xSrv.ExecuteCommand(128) Catch exc As Exception MsgBox("Fehler in ExecuteCommand! " & exc.Message) End Try Marcel Gnoth – www.gnoth.net
Der Dienst: Klasse BusyClerk • Anwendungslogik des Dienstes • kann auch ohne Dienstanwendung getestet werden • Überwacht ein Verzeichnis und protokolliert neue Dateien (IO.FileSystemWatcher) • Überwacht eine MessageQueue und verarbeitet neu eingetroffene Nachrichten (Messaging.MessageQueue) • bildet Start, Stop,... in der Anwendungslogik ab • gehört eigentlich in eigene Dll ... zum Testen Marcel Gnoth – www.gnoth.net
Message Queueing • Transport von Nachrichten zwischen Computern Marcel Gnoth – www.gnoth.net
Message Queueing – Konzepte • Asynchrone Abarbeitung von Aufgaben • Empfänger oder Sender kann Offline sein • Nachrichten werden zwischengepuffert • vergleichbar mit e-mail für Computerprogramme • Aktiver Austausch von Informationen • zwischen Programmen / Computern • Pushen von Informationen Marcel Gnoth – www.gnoth.net
Klasse BusyClerk Public Class BusyClerk Private WithEvents m_FSW As System.IO.FileSystemWatcher Private WithEvents m_MQIn As Messaging.MessageQueue Public Event ErrorDuringProcess(...) Public Event FileArrived(...) Public Event MQArrived(ByVal Label As String) Private Sub theFSW_Created(...) Handles m_FSW.Created RaiseEvent FileArrived(e.FullPath, f.Length.ToString) End Sub Sub mqIn_ReceiveCompleted(...)Handles m_MQIn.ReceiveCompleted RaiseEvent MQArrived(e.Message.Label) m_AsyncOP = m_MQIn.BeginReceive End Sub End Class Marcel Gnoth – www.gnoth.net
Klasse BusyClerk.ClerkStart • Arbeit starten, Queue lauschen, Dir überwachen • ClerkStop: Ressourcen freigeben, Arbeit beenden • ClerkPause, ClerkContinue • Arbeit unterbrechen, Ressourcen halten (je nach Aufgabe) Public Sub ClerkStart() m_InboxDir = New DirectoryInfo(m_InboxPath) m_FSW = New System.IO.FileSystemWatcher() m_FSW.NotifyFilter = System.IO.NotifyFilters.FileName m_FSW.Path = m_InboxDir.FullName m_FSW.EnableRaisingEvents = True m_MQIn = New MessageQueue(m_QueuePath) m_AsyncOP = m_MQIn.BeginReceive() End Sub Marcel Gnoth – www.gnoth.net
Klasse BigBrotherSvc • Klasse mit Komponentendesigner • erbt von ServiceBase • Sub Main für SCM • überschreibt Methoden • OnStart, OnStop, OnPause, OnContinue • OnCommand, Ereignisse der Klasse BusyClerk • PerformanceCounter und EventLog • ..... der ganze Service Kram Marcel Gnoth – www.gnoth.net
BigBrotherSvc – Komponenten • Eine BusyClerk – Instanz, jemand muß ja die Arbeit machen • Ein Eventlog • Protokollieren der Ereignisse, folgt... • Zwei PerformanceCounter • Messen der Leistung des Dienstes, folgt... Private WithEvents m_BusyClerk As BusyClerk Private WithEvents m_LogBigBrother As EventLog Private pcMsgCount As PerformanceCounter Private pcMsgCountPerSecond As PerformanceCounter Marcel Gnoth – www.gnoth.net
BigBrotherSvc.Start • Erzeugen und Öffnen des Eventlogs • Erzeugen und aktivieren der PerformanceCounter • Starten der Arbeit • OnStart darf nur 30 Sekunden dauern, sonst bricht SCM den Start ab. • Wenn zu lange, dann Start in eigenen Thread verlagern Protected Overrides Sub OnStart(ByVal args() As String) Call CreateEventLog() Call CreatePerfCounter() m_BusyClerk = New BusyClerk(FILE_PATH, MSMQ_PATH) m_BusyClerk.ClerkStart() m_LogBigBrother.WriteEntry("Dienst gestartet...") End Sub Marcel Gnoth – www.gnoth.net
BigBrotherSvc – Stop, Pause, ... • weiterreichen der Aufrufe des SCM an die Arbeitskomponente Protected Overrides Sub OnStop() m_BusyClerk.ClerkStop() End Sub Protected Overrides Sub OnPause() m_BusyClerk.ClerkPause() End Sub Protected Overrides Sub OnContinue() m_BusyClerk.ClerkContinue() End Sub Protected Overrides Sub OnShutdown() m_BusyClerk.ClerkStop() End Sub Marcel Gnoth – www.gnoth.net
Das Windows Eventlog Marcel Gnoth – www.gnoth.net
Log – Dateien • Programme ohne Anwenderinteraktion protokollieren Meldungen in Log – Dateien • Anwendung, System, Security • AutoLog – Property des Dienstes schreibt nach Anwendung • Eigene Log – Dateien • EventVwr.msc: Anwendung zum Betrachten der LogDateien • VS.Net – Server Explorer Marcel Gnoth – www.gnoth.net