Gibt es eine einfachere Möglichkeit, den Code zu durchlaufen, als den Dienst über den Windows Service Control Manager zu starten und dann den Debugger an den Thread anzuhängen? Es ist etwas umständlich und ich frage mich, ob es einen einfacheren Ansatz gibt.
c#
debugging
windows-services
Matthias
quelle
quelle
Antworten:
Wenn ich den Dienst schnell debuggen möchte, schaue ich einfach dort rein
Debugger.Break()
. Wenn diese Linie erreicht ist, werde ich wieder zu VS zurückkehren. Vergessen Sie nicht, diese Zeile zu entfernen, wenn Sie fertig sind.UPDATE: Alternativ zu
#if DEBUG
Pragmas können Sie auchConditional("DEBUG_SERVICE")
Attribute verwenden.OnStart
Rufen Sie auf Ihrem einfach diese Methode auf:Dort wird der Code nur während Debug-Builds aktiviert. Wenn Sie gerade dabei sind, kann es hilfreich sein, eine separate Build-Konfiguration für das Service-Debugging zu erstellen.
quelle
Ich denke auch, dass eine separate "Version" für die normale Ausführung und als Service der richtige Weg ist, aber ist es wirklich erforderlich, einen separaten Befehlszeilenschalter für diesen Zweck zuzuweisen?
Könnten Sie nicht einfach tun:
Das hätte den "Vorteil", dass Sie Ihre App einfach per Doppelklick starten können (OK, wenn Sie das wirklich brauchen) und dass Sie einfach F5in Visual Studio klicken können (ohne die Projekteinstellungen ändern zu müssen, um diese
/console
Option einzuschließen).Technisch gesehen wird
Environment.UserInteractive
geprüft, ob dasWSF_VISIBLE
Flag für die aktuelle Fensterstation gesetzt ist. Gibt es jedoch einen anderen Grund, aus dem es zurückkehren würdefalse
, abgesehen davon, dass es als (nicht interaktiver) Dienst ausgeführt wird?quelle
System.Diagnostics.Debugger.IsAttached
stattdessen verwendenEnvironment.UserInteractive
.Als ich vor einigen Wochen ein neues Serviceprojekt eingerichtet habe, habe ich diesen Beitrag gefunden. Obwohl es viele großartige Vorschläge gibt, habe ich immer noch nicht die gewünschte Lösung gefunden: Die Möglichkeit, die Serviceklassen
OnStart
undOnStop
-methoden aufzurufen , ohne die Serviceklassen zu ändern.Die Lösung, die ich gefunden habe, verwendet den
Environment.Interactive
ausgewählten Laufmodus, wie in anderen Antworten auf diesen Beitrag vorgeschlagen.Der
RunInteractive
Helfer verwendet Reflection, um die geschütztenOnStart
undOnStop
Methoden aufzurufen :Dies ist der gesamte erforderliche Code, aber ich habe auch eine exemplarische Vorgehensweise mit Erklärungen geschrieben.
quelle
walk through
), ist sicherzustellen, dass Sie in die Projekteigenschaften gehen und den Ausgabetyp in ändern,Console Application
bevor Sie versuchen, zu kompilieren und auszuführen. Finden Sie es beiProject Properties -> Application -> Output type -> Console Application
. Damit dies für mich richtig funktioniert, musste ich die Anwendung mit demstart
Befehl ausführen . Bsp.:C:\"my app name.exe" -service
Würde bei mir nicht funktionieren. Stattdessen benutzte ichC:\start /wait "" "my app name.exe" -service
Manchmal ist es wichtig zu analysieren, was während des Starts des Dienstes vor sich geht. Das Anhängen an den Prozess hilft hier nicht weiter, da Sie nicht schnell genug sind, um den Debugger anzuhängen, während der Dienst gestartet wird.
Die kurze Antwort lautet: Ich verwende dazu die folgenden 4 Codezeilen :
Diese werden
OnStart
wie folgt in die Dienstmethode eingefügt :Für diejenigen, die es noch nicht getan haben, habe ich unten detaillierte Hinweise beigefügt , da Sie leicht stecken bleiben können. Die folgenden Hinweise beziehen sich auf Windows 7x64 und Visual Studio 2010 Team Edition , sollten jedoch auch für andere Umgebungen gültig sein.
Wichtig: Stellen Sie den Dienst im "manuellen" Modus
InstallUtil
bereit (verwenden Sie entweder das Dienstprogramm an der VS-Eingabeaufforderung oder führen Sie ein von Ihnen vorbereitetes Dienstinstallationsprojekt aus). Öffnen Sie Visual Studio, bevor Sie den Dienst starten, und laden Sie die Lösung mit dem Quellcode des Dienstes. Richten Sie zusätzliche Haltepunkte nach Bedarf in Visual Studio ein. Starten Sie den Dienst dann über die Dienststeuerung.Aufgrund des
Debugger.Launch
Codes wird das Dialogfeld "In Servicename.exe ist eine nicht behandelte Microsoft .NET Framework-Ausnahme aufgetreten ." erscheinen. Klicken Sie wie im Screenshot gezeigt: Yes, debug Servicename.exeInsbesondere in Windows 7 UAC werden Sie anschließend möglicherweise aufgefordert, Administratoranmeldeinformationen einzugeben. Geben Sie sie ein und fahren Sie fort mit Yes:
Danach wird das bekannte Just-In-Time-Debugger-Fenster von Visual Studio angezeigt. Sie werden gefragt, ob Sie mit dem ausgewählten Debugger debuggen möchten. Bevor Sie auf klicken Yes, wählen Sie aus , dass Sie keine neue Instanz öffnen möchten (2. Option). Eine neue Instanz wäre hier nicht hilfreich, da der Quellcode nicht angezeigt wird. Sie wählen stattdessen die zuvor geöffnete Visual Studio-Instanz aus:
Nachdem Sie geklickt haben Yes, zeigt Visual Studio nach einer Weile den gelben Pfeil rechts in der Zeile an, in der sich die
Debugger.Launch
Anweisung befindet, und Sie können Ihren Code debuggen (MethodeMyInitOnStart
, die Ihre Initialisierung enthält).Durch Drücken von wird F5die Ausführung sofort fortgesetzt, bis der nächste von Ihnen vorbereitete Haltepunkt erreicht ist.
Tipp: Um den Dienst am Laufen zu halten, wählen Sie Debug -> Alle trennen . Auf diese Weise können Sie einen Client ausführen, der mit dem Dienst kommuniziert, nachdem dieser ordnungsgemäß gestartet wurde und Sie das Debuggen des Startcodes abgeschlossen haben. Wenn Sie Shift+F5 drücken (Debugging beenden), wird der Dienst beendet. Stattdessen sollten Sie das Service Control Panel verwenden , um es zu stoppen.
Beachten Sie das
Wenn Sie ein Release erstellen , wird der Debug-Code automatisch entfernt und der Dienst wird normal ausgeführt.
Ich verwende
Debugger.Launch()
, der einen Debugger startet und anfügt . Ich habe auch getestetDebugger.Break()
, was nicht funktioniert hat , da beim Start des Dienstes noch kein Debugger angeschlossen ist (was den "Fehler 1067: Der Prozess wurde unerwartet beendet" verursacht ).RequestAdditionalTime
setzt eine längere Timeout für die Inbetriebnahme des Service (es ist nicht selbst zu verzögern den Code, sondern wird sofort mit der weiterhinDebugger.Launch
Anweisung). Andernfalls ist das Standardzeitlimit zum Starten des Dienstes zu kurz und das Starten des Dienstes schlägt fehl, wenn Sie nichtbase.Onstart(args)
schnell genug vom Debugger aus anrufen . Bei einer Zeitüberschreitung von 10 Minuten wird praktisch vermieden, dass die Meldung " Der Dienst hat nicht geantwortet ..." unmittelbar nach dem Start des Debuggers angezeigt wird.Sobald Sie sich daran gewöhnt haben, ist diese Methode sehr einfach, da Sie lediglich 4 Zeilen zu einem vorhandenen Service-Code hinzufügen müssen, damit Sie schnell die Kontrolle und das Debuggen erlangen können.
quelle
base.RequestAdditionalTime(600000)
Verhindert wie beschrieben, dass die Dienststeuerung den Dienst für 10 Minuten beendet, wenn sie nichtbase.OnStart(args)
innerhalb dieser Zeitspanne anruft. Abgesehen davon erinnere ich mich, dass die Benutzerkontensteuerung auch abgebrochen wird, wenn Sie die Administratoranmeldeinformationen nach einer Weile nicht mehr eingeben (ich weiß nicht, wie viele Sekunden genau, aber ich denke, Sie müssen sie innerhalb einer Minute eingeben, sonst bricht die Benutzerkontensteuerung ab). , wodurch die Debug-Sitzung beendet wird.Normalerweise kapsle ich die Logik des Dienstes in eine separate Klasse und starte diese von einer 'Runner'-Klasse. Diese Runner-Klasse kann der eigentliche Dienst oder nur eine Konsolenanwendung sein. Ihre Lösung hat also (mindestens) 3 Projekte:
quelle
Dieses YouTube-Video von Fabio Scopel erklärt, wie man einen Windows-Dienst ganz gut debuggt ... die eigentliche Methode beginnt im Video um 4:45 Uhr ...
Hier ist der Code, der im Video erklärt wird ... Fügen Sie in Ihrer Program.cs-Datei das Material für den Debug-Abschnitt hinzu ...
Fügen Sie in Ihrer Service1.cs-Datei die OnDebug () -Methode hinzu ...
Grundsätzlich müssen Sie ein erstellen
public void OnDebug()
, das das aufruft,OnStart(string[] args)
da es geschützt und außerhalb nicht zugänglich ist. Dasvoid Main()
Programm wird mit#if
Präprozessor mit hinzugefügt#DEBUG
.Visual Studio definiert,
DEBUG
ob das Projekt im Debug-Modus kompiliert wird. Dadurch kann der Debug-Abschnitt (unten) ausgeführt werden, wenn die Bedingung erfüllt istUnd es wird genau wie eine Konsolenanwendung ausgeführt. Sobald alles in Ordnung ist, können Sie den Modus ändern
Release
und der reguläreelse
Abschnitt löst die Logik ausquelle
AKTUALISIEREN
Dieser Ansatz ist bei weitem der einfachste:
http://www.codeproject.com/KB/dotnet/DebugWinServices.aspx
Ich lasse meine ursprüngliche Antwort unten für die Nachwelt.
Meine Dienste haben in der Regel eine Klasse, die einen Timer kapselt, da der Dienst in regelmäßigen Abständen prüfen soll, ob noch etwas zu tun ist.
Wir aktualisieren die Klasse neu und rufen StartEventLoop () während des Starts des Dienstes auf. (Diese Klasse kann auch problemlos von einer Konsolen-App aus verwendet werden.)
Der nette Nebeneffekt dieses Entwurfs ist, dass die Argumente, mit denen Sie den Timer einrichten, verwendet werden können, um eine Verzögerung zu haben, bevor der Dienst tatsächlich funktioniert, sodass Sie Zeit haben, einen Debugger manuell anzuhängen.
Außerdem habe ich Folgendes getan (bereits in früheren Antworten erwähnt, jedoch mit den Flags des bedingten Compilers [#if], um zu verhindern, dass es in einem Release-Build ausgelöst wird).
Ich habe damit aufgehört, weil wir manchmal vergessen haben, Release einzubauen und eine Debugger-Pause in einer App einzulegen, die auf einer Client-Demo ausgeführt wird (peinlich!).
quelle
// do something
die Fertigstellung länger als 30 Minuten dauert?quelle
OnStart
istprotected
und Sie können die Zugriffsebene nicht ändern :(Sie können den Dienst auch über die Eingabeaufforderung (sc.exe) starten.
Persönlich würde ich den Code in der Debugging-Phase als eigenständiges Programm ausführen, und wenn die meisten Fehler behoben sind, wechseln Sie zur Ausführung als Dienst.
quelle
Früher hatte ich einen Befehlszeilenschalter, der das Programm entweder als Dienst oder als reguläre Anwendung startete. Dann würde ich in meiner IDE den Schalter so einstellen, dass ich meinen Code durchgehen kann.
Bei einigen Sprachen können Sie tatsächlich erkennen, ob es in einer IDE ausgeführt wird, und diesen Wechsel automatisch durchführen.
Welche Sprache benutzt du?
quelle
Verwenden Sie die TopShelf- Bibliothek.
Erstellen Sie eine Konsolenanwendung und konfigurieren Sie das Setup in Ihrem Main
Um Ihren Dienst zu debuggen, drücken Sie einfach F5 im Visual Studio.
Geben Sie zum Installieren des Dienstes cmd "console.exe install" ein.
Anschließend können Sie den Dienst im Windows Service Manager starten und beenden.
quelle
Ich denke, es hängt davon ab, welches Betriebssystem Sie verwenden. Vista ist aufgrund der Trennung zwischen den Sitzungen viel schwieriger mit Diensten zu verbinden.
Die zwei Optionen, die ich in der Vergangenheit verwendet habe, sind:
Hoffe das hilft.
quelle
Ich möchte in der Lage sein, jeden Aspekt meines Dienstes zu debuggen, einschließlich aller Initialisierungen in OnStart (), während ich ihn dennoch mit vollem Dienstverhalten im Rahmen des SCM ausführe ... kein "Konsolen" - oder "App" -Modus.
Dazu erstelle ich im selben Projekt einen zweiten Dienst, der zum Debuggen verwendet wird. Wenn der Debug-Dienst wie gewohnt gestartet wird (dh im MMC-Plugin für Dienste), wird der Diensthostprozess erstellt. Auf diese Weise können Sie den Debugger anhängen, obwohl Sie Ihren eigentlichen Dienst noch nicht gestartet haben. Starten Sie nach dem Anhängen des Debuggers an den Prozess Ihren eigentlichen Dienst, und Sie können überall im Dienstlebenszyklus darauf zugreifen, einschließlich OnStart ().
Da nur ein sehr geringer Codeeinbruch erforderlich ist, kann der Debug-Service problemlos in Ihr Service-Setup-Projekt aufgenommen und aus Ihrer Produktionsversion entfernt werden, indem eine einzelne Codezeile auskommentiert und ein einzelnes Projektinstallationsprogramm gelöscht wird.
Einzelheiten:
1) Angenommen, Sie implementieren
MyService
, erstellen Sie auchMyServiceDebug
. Fügen Sie beide wie folgt zumServiceBase
Array hinzuProgram.cs
:2) Fügen Sie den realen Dienst UND den Debug-Dienst zum Projektinstallationsprogramm für das Dienstprojekt hinzu:
Beide Dienste (Real und Debug) werden eingeschlossen, wenn Sie die Ausgabe des Dienstprojekts zum Setup-Projekt für den Dienst hinzufügen. Nach der Installation werden beide Dienste im MMC-Plugin service.msc angezeigt.
3) Starten Sie den Debug-Dienst in MMC.
4) Hängen Sie in Visual Studio den Debugger an den vom Debug-Dienst gestarteten Prozess an.
5) Starten Sie den echten Dienst und genießen Sie das Debuggen.
quelle
Wenn ich einen Dienst schreibe, füge ich die gesamte Dienstlogik in ein DLL-Projekt ein und erstelle zwei "Hosts", die diese DLL aufrufen. Einer ist ein Windows-Dienst und der andere ist eine Befehlszeilenanwendung.
Ich verwende die Befehlszeilenanwendung zum Debuggen und hänge den Debugger nur für Fehler an den realen Dienst an, die ich in der Befehlszeilenanwendung nicht reproduzieren kann.
Wenn Sie diesen Ansatz verwenden, denken Sie daran, dass Sie den gesamten Code testen müssen, während Sie in einem echten Dienst ausgeführt werden. Das Befehlszeilentool ist eine nette Debugging-Hilfe. Es ist eine andere Umgebung und verhält sich nicht genau wie ein echter Dienst.
quelle
Beim Entwickeln und Debuggen eines Windows-Dienstes führe ich ihn normalerweise als Konsolenanwendung aus, indem ich einen / console-Startparameter hinzufüge und dies überprüfe. Macht das Leben viel einfacher.
quelle
Wie wäre es mit Debugger.Break () in der ersten Zeile?
quelle
Zum Debuggen von Windows-Diensten kombiniere ich GFlags und eine von regedit erstellte REG-Datei.
Oder speichern Sie die folgenden Snippets und ersetzen Sie servicename.exe durch den gewünschten ausführbaren Namen.
debugon.reg:
debugoff.reg:
quelle
Für die routinemäßige Kleinprogrammierung habe ich einen sehr einfachen Trick ausgeführt, um meinen Dienst einfach zu debuggen:
Beim Start des Dienstes suche ich nach einem Befehlszeilenparameter "/ debug". Wenn der Dienst mit diesem Parameter aufgerufen wird, starte ich nicht den üblichen Dienst, sondern starte alle Listener und zeige einfach die Meldung "Debug in Bearbeitung, zum Beenden OK drücken" an.
Wenn mein Dienst auf die übliche Weise gestartet wird, wird er als Dienst gestartet. Wenn er mit dem Befehlszeilenparameter / Debug gestartet wird, verhält er sich wie ein normales Programm.
In VS füge ich einfach als Debugging-Parameter hinzu / debugge und starte das Serviceprogramm direkt.
Auf diese Weise kann ich die meisten kleinen Probleme problemlos beheben. Natürlich müssen einige Dinge noch als Service debuggt werden, aber für 99% ist dies gut genug.
quelle
quelle
Ich verwende eine Variation der Antwort von JOP. Mithilfe von Befehlszeilenparametern können Sie den Debugging-Modus in der IDE mit Projekteigenschaften oder über den Windows-Dienstmanager festlegen.
quelle
Verwenden Sie 'Debugger.Break ()', um Probleme mit vorhandenen Windows-Dienstprogrammen zu beheben, wie von anderen vorgeschlagen.
Für ein neues Windows-Dienstprogramm würde ich die Methode von James Michael Hare empfehlen: http://geekswithblogs.net/BlackRabbitCoder/archive/2011/03/01/c-toolbox-debug-able-self-installable-windows-service-template- redux.aspx
quelle
Platzieren Sie einfach Ihr Debugger-Mittagessen an einer beliebigen Stelle und hängen Sie Visualstudio beim Start an
Außerdem müssen Sie VS als Administatrator starten und zulassen, dass ein Prozess automatisch von einem anderen Benutzer debuggt werden kann (wie hier erläutert ):
quelle
Verwenden Sie das Windows Service Template C # -Projekt, um eine neue Service-App zu erstellen: https://github.com/HarpyWar/windows-service-template
Es gibt einen automatisch erkannten Konsolen- / Servicemodus, eine automatische Installation / Deinstallation Ihres Dienstes und einige der am häufigsten verwendeten Funktionen.
quelle
Hier ist die einfache Methode, mit der ich den Dienst ohne zusätzliche "Debug" -Methoden und mit integrierten VS-Unit-Tests getestet habe.
quelle
quelle
Sie haben zwei Möglichkeiten, um das Debuggen durchzuführen.
Bitte beziehen Sie sich auf DIESEN Blog-Beitrag, den ich für das Thema erstellt habe.
quelle
Einfach einfügen
irgendwo in Ihrem Code.
Beispielsweise ,
Es wird getroffen,
Debugger.Break();
wenn Sie Ihr Programm ausführen.quelle
Am besten verwenden Sie den Namespace ' System.Diagnostics '.
Fügen Sie Ihren Code in den Block "if else" für den Debug-Modus und den Release-Modus ein, wie unten gezeigt, um in Visual Studio zwischen dem Debug- und dem Release-Modus zu wechseln.
quelle