Vorbereiten des Debuggens der Dienstanwendung
In diesem Thema werden alle vorbereitenden Schritte aufgelistet, die vor dem Debuggen einer Dienstanwendung erforderlich sein können. Welche Schritte in Ihrem Szenario erforderlich sind, hängt davon ab, welche Anfügeoption Sie ausgewählt haben und welche Debugkonfiguration Sie ausgewählt haben. Eine Liste dieser Optionen finden Sie unter Auswählen der besten Methode.
Jeder der in diesem Thema beschriebenen vorbereitenden Schritte gibt die Bedingungen an, unter denen dies erforderlich ist. Diese Schritte können in beliebiger Reihenfolge ausgeführt werden.
Aktivieren des Debuggens des Initialisierungscodes
Wenn Sie planen, die Dienstanwendung ab Beginn ihrer Ausführung zu debuggen, einschließlich des Initialisierungscodes, ist dieser vorbereitende Schritt erforderlich.
Suchen Oder erstellen Sie den folgenden Registrierungsschlüssel, wobei ProgramName der Name der ausführbaren Datei der Dienstanwendung ist:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\ProgramName
ProgramName sollte die Dateinamenerweiterung, aber nicht den Pfad enthalten. Beispielsweise kann ProgramName Myservice.exe oder Thisservice.dll sein.
Erstellen Sie unter diesem Registrierungsschlüssel einen Zeichenfolgendatenwert mit dem Namen Debugger. Der Wert dieser Zeichenfolge sollte auf den vollständigen Pfad und Dateinamen eines Debuggers festgelegt werden, der an die Dienstanwendung angefügt werden soll.
Wenn Sie planen, lokal zu debuggen, verwenden Sie eine Zeichenfolge wie die folgende:
c:\Debuggers\windbg.exe
Wählen Sie diese Option nicht aus, wenn Sie Windows Vista oder eine höhere Version von Windows ausführen.
Wenn Sie das Remotedebuggen verwenden möchten, geben Sie NTSD mit der Option -noio an. Dadurch wird NTSD ohne eigene Konsole ausgeführt, auf die nur über die Remoteverbindung zugegriffen werden kann. Beispiel:
c:\Debuggers\ntsd.exe -server ServerTransport -noio -y SymbolPath
Wenn Ihre Debugsitzung beginnt, bevor Windows vollständig geladen ist, können Sie möglicherweise nicht auf Symbole von einer Remotefreigabe zugreifen. In einem solchen Fall müssen Sie lokale Symbole verwenden. ServerTransport muss ein Transportprotokoll angeben, das vom Windows-Kernel ohne Interfacing mit einem Benutzermodusdienst wie TCP oder NPIPE implementiert wird. Informationen zur Syntax von ServerTransport finden Sie unter Aktivieren eines Debugservers.
Wenn Sie planen, den Benutzermodusdebugger über einen Kernelmodusdebugger zu steuern, geben Sie NTSD mit der Option -d an. Beispiel:
c:\Debuggers\ntsd.exe -d -y SymbolPath
Wenn Sie planen, diese Methode zu verwenden und auf Ihre Benutzermodussymbole von einem Symbolserver aus zugegriffen wird, sollten Sie diese Methode mit dem Remotedebuggen kombinieren. Geben Sie in diesem Fall NTSD mit der Option -ddefer an. Wählen Sie ein Transportprotokoll aus, das vom Windows-Kernel ohne Interfacing mit einem Benutzermodusdienst wie TCP oder NPIPE implementiert wird. Beispiel:
c:\Debuggers\ntsd.exe -server ServerTransport -ddefer -y SymbolPath
Ausführliche Informationen finden Sie unter Steuern des User-Mode Debuggers über den Kerneldebugger.
Nach Abschluss dieser Registrierungsbearbeitung wird der Debugger immer dann gestartet, wenn ein Dienst mit diesem Namen gestartet oder neu gestartet wird.
Aktivieren des Einbruchs der Dienstanwendung in den Debugger
Wenn die Dienstanwendung in den Debugger einbricht, wenn sie abstürzt oder auf eine Ausnahme stößt, ist dieser vorbereitende Schritt erforderlich. Dieser Schritt ist auch erforderlich, wenn die Dienstanwendung durch Aufrufen der DebugBreak-Funktion in den Debugger einbricht.
Hinweis Wenn Sie das Debuggen des Initialisierungscodes aktiviert haben (der Schritt, der im Unterabschnitt "Aktivieren des Debuggens des Initialisierungscodes" beschrieben wird), sollten Sie diesen Schritt überspringen. Wenn das Debuggen von Initialisierungscode aktiviert ist, wird der Debugger beim Starten an die Dienstanwendung angefügt, was dazu führt, dass alle Abstürze, Ausnahmen und Aufrufe von DebugBreak an den Debugger weitergeleitet werden, ohne dass zusätzliche Vorbereitungen erforderlich sind.
Dieser vorbereitende Schritt umfasst die Registrierung des ausgewählten Debuggers als postmortem-Debugger. Dazu verwenden Sie die Optionen -iae oder -iaec in der Befehlszeile des Debuggers. Wir empfehlen die folgenden Befehle, aber wenn Sie sie variieren möchten, lesen Sie die Syntaxdetails unter Aktivieren des Postmortem-Debuggens.
Wenn Sie planen, lokal zu debuggen, verwenden Sie einen Befehl wie den folgenden:
windbg -iae
Wählen Sie diese Option nicht aus, wenn Sie Windows Vista oder eine höhere Version von Windows ausführen.
Wenn Sie das Remotedebuggen verwenden möchten, geben Sie NTSD mit der Option -noio an. Dadurch wird NTSD ohne eigene Konsole ausgeführt, auf die nur über die Remoteverbindung zugegriffen werden kann. Um einen postmortem-Debugger zu installieren, der den Parameter -server enthält, müssen Sie die Registrierung manuell bearbeiten. Weitere Informationen finden Sie unter Aktivieren des Postmortemdebuggens. Der Debuggerwert des AeDebug-Schlüssels kann beispielsweise wie folgt aussehen:
ntsd -server npipe:pipe=myproc%x -noio -p %ld -e %ld -g -y SymbolPath
In der Pipespezifikation wird das Token %x durch die Prozess-ID des Prozesses ersetzt, der den Debugger startet. Dadurch wird sichergestellt, dass, wenn mehr als ein Prozess einen postmortem-Debugger startet, jeder einen eindeutigen Pipenamen hat. Wenn Ihre Debugsitzung beginnt, bevor Windows vollständig geladen ist, können Sie möglicherweise nicht auf Symbole von einer Remotefreigabe zugreifen. In einem solchen Fall müssen Sie lokale Symbole verwenden. ServerTransport muss ein Transportprotokoll angeben, das vom Windows-Kernel ohne Interfacing mit einem Benutzermodusdienst wie TCP oder NPIPE implementiert wird. Informationen zur Syntax von ServerTransport finden Sie unter Aktivieren eines Debugservers.
Wenn Sie planen, den Benutzermodusdebugger über einen Kernelmodusdebugger zu steuern, geben Sie NTSD mit der Option -d an. Beispiel:
ntsd -iaec -d -y SymbolPath
Wenn Sie diese Methode auswählen und über einen Symbolserver auf Benutzermodussymbole zugreifen möchten, sollten Sie diese Methode mit dem Remotedebuggen kombinieren. Geben Sie in diesem Fall NTSD mit der Option -ddefer an. Wählen Sie ein Transportprotokoll aus, das vom Windows-Kernel ohne Interfacing mit einem Benutzermodusdienst wie TCP oder NPIPE implementiert wird. Um einen postmortem-Debugger zu installieren, der den Parameter -server enthält, müssen Sie die Registrierung manuell bearbeiten. Weitere Informationen finden Sie unter Aktivieren des Postmortemdebuggens. Der Debuggerwert des AeDebug-Schlüssels kann beispielsweise wie folgt aussehen:
ntsd -server npipe:pipe=myproc%x -ddefer -p %ld -e %ld -g -y SymbolPath
Ausführliche Informationen finden Sie unter Steuern des User-Mode Debuggers über den Kerneldebugger.
Wenn Sie einen dieser Befehle ausgeben, wird der postmortem-Debugger registriert. Dieser Debugger wird gestartet, wenn ein Benutzermodusprogramm, einschließlich einer Dienstanwendung, auf eine Ausnahme stößt oder eine DebugBreak-Funktion ausführt.
Anpassen des Dienstanwendungstimeouts
Wenn Sie planen, den Debugger automatisch zu starten (entweder beim Starten des Diensts oder wenn eine Ausnahme auftritt), ist dieser vorbereitende Schritt erforderlich.
Suchen Sie folgenden Registrierungsschlüssel:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
Suchen Oder erstellen Sie unter diesem Schlüssel einen DWORD-Datenwert namens ServicesPipeTimeout. Legen Sie diesen Eintrag auf den Zeitraum in Millisekunden fest, für den der Dienst warten soll, bevor die Zeitüberschreitung erfolgt. Beispielsweise ist ein Wert von 60.000 eine Minute, während ein Wert von 86.400.000 24 Stunden ist. Wenn dieser Registrierungswert nicht festgelegt ist, beträgt das Standardtimeout etwa dreißig Sekunden.
Die Bedeutung dieses Werts besteht darin, dass eine Uhr beim Starten der einzelnen Dienste ausgeführt wird, und wenn der Timeoutwert erreicht wird, jeder Debugger, der an den Dienst angefügt ist, beendet wird. Daher sollte der von Ihnen ausgewählte Wert länger sein als die Gesamtdauer, die zwischen dem Starten des Diensts und dem Abschluss Ihrer Debugsitzung verstreicht.
Diese Einstellung gilt für jeden Dienst, der nach Abschluss der Registrierungsbearbeitung gestartet oder neu gestartet wird. Wenn ein Dienst abstürzt oder abstürzt und diese Einstellung weiterhin gültig ist, wird das Problem von Windows nicht erkannt. Daher sollten Sie diese Einstellung nur beim Debuggen verwenden und den Registrierungsschlüssel nach Abschluss des Debuggens auf den ursprünglichen Wert zurückgeben.
Isolieren des Diensts
Manchmal werden mehrere Dienste in einem einzelnen Diensthostprozess (Svchost) kombiniert. Wenn Sie einen solchen Dienst debuggen möchten, müssen Sie ihn zuerst in einen separaten Svchost-Prozess isolieren.
Es gibt drei Methoden, mit denen Sie einen Dienst isolieren können. Microsoft empfiehlt die Methode Verschieben des Diensts in eine eigene Gruppe, wie folgt. Die alternativen Methoden (Ändern des Diensttyps und Duplizieren der SvcHost-Binärdatei) können auf temporärer Basis für das Debuggen verwendet werden, aber da sie die Ausführungsweise des Diensts ändern, sind sie nicht so zuverlässig wie die erste Methode.
Bevorzugte Methode: Verschieben des Diensts in eine eigene Gruppe
Geben Sie den folgenden Dienstkonfigurationstool-Befehl (Sc.exe) aus, wobei ServiceName der Name des Diensts ist:
sc qc ServiceName
Dadurch werden die aktuellen Konfigurationswerte für den Dienst angezeigt. Der wert von Interesse ist BINARY_PATH_NAME, der die Befehlszeile angibt, die zum Starten des Dienststeuerungsprogramms verwendet wird. Da Ihr Dienst in diesem Szenario noch nicht isoliert ist, enthält diese Befehlszeile einen Verzeichnispfad, Svchost.exe und einige SvcHost-Parameter, einschließlich des Schalters -k, gefolgt von einem Gruppennamen. Dies kann z. B. wie folgt aussehen:
%SystemRoot%\System32\svchost.exe -k LocalServiceNoNetwork
Merken Sie sich diesen Pfad und den Gruppennamen. sie werden in den Schritten 5 und 6 verwendet.
Suchen Sie folgenden Registrierungsschlüssel:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\SvcHost
Erstellen Sie einen neuen REG_MULTI_SZ-Wert mit einem eindeutigen Namen (z. B. TempGrp).
Legen Sie diesen neuen Wert auf den Namen des Diensts fest, den Sie isolieren möchten. Schließen Sie keinen Verzeichnispfad oder keine Dateinamenerweiterung ein. Beispielsweise können Sie den neuen Wert TempGrp auf MyService festlegen.
Erstellen Sie unter demselben Registrierungsschlüssel einen neuen Schlüssel mit demselben Namen, den Sie in Schritt 2 verwendet haben. Beispiel:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\SvcHost\TempGrp
Nun enthält der SvcHost-Schlüssel einen Wert mit dem neuen Namen und einen untergeordneten Schlüssel mit diesem Namen.
Suchen Sie nach einem anderen Schlüssel, der dem SvcHost-Schlüssel untergeordnet ist und denselben Namen wie die Gruppe hat, die Sie in Schritt 1 gefunden haben. Wenn ein solcher Schlüssel vorhanden ist, überprüfen Sie alle darin enthaltenen Werte, und erstellen Sie Duplikate davon in dem neuen Schlüssel, den Sie in Schritt 4 erstellt haben.
Der alte Schlüssel kann z. B. wie folgt heißen:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\SvcHost\LocalServiceNoNetwork
und kann Werte wie CoInitializeSecurityParam, AuthenticationCapabilities und andere Werte enthalten. Sie wechseln zum neu erstellten Schlüssel:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\SvcHost\TempGrp
und erstellen Darin Werte, die in Name, Typ und Daten mit denen im alten Schlüssel identisch sind.
Wenn der alte Schlüssel nicht vorhanden ist, müssen Sie keinen neuen Schlüssel erstellen.
Verwenden Sie den folgenden Dienstkonfigurationstoolbefehl, um den pfad in Schritt 1 zu überarbeiten:
sc config ServiceName binPath= "RevisedPath"
In diesem Befehl ist ServiceName der Name des Diensts, und RevisedPath ist der neue Wert, den Sie für BINARY_PATH_NAME angeben. Verwenden Sie für RevisedPath genau denselben Pfad wie der in Schritt 1 angezeigte Pfad, einschließlich aller in dieser Zeile angezeigten Optionen, und nehmen Sie nur eine Änderung vor: Ersetzen Sie den Parameter nach dem Schalter -k durch den Namen des neuen Registrierungswerts, den Sie in Schritt 2 erstellt haben. Schließen Sie RevisedPath in Anführungszeichen ein. Der Platz nach dem Gleichheitszeichen ist erforderlich.
Ihr Befehl könnte beispielsweise wie dieser aussehen:
sc config MyService binPath= "%SystemRoot%\System32\svchost.exe -k TempGrp"
Sie können den Befehl sc qc erneut verwenden, um die vorgenommene Änderung zu überprüfen.
Diese Einstellungen werden beim nächsten Start des Diensts wirksam. Um die Auswirkungen des alten Diensts zu löschen, wird empfohlen, Windows neu zu starten, anstatt nur den Dienst neu zu starten.
Wenn Sie nach Abschluss des Debuggens diesen Dienst an den Host des freigegebenen Diensts zurückgeben möchten, verwenden Sie erneut den Befehl sc config , um den binären Pfad auf den ursprünglichen Wert zurückzugeben, und löschen Sie die neuen Registrierungsschlüssel und -werte, die Sie erstellt haben.
Alternative Methode: Ändern des Diensttyps
Geben Sie den folgenden Dienstkonfigurationstool-Befehl (Sc.exe) aus, wobei ServiceName der Name des Diensts ist:
sc config ServiceName type= own
Der Platz nach dem Gleichheitszeichen ist erforderlich.
Starten Sie den Dienst mit den folgenden Befehlen neu:
net stop ServiceName net start ServiceName
Diese Alternative ist nicht die empfohlene Methode, da sie das Verhalten des Diensts ändern kann. Wenn Sie diese Methode verwenden, verwenden Sie den folgenden Befehl, um das normale Verhalten zu rückgängig machen, nachdem Sie das Debuggen abgeschlossen haben:
sc config ServiceName type= share
Alternative Methode: Duplizieren der SvcHost Binary
Die Svchost.exe ausführbare Datei befindet sich im System32-Verzeichnis von Windows. Erstellen Sie eine Kopie dieser Datei, benennen Sie sie svhost2.exe, und platzieren Sie sie ebenfalls im System32-Verzeichnis.
Geben Sie den folgenden Dienstkonfigurationstool-Befehl (Sc.exe) aus, wobei ServiceName der Name des Diensts ist:
sc qc ServiceName
Mit diesem Befehl werden die aktuellen Konfigurationswerte für den Dienst angezeigt. Der wert von Interesse ist BINARY_PATH_NAME, der die Befehlszeile angibt, die zum Starten des Dienststeuerungsprogramms verwendet wird. Da ihr Dienst in diesem Szenario noch nicht isoliert ist, enthält diese Befehlszeile einen Verzeichnispfad, Svchost.exe und wahrscheinlich einige SvcHost-Parameter. Dies kann z. B. wie folgt aussehen:
%SystemRoot%\System32\svchost.exe -k LocalServiceNoNetwork
Um diesen Pfad zu überarbeiten, geben Sie den folgenden Befehl aus:
sc config ServiceName binPath= "RevisedPath"
In diesem Befehl ist ServiceName der Name des Diensts, und RevisedPath ist der neue Wert, den Sie für BINARY_PATH_NAME angeben. Verwenden Sie für RevisedPath genau denselben Pfad wie der in Schritt 2 angezeigte Pfad, einschließlich aller optionen, die in dieser Zeile angezeigt werden, und nehmen Sie nur eine Änderung vor: Ersetzen Sie Svchost.exe durch Svchost2.exe. Schließen Sie RevisedPath in Anführungszeichen ein. Der Platz nach dem Gleichheitszeichen ist erforderlich.
Ihr Befehl könnte beispielsweise wie dieser aussehen:
sc config MyService binPath= "%SystemRoot%\System32\svchost2.exe -k LocalServiceNoNetwork"
Sie können den Befehl sc qc erneut verwenden, um die vorgenommene Änderung zu überprüfen.
Starten Sie den Dienst mithilfe der folgenden Befehle neu:
net stop ServiceName net start ServiceName
Diese Alternative ist nicht die empfohlene Methode, da sie das Verhalten des Diensts ändern kann. Wenn Sie diese Methode verwenden, verwenden Sie den Befehl sc config , um den Pfad zurück in den ursprünglichen Wert zu ändern, nachdem Sie das Debuggen abgeschlossen haben.