Compartilhar via


Preparar para depurar o aplicativo de serviço

Este tópico lista todas as etapas preparatórias que podem ser necessárias antes da depuração de um aplicativo de serviço. Quais etapas são necessárias em seu cenário dependem de qual opção de anexação você escolheu e qual configuração de depuração você escolheu. Para obter uma lista dessas opções, consulte Escolhendo o melhor método para depurar um aplicativo de serviço.

Cada uma das etapas preparatórias descritas neste tópico especifica as condições sob as quais ela é necessária. Essas etapas podem ser feitas em qualquer ordem.

Habilitar a depuração do código de inicialização

Se você planeja depurar o aplicativo de serviço desde o início de sua execução, incluindo seu código de inicialização, essa etapa preparatória será necessária.

Localize ou crie a seguinte chave do Registro, em que ProgramName é o nome do arquivo executável do aplicativo de serviço:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\ProgramName 

ProgramName deve incluir a extensão de nome de arquivo, mas não o caminho. Por exemplo, ProgramName pode ser Myservice.exe ou Thisservice.dll.

Nessa chave do Registro, crie um valor de dados de cadeia de caracteres intitulado Depurador. O valor dessa cadeia de caracteres deve ser definido como o caminho completo e o nome do arquivo de um depurador a ser anexado à aplicação de serviço.

  • Se você planeja depurar localmente, use uma cadeia de caracteres como a seguinte:

    c:\Debuggers\windbg.exe 
    

    Não escolha essa opção se você estiver executando o Windows Vista ou uma versão posterior do Windows.

  • Se você planeja usar a depuração remota, especifique NTSD com a opção -noio. Isso faz com que o NTSD seja executado sem nenhum console próprio, acessível apenas por meio da conexão remota. Por exemplo:

    c:\Debuggers\ntsd.exe -server ServerTransport -noio -y SymbolPath 
    

    Se a sessão de depuração começar antes do Windows estar totalmente carregado, talvez você não consiga acessar símbolos de um compartilhamento remoto; nesse caso, você deve usar símbolos locais. ServerTransport deve especificar um protocolo de transporte implementado pelo kernel do Windows sem interfiguração com um serviço de modo de usuário, como TCP ou NPIPE. Para obter a sintaxe de ServerTransport, consulte Ativando um servidor de depuração.

  • Se você planeja controlar o depurador de modo de usuário a partir de um depurador de modo kernel, especifique NTSD com a opção -d. Por exemplo:

    c:\Debuggers\ntsd.exe -d -y SymbolPath 
    

    Se você planeja usar esse método e seus símbolos de modo de usuário serão acessados de um servidor de símbolos, você deverá combinar esse método com a depuração remota. Nesse caso, especifique NTSD com a opção -ddefer. Escolha um protocolo de transporte implementado pelo kernel do Windows sem interfiguração com um serviço de modo de usuário, como TCP ou NPIPE. Por exemplo:

    c:\Debuggers\ntsd.exe -server ServerTransport -ddefer -y SymbolPath 
    

    Para obter detalhes, consulte Controlando o depurador User-Mode a partir do depurador kernel.

Depois que essa edição do Registro for concluída, o depurador será iniciado sempre que um serviço com esse nome for iniciado ou reiniciado.

Habilitar a aplicação de serviço para interromper o depuração

Se você quiser que a aplicação de serviço interrompa o depurador quando ele falhar ou encontrar uma exceção, essa etapa preparatória será necessária. Essa etapa também será necessária se você quiser que a aplicação de serviço interrompa o depurador chamando a função DebugBreak.

Observação Se você tiver habilitado a depuração do código de inicialização (a etapa descrita na subseção "Habilitando a depuração do código de inicialização"), ignore esta etapa. Quando a depuração de código de inicialização é habilitada, o depurador é anexado ao aplicativo de serviço quando ele é iniciado, o que faz com que todas as falhas, exceções e chamadas para DebugBreak sejam roteadas para o depurador sem que sejam necessárias preparações adicionais.

Registrar o depurador escolhido como o depurador pós-morte é uma etapa preparatória. Isso é feito usando as opções -iae ou -iaec na linha de comando do depurador. Recomendamos os comandos a seguir, mas, se você quiser variar, confira os detalhes da sintaxe em Habilitar a depuração de análise posterior.

  • Se você planeja depurar localmente, use um comando como o seguinte:

    windbg -iae 
    

    Não escolha essa opção se você estiver executando o Windows Vista ou uma versão posterior do Windows.

  • Se você planeja usar a depuração remota, especifique NTSD com a opção -noio. Isso faz com que o NTSD seja executado sem nenhum console próprio, acessível apenas por meio da conexão remota. Você deve editar manualmente o registro para instalar um depurador de análise posterior que inclui o parâmetro -server. Para obter detalhes, consulte Habilitar a depuração de análise posterior. Por exemplo, o valor Depurador da chave AeDebug pode ser o seguinte:

    ntsd -server npipe:pipe=myproc%x -noio -p %ld -e %ld -g -y SymbolPath 
    

    Na especificação de pipe, o token %x é substituído pelo ID do processo que inicia o depurador. Isso garante que, se mais de um processo iniciar um depurador de análise posterior, cada um terá um nome de canal exclusivo. Se a sessão de depuração começar antes do Windows ser totalmente carregado, talvez você não consiga acessar símbolos de um compartilhamento remoto; nesse caso, você deve usar símbolos locais. ServerTransport deve especificar um protocolo de transporte implementado pelo kernel do Windows sem interfiguração com um serviço de modo de usuário, como TCP ou NPIPE. Para obter a sintaxe de ServerTransport, consulte Ativando um servidor de depuração.

  • Se você planeja controlar o depurador modo usuário a partir de um depurador modo kernel, especifique NTSD com a opção -d. Por exemplo:

    ntsd -iaec -d -y SymbolPath 
    

    Se você escolher esse método e pretende acessar símbolos de modo usuário de um servidor de símbolos, deverá combinar esse método com depuração remota. Nesse caso, especifique NTSD com a opção -ddefer. Escolha um protocolo de transporte implementado pelo kernel do Windows sem interfiguração com um serviço de modo de usuário, como TCP ou NPIPE. Para instalar um depurador pós-morte que inclui o parâmetro -server, você deve editar manualmente o registro; para obter detalhes, consulte Habilitando a Depuração Pós-Morte. Por exemplo, o valor Depurador da chave AeDebug pode ser o seguinte:

    ntsd -server npipe:pipe=myproc%x -ddefer -p %ld -e %ld -g -y SymbolPath 
    

    Para obter detalhes, veja Controlando o Depurador User-Mode a partir do Depurador de Kernel.

Quando você emite um desses comandos, o depurador de análise posterior é registrado. Esse depurador será iniciado sempre que qualquer programa de modo de usuário, incluindo um aplicativo de serviço, encontrar uma exceção ou executar uma função DebugBreak.

Ajustar o tempo limite da aplicação de serviço

Se você planeja iniciar o depurador automaticamente (quando o serviço é iniciado ou quando encontra uma exceção), essa etapa preparatória é necessária.

Localize a seguinte chave do Registro:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control

Nessa chave, localize ou crie um valor de dados DWORD chamado ServicesPipeTimeout. Defina essa entrada como a quantidade de tempo em milissegundos que você deseja que o serviço aguarde antes do tempo limite. Por exemplo, um valor de 60.000 é de um minuto, enquanto um valor de 86.400.000 é de 24 horas. Quando esse valor do Registro não é definido, o tempo limite padrão é de cerca de trinta segundos.

O significado desse valor é que um relógio começa a contar quando cada serviço é iniciado e, quando o valor do tempo limite é atingido, qualquer depurador anexado ao serviço é encerrado. Portanto, o valor escolhido deve ser maior do que o tempo total decorrido entre a inicialização do serviço e a conclusão da sessão de depuração.

Essa configuração se aplica a todos os serviços iniciados ou reiniciados após a conclusão da edição do Registro. Se algum serviço falhar ou travar e essa configuração ainda estiver em vigor, o problema não será detectado pelo Windows. Portanto, você deve usar essa configuração somente enquanto estiver depurando e retornar a chave do Registro ao seu valor original após a conclusão da depuração.

Isolar o serviço

Às vezes, vários serviços são combinados em um único processo de Host de Serviço (Svchost). Se você quiser depurar esse serviço, deve primeiro isolá-lo em um processo Svchost separado.

Há três métodos pelos quais você pode isolar um serviço. A Microsoft recomenda mover o serviço para seu próprio método de grupo, da seguinte maneira. Os métodos alternativos (alterando o tipo de serviço e duplicando o binário SvcHost) podem ser usados temporariamente para depuração, mas como alteram a maneira como o serviço é executado, eles não são tão confiáveis quanto o primeiro método.

Método preferencial: movendo o serviço para seu próprio grupo

  1. Emita o seguinte comando de configuração de serviço (Sc.exe), em que ServiceName é o nome do serviço:

    sc qc ServiceName 
    

    Isso exibe os valores de configuração atuais para o serviço. O valor de interesse é BINARY_PATH_NAME, que especifica a linha de comando usada para iniciar o programa de controle de serviço. Nesse cenário, como seu serviço ainda não está isolado, essa linha de comando inclui um caminho de diretório, Svchost.exee alguns parâmetros SvcHost, incluindo o comutador -k, seguido por um nome de grupo. Por exemplo, ele pode ter uma aparência semelhante a esta:

    %SystemRoot%\System32\svchost.exe -k LocalServiceNoNetwork 
    

    Lembre-se desse caminho e do nome do grupo; eles são usados nas etapas 5 e 6.

  2. Localize a seguinte chave do Registro:

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\SvcHost 
    

    Crie um novo valor REG_MULTI_SZ com um nome exclusivo (por exemplo, tempGrp).

  3. Defina esse novo valor igual ao nome do serviço que você deseja isolar. Não inclua nenhum caminho de diretório ou extensão de nome de arquivo. Por exemplo, você pode definir o novo valor TempGrp igual a MyService.

  4. Na mesma chave do Registro, crie uma nova chave com o mesmo nome usado na etapa 2. Por exemplo:

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\SvcHost\TempGrp 
    

    Agora, a chave SvcHost contém um valor com o novo nome e também tem uma chave subordinada com esse mesmo nome.

  5. Procure outra chave subordinada à chave SvcHost que tenha o mesmo nome do grupo encontrado na etapa 1. Se essa chave existir, examine todos os valores nela e crie duplicatas deles na nova chave que você criou na etapa 4.

    Por exemplo, a chave antiga pode ser nomeada assim:

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\SvcHost\LocalServiceNoNetwork 
    

    e pode conter valores como CoInitializeSecurityParam, AuthenticationCapabilitiese outros valores. Você iria para a chave recém-criada:

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\SvcHost\TempGrp 
    

    e crie valores que sejam idênticos em nome, tipo e dados para aqueles na chave antiga.

    Se a chave antiga não existir, você não precisará criar uma nova chave.

  6. Use o seguinte comando da ferramenta Configuração de Serviço para revisar o caminho encontrado na etapa 1:

    sc config ServiceName binPath= "RevisedPath" 
    

    Neste comando, ServiceName é o nome do serviço e RevisedPath é o novo valor que você está fornecendo para BINARY_PATH_NAME. Para RevisedPath, use exatamente o mesmo caminho que o exibido na etapa 1, incluindo todas as opções mostradas nessa linha, fazendo apenas uma alteração: substitua o parâmetro após a opção -k pelo nome do novo valor do Registro criado na etapa 2. Coloque RevisedPath entre aspas. O espaço após o sinal de igual é obrigatório.

    Por exemplo, seu comando pode ter esta aparência:

    sc config MyService binPath= "%SystemRoot%\System32\svchost.exe -k TempGrp" 
    

    Talvez você queira usar o comando sc qc novamente para examinar a alteração feita.

Essas configurações entrarão em vigor na próxima vez que o serviço for iniciado. Para limpar os efeitos do serviço antigo, recomendamos reiniciar o Windows em vez de apenas reiniciar o serviço.

Depois de concluir a depuração, se você quiser retornar esse serviço ao host de serviço compartilhado, use o comando sc config novamente para restaurar o caminho binário ao seu valor original e, em seguida, exclua as novas chaves e valores do Registro que você criou.

Método alternativo : alterando o tipo de serviço

  1. Emita o seguinte comando de configuração de serviço (Sc.exe), em que ServiceName é o nome do serviço:

    sc config ServiceName type= own 
    

    O espaço após o sinal de igual é obrigatório.

  2. Reinicie o serviço usando os seguintes comandos:

    net stop ServiceName 
    net start ServiceName 
    

Essa alternativa não é o método recomendado porque pode alterar o comportamento do serviço. Se você usar esse método, use o seguinte comando para reverter para o comportamento normal depois de concluir a depuração:

sc config ServiceName type= share 

Método alternativo: duplicar o binário SvcHost

  1. O arquivo executável Svchost.exe está localizado no diretório system32 do Windows. Faça uma cópia desse arquivo, nomeie-o svhost2.exee coloque-o no diretório system32 também.

  2. Emita o seguinte comando de configuração de serviço (Sc.exe), em que ServiceName é o nome do serviço:

    sc qc ServiceName 
    

    Este comando exibe os valores de configuração atuais para o serviço. O valor de interesse é BINARY_PATH_NAME, que especifica a linha de comando usada para iniciar o programa de controle de serviço. Nesse cenário, como seu serviço ainda não está isolado, essa linha de comando incluirá um caminho de diretório, Svchost.exee, provavelmente, alguns parâmetros SvcHost. Por exemplo, ele pode ter uma aparência semelhante a esta:

    %SystemRoot%\System32\svchost.exe -k LocalServiceNoNetwork 
    
  3. Para revisar esse caminho, emita o seguinte comando:

    sc config ServiceName binPath= "RevisedPath" 
    

    Neste comando, ServiceName é o nome do serviço e RevisedPath é o novo valor que você está fornecendo para BINARY_PATH_NAME. Para RevisedPath, use exatamente o mesmo caminho que o exibido na etapa 2, incluindo todas as opções mostradas nessa linha, fazendo apenas uma alteração: substituir Svchost.exe por Svchost2.exe. Coloque RevisedPath entre aspas. O espaço após o sinal de igual é obrigatório.

    Por exemplo, seu comando pode ter esta aparência:

    sc config MyService binPath= "%SystemRoot%\System32\svchost2.exe -k LocalServiceNoNetwork" 
    

    Você pode usar o comando sc qc novamente para examinar a alteração feita.

  4. Reinicie o serviço usando os seguintes comandos:

    net stop ServiceName 
    net start ServiceName 
    

Essa alternativa não é o método recomendado porque pode alterar o comportamento do serviço. Se você utilizar este método, use o comando sc config para redefinir o caminho ao seu valor original após concluir a depuração.