Depurar servicios con ayuda de PowerShell

Hablaba hace unos días de algunos trucos para depurar servicios: Depurando servicios de Windows más facilmente. Los trucos comentados en mi anterior post, aun siendo útililes, tienen un problema. De una u otra manera alteran el servicio que queremeos depurar. El código que realmente se ejecuta no es exactamente el código que ejcutará nuestro servicio en su versión release.


Windows cuenta con un mecanismo que nos permite establecer un depurador para que se ejecute cuando se arranca un determinado ejecutable. El proceso, que es bastante tedioso, está sobradamente descrito en estos dos artículos: Debugging startup code of services and com servers y How to debug Windows services. He hecho un script de PowerShell que automatiza el proceso.


Os dejo el código de PowerShell, que además es un buen ejemplo sobre como trabajar con el registro y sobre como parsear parámetros de línea de comandos con PowerShell.






  1. #Script que automatiza el establecimiento de un depurador para que se inicie al inicia un servicio  
  2. #El procedimiento está descrito en http://support.microsoft.com/kb/824344  
  3.  
  4. #Asegurarnos de que todas las variables son previamente declaradas  
  5.  
  6. param ( [switch] $Prepare,  
  7.         [switch] $Clean,  
  8.         [string] $ServiceName,  
  9.         [string] $ServiceExecutable )  
  10.           
  11. Set-PSDebug -Strict  
  12.  
  13. #Path al depurador que deseamos usar  
  14. #Yo uso el depurado de VS pero podríamos usar windbg si el servicio fuese nativo y no .net  
  15. $debuggerPath = “vsjitdebugger.exe” 
  16. $imageFileExecutionOptionsPath = “HKLM:SOFTWAREMicrosoftWindows NTCurrentVersionImage File Execution Options” + $ServiceExecutable
  17. $serviceRegistryPath = “HKLM:SYSTEMCurrentControlSetServices” + $ServiceName 
  18. $servicesControlRegitryPath = “HKLM:SYSTEMCurrentControlSetControl” 
  19.  
  20. function Usage()  
  21. {  
  22.     “Establece las claves del registro necesarias para que el depurador se adjunte automáticamente al proceso de un servicio cuando este se ejecuta.” 
  23.     “Puede ser necesario reiniciar la máquina para que este script tenga efecto.” 
  24.     “Basicamente este script automatiza el proceso descrito en http://support.microsoft.com/kb/824344.” 
  25.     “” 
  26.     “Usage: Debug-Service -Prepare | -Clear -ServiceName <string> -ServiceExecutable <string>” 
  27.     “” 
  28.     “Parameters:” 
  29.     “-Prepare: Prepara el servicio especificado para su depuración.” 
  30.     “-Clear: Vuelve el servicio a su estado normal.” 
  31.      
  32.     exit  
  33. }  
  34.  
  35. function Prepare()  
  36. {  
  37.     #Configuramos en el registro el depurador a iniciar cuando se arranque el servicio  
  38.     if ( !(Test-Path $imageFileExecutionOptionsPath))  
  39.     {  
  40.         New-Item -path $imageFileExecutionOptionsPath | out-null  
  41.     }  
  42.       
  43.     Set-ItemProperty -path $imageFileExecutionOptionsPath -name “debugger” -value $debuggerPath 
  44.  
  45.     #Configuramos el servicio como interactivo para que se pueda mostrar la ventana del depurador  
  46.     $serviceTypeValue = (Get-ItemProperty -path $serviceRegistryPath).Type  
  47.     $serviceTypeValue = $serviceTypeValue -bor 0x00000100  
  48.     Set-ItemProperty -path $serviceRegistryPath -name “Type” -value $serviceTypeValue 
  49.     #Establecemos el arranque del servicio a manual  
  50.     Set-ItemProperty -path $serviceRegistryPath -name “Start” -value 3  
  51.       
  52.     #Configuramos el tiempo de timeout para el arranque de los servicios en 24 horas para tener margen para depurar  
  53.     Set-ItemProperty -path $servicesControlRegitryPath -name “ServicesPipeTimeout” -value 86400000  
  54. }  
  55.  
  56. function Clean()  
  57. {  
  58.     if ( (Test-Path $imageFileExecutionOptionsPath))  
  59.     {  
  60.         Remove-Item -path $imageFileExecutionOptionsPath 
  61.     }  
  62.       
  63.     Remove-ItemProperty -path $servicesControlRegitryPath -name “ServicesPipeTimeout” 
  64. }  
  65.  
  66. if (!($Prepare -or $Clean) -or !($ServiceName -and $ServiceExecutable))  
  67. {  
  68.     Usage  
  69. }  
  70.  
  71. if ($Prepare -and $Clean)  
  72. {  
  73.     Write-Warning “No se puede usar Prepare y Clean a la vez” 
  74.     exit  
  75. }  
  76.  
  77. if ($Prepare)  
  78. {  
  79.     Prepare  
  80. }  
  81.  
  82. if ($Clean)  
  83. {  
  84.     Clean  

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *