Preparazione del debug dell'applicazione di servizio
In questo argomento sono elencati tutti i passaggi preliminari che possono essere necessari prima di eseguire il debug di un'applicazione di servizio. I passaggi necessari nello scenario dipendono dall'opzione di collegamento scelta e dalla configurazione di debug scelta. Per un elenco di queste opzioni, vedere Scelta del metodo migliore per eseguire il debug di un'applicazione di servizio.
Ognuno dei passaggi preliminari descritti in questo argomento specifica le condizioni in cui è necessario. Questi passaggi possono essere eseguiti in qualsiasi ordine.
Abilitazione del debug del codice di inizializzazione
Se si prevede di eseguire il debug dell'applicazione di servizio dall'inizio dell'esecuzione, incluso il relativo codice di inizializzazione, è necessario questo passaggio preparatorio.
Individuare o creare la chiave del Registro di sistema seguente, dove ProgramName è il nome del file eseguibile dell'applicazione di servizio:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\ProgramName
ProgramName deve includere l'estensione del nome file, ma non il percorso. Ad esempio, ProgramName potrebbe essere Myservice.exe o Thisservice.dll.
In questa chiave del Registro di sistema creare un valore di dati stringa denominato Debugger. Il valore di questa stringa deve essere impostato sul percorso completo e sul nome file di un debugger da associare all'applicazione di servizio.
Se si prevede di eseguire il debug in locale, usare una stringa come la seguente:
c:\Debuggers\windbg.exe
Non scegliere questa opzione se si esegue Windows Vista o una versione successiva di Windows.
Se si prevede di usare il debug remoto, specificare NTSD con l'opzione -noio. In questo modo NTSD viene eseguito senza alcuna console di propria proprietà, accessibile solo tramite la connessione remota. Per esempio:
c:\Debuggers\ntsd.exe -server ServerTransport -noio -y SymbolPath
Se la sessione di debug inizia prima del caricamento completo di Windows, potrebbe non essere possibile accedere ai simboli da una condivisione remota; in tal caso, è necessario usare i simboli locali. ServerTransport deve specificare un protocollo di trasporto implementato dal kernel di Windows senza interfacciarsi con un servizio in modalità utente, ad esempio TCP o NPIPE. Per la sintassi di ServerTransport, vedere Attivazione di un server di debug.
Se si prevede di controllare il debugger in modalità utente da un debugger in modalità kernel, specificare NTSD con l'opzione -d. Per esempio:
c:\Debuggers\ntsd.exe -d -y SymbolPath
Se si prevede di usare questo metodo e i simboli in modalità utente saranno accessibili da un server di simboli, è necessario combinare questo metodo con il debug remoto. In questo caso, specificare NTSD con l'opzione -ddefer. Scegliere un protocollo di trasporto implementato dal kernel di Windows senza interfacciarsi con un servizio in modalità utente, ad esempio TCP o NPIPE. Per esempio:
c:\Debuggers\ntsd.exe -server ServerTransport -ddefer -y SymbolPath
Per informazioni dettagliate, vedere Controllo del debugger User-Mode dal debugger del kernel.
Al termine della modifica del Registro di sistema, il debugger viene avviato ogni volta che un servizio con questo nome viene avviato o riavviato.
abilitare l'applicazione di servizio per avviare il debugger
Se desideri che l'applicazione di servizio si interrompa nel debugger quando si arresta in modo anomalo o rileva un'eccezione, questo passaggio preparatorio è necessario. Questo passaggio è necessario anche se si vuole che l'applicazione di servizio si interrompa nel debugger utilizzando la funzione DebugBreak.
Nota Se è stato abilitato il debug del codice di inizializzazione (il passaggio descritto nella sottosezione "Abilitazione del debug del codice di inizializzazione"), è consigliabile ignorare questo passaggio. Quando il debug del codice di inizializzazione è abilitato, il debugger si connette all'applicazione di servizio quando questa viene avviata, il che fa sì che tutti gli arresti anomali, le eccezioni e le chiamate a DebugBreak vengano instradati al debugger senza bisogno di ulteriori preparazioni.
Questo passaggio preparatorio comporta la registrazione del debugger scelto come debugger postmortem. A tale scopo, usare le opzioni -iae o -iaec nella riga di comando del debugger. È consigliabile usare i comandi seguenti, ma se si vogliono variarli, vedere i dettagli della sintassi in Abilitazione del debug postmortem.
Se si prevede di eseguire il debug in locale, usare un comando simile al seguente:
windbg -iae
Non scegliere questa opzione se si esegue Windows Vista o una versione successiva di Windows.
Se si prevede di usare il debug remoto, specificare NTSD con l'opzione -noio. In questo modo NTSD viene eseguito senza alcuna console di propria proprietà, accessibile solo tramite la connessione remota. Per installare un debugger postmortem che include il parametro -server, è necessario modificare manualmente il Registro di sistema; per informazioni dettagliate, vedere Abilitazione del debug postmortem. Ad esempio, il valore debugger della chiave AeDebug potrebbe essere il seguente:
ntsd -server npipe:pipe=myproc%x -noio -p %ld -e %ld -g -y SymbolPath
Nella specifica della pipe, il token %x viene sostituito con l'ID processo della procedura che avvia il debugger. Ciò garantisce che se più processi avviano un debugger postmortem, ognuno ha un nome di pipe univoco. Se la sessione di debug inizia prima del caricamento completo di Windows, potrebbe non essere possibile accedere ai simboli da una condivisione remota; in tal caso, è necessario usare i simboli locali. ServerTransport deve specificare un protocollo di trasporto implementato dal kernel di Windows senza interfacciarsi con un servizio in modalità utente, ad esempio TCP o NPIPE. Per la sintassi di ServerTransport, vedere Attivazione di un server di debug.
Se si prevede di controllare il debugger in modalità utente da un debugger in modalità kernel, specificare NTSD con l'opzione -d. Per esempio:
ntsd -iaec -d -y SymbolPath
Se si sceglie questo metodo e si intende accedere ai simboli in modalità utente da un server di simboli, è necessario combinare questo metodo con il debug remoto. In questo caso, specificare NTSD con l'opzione -ddefer. Scegliere un protocollo di trasporto implementato dal kernel di Windows senza interfacciarsi con un servizio in modalità utente, ad esempio TCP o NPIPE. Per installare un debugger postmortem che include il parametro -server, è necessario modificare manualmente il Registro di sistema; per informazioni dettagliate, vedere Abilitazione del debug postmortem. Ad esempio, il valore del debugger della chiave AeDebug potrebbe essere il seguente:
ntsd -server npipe:pipe=myproc%x -ddefer -p %ld -e %ld -g -y SymbolPath
Per informazioni dettagliate, vedere Controllo del debugger User-Mode dal debugger del kernel.
Quando esegui uno di questi comandi, il debugger post-mortem viene registrato. Questo debugger verrà avviato ogni volta che un programma in modalità utente, inclusa un'applicazione di servizio, rileva un'eccezione o esegue una funzione DebugBreak.
Regolazione del timeout dell'applicazione del servizio
Se si prevede di avviare automaticamente il debugger (all'avvio del servizio o quando viene rilevata un'eccezione), è necessario questo passaggio preparatorio.
Individua la seguente chiave del Registro di sistema:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
In questa chiave, individuare o creare un valore dati DWORD denominato ServicesPipeTimeout. Impostare questa voce sulla quantità di tempo in millisecondi in cui si vuole che il servizio attenda prima del timeout. Ad esempio, un valore di 60.000 corrisponde a un minuto, mentre un valore di 86.400.000 corrisponde a 24 ore. Quando questo valore del Registro di sistema non è impostato, il timeout predefinito è di circa trenta secondi.
Il significato di questo valore è che un cronometro inizia a funzionare all'avvio di ogni servizio e quando viene raggiunto il valore di timeout, qualsiasi debugger collegato al servizio viene interrotto. Di conseguenza, il valore scelto deve essere più lungo del tempo totale trascorso tra l'avvio del servizio e il completamento della sessione di debug.
Questa impostazione si applica a ogni servizio avviato o riavviato al termine della modifica del Registro di sistema. Se alcuni servizi si arrestano in modo anomalo o si bloccano e questa impostazione è ancora attiva, il problema non viene rilevato da Windows. Pertanto, è consigliabile usare questa impostazione solo durante il debug e restituire la chiave del Registro di sistema al valore originale al termine del debug.
isolare il servizio
In alcuni casi, più servizi vengono combinati in un singolo processo Service Host (Svchost). Se si vuole eseguire il debug di un servizio di questo tipo, è prima necessario isolarlo in un processo Svchost separato.
Esistono tre metodi in base ai quali è possibile isolare un servizio. Microsoft consiglia il metodo "Spostare il servizio in un proprio gruppo", come segue. I metodi alternativi (modifica del tipo di servizio e duplicazione del file binario SvcHost) possono essere usati in modo temporaneo per il debug, ma poiché modificano la modalità di esecuzione del servizio, non sono affidabili come il primo metodo.
metodo preferito: spostamento del servizio nel proprio gruppo
Eseguire il comando service configuration tool (Sc.exe) seguente, in cui ServiceName è il nome del servizio:
sc qc ServiceName
Vengono visualizzati i valori di configurazione correnti per il servizio. Il valore di interesse è BINARY_PATH_NAME, che specifica la riga di comando usata per avviare il programma di controllo del servizio. In questo scenario, poiché il servizio non è ancora isolato, questa riga di comando include un percorso di directory, Svchost.exee alcuni parametri SvcHost, inclusa l'opzione -k, seguita da un nome di gruppo. Ad esempio, potrebbe essere simile al seguente:
%SystemRoot%\System32\svchost.exe -k LocalServiceNoNetwork
Ricordare questo percorso e il nome del gruppo; vengono usati nei passaggi 5 e 6.
Trova la seguente chiave del Registro di sistema:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\SvcHost
Creare un nuovo valore REG_MULTI_SZ con un nome univoco, ad esempio TempGrp).
Impostare questo nuovo valore uguale al nome del servizio da isolare. Non includere nessun percorso di directory o estensione di file. Ad esempio, è possibile impostare il nuovo valore TempGrp uguale a MyService.
Nella stessa chiave del Registro di sistema creare una nuova chiave con lo stesso nome usato nel passaggio 2. Per esempio:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\SvcHost\TempGrp
Ora la chiave SvcHost contiene un valore con il nuovo nome e ha anche una chiave subordinata con lo stesso nome.
Cercare un'altra chiave subordinata alla chiave SvcHost con lo stesso nome del gruppo trovato nel passaggio 1. Se tale chiave esiste, esaminare tutti i valori in esso contenuti e creare duplicati nella nuova chiave creata nel passaggio 4.
Ad esempio, la chiave precedente potrebbe essere denominata come segue:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\SvcHost\LocalServiceNoNetwork
e può contenere valori come CoInitializeSecurityParam, AuthenticationCapabilitiese altri valori. Si passerebbe alla chiave appena creata:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\SvcHost\TempGrp
e creare valori in esso identici in nome, tipo e dati a quelli nella chiave precedente.
Se la chiave precedente non esiste, non è necessario creare una nuova chiave.
Usare il comando seguente dello strumento di configurazione del servizio per modificare il percorso trovato nel passaggio 1:
sc config ServiceName binPath= "RevisedPath"
In questo comando ServiceName è il nome del servizio e RevisedPath è il nuovo valore fornito per BINARY_PATH_NAME. Per RevisedPath, utilizzare lo stesso percorso esatto mostrato nel passaggio 1, incluse tutte le opzioni visualizzate in quella riga, effettuando una sola modifica: sostituire il parametro che segue l'opzione -k con il nome del nuovo valore del Registro di sistema creato nel passaggio 2. Racchiudere RevisedPath tra virgolette. Lo spazio dopo il segno di uguale è obbligatorio.
Ad esempio, il comando potrebbe essere simile al seguente:
sc config MyService binPath= "%SystemRoot%\System32\svchost.exe -k TempGrp"
È possibile usare di nuovo il comando sc qc per esaminare la modifica apportata.
Queste impostazioni avranno effetto alla successiva avvio del servizio. Per cancellare gli effetti del servizio precedente, è consigliabile riavviare Windows anziché riavviare il servizio.
Dopo aver completato il debug, se si vuole restituire il servizio all'host del servizio condiviso, usare di nuovo il comando sc config
metodo alternativo : modifica del tipo di servizio
Eseguire il comando service configuration tool (Sc.exe) seguente, in cui ServiceName è il nome del servizio:
sc config ServiceName type= own
Lo spazio dopo il segno di uguale è obbligatorio.
Riavviare il servizio usando i comandi seguenti:
net stop ServiceName net start ServiceName
Questa alternativa non è il metodo consigliato perché può modificare il comportamento del servizio. Se si usa questo metodo, usare il comando seguente per ripristinare il comportamento normale dopo aver completato il debug:
sc config ServiceName type= share
Metodo Alternativo: Duplicare il Binario SvcHost
Il file eseguibile Svchost.exe si trova nella directory system32 di Windows. Creare una copia di questo file, denominarla svhost2.exee inserirla anche nella directory system32.
Eseguire il comando service configuration tool (Sc.exe) seguente, in cui ServiceName è il nome del servizio:
sc qc ServiceName
Questo comando visualizza i valori di configurazione correnti per il servizio. Il valore di interesse è BINARY_PATH_NAME, che specifica la riga di comando usata per avviare il programma di controllo del servizio. In questo scenario, poiché il servizio non è ancora isolato, questa riga di comando includerà un percorso di directory, Svchost.exee probabilmente alcuni parametri SvcHost. Ad esempio, potrebbe essere simile al seguente:
%SystemRoot%\System32\svchost.exe -k LocalServiceNoNetwork
Per modificare questo percorso, eseguire il comando seguente:
sc config ServiceName binPath= "RevisedPath"
In questo comando ServiceName è il nome del servizio e RevisedPath è il nuovo valore fornito per BINARY_PATH_NAME. Per RevisedPath, usare lo stesso percorso visualizzato nel passaggio 2, incluse tutte le opzioni visualizzate in tale riga, apportando una sola modifica: sostituire Svchost.exe con Svchost2.exe. Racchiudere RevisedPath tra virgolette. Lo spazio dopo il segno di uguale è obbligatorio.
Ad esempio, il comando potrebbe essere simile al seguente:
sc config MyService binPath= "%SystemRoot%\System32\svchost2.exe -k LocalServiceNoNetwork"
È possibile usare di nuovo il comando sc qc per esaminare la modifica apportata.
Riavviare il servizio usando i comandi seguenti:
net stop ServiceName net start ServiceName
Questa alternativa non è il metodo consigliato perché può modificare il comportamento del servizio. Se si utilizza questo metodo, usa il comando sc config per ripristinare il percorso al suo valore originale dopo aver completato il debug.