¿Hay una manera más fácil de recorrer el código que iniciar el servicio a través del Administrador de control de servicios de Windows y luego adjuntar el depurador al hilo? Es un poco engorroso y me pregunto si hay un enfoque más directo.
c#
debugging
windows-services
Matthias
fuente
fuente
Respuestas:
Si quiero depurar rápidamente el servicio, simplemente entro
Debugger.Break()
allí. Cuando se alcanza esa línea, me devolverá a VS. No olvide eliminar esa línea cuando haya terminado.ACTUALIZACIÓN: Como alternativa a los
#if DEBUG
pragmas, también puede usar elConditional("DEBUG_SERVICE")
atributo.En su
OnStart
, simplemente llame a este método:Allí, el código solo se habilitará durante las compilaciones de depuración. Mientras lo hace, puede ser útil crear una configuración de compilación separada para la depuración del servicio.
fuente
También creo que tener una "versión" separada para la ejecución normal y como servicio es el camino a seguir, pero ¿es realmente necesario dedicar un interruptor de línea de comando separado para ese propósito?
¿No podrías simplemente hacer:
Eso tendría el "beneficio" de que puede iniciar su aplicación mediante un doble clic (OK, si realmente lo necesita) y que puede presionar F5en Visual Studio (sin la necesidad de modificar la configuración del proyecto para incluir esa
/console
Opción).Técnicamente,
Environment.UserInteractive
comprueba si elWSF_VISIBLE
indicador está configurado para la estación de ventana actual, pero ¿hay alguna otra razón por la que regresaríafalse
, además de ejecutarse como un servicio (no interactivo)?fuente
System.Diagnostics.Debugger.IsAttached
lugar de hacerloEnvironment.UserInteractive
.Cuando configuré un nuevo proyecto de servicio hace unas semanas, encontré esta publicación. Si bien hay muchas sugerencias geniales, todavía no encontré la solución que quería: la posibilidad de llamar a las clases
OnStart
yOnStop
métodos de servicio sin ninguna modificación a las clases de servicio.La solución que se me ocurrió utiliza el
Environment.Interactive
modo de ejecución selectivo, como lo sugieren otras respuestas a esta publicación.El
RunInteractive
ayudante usa la reflexión para llamar a los métodosOnStart
y protegidosOnStop
:Este es todo el código requerido, pero también escribí un tutorial con explicaciones.
fuente
walk through
) es asegurarme de que vaya a las propiedades del proyecto y cambie el tipo de salida aConsole Application
antes de intentar compilar y ejecutar. Encuéntralo enProject Properties -> Application -> Output type -> Console Application
. Además, para que esto funcione correctamente para mí, terminé teniendo que ejecutar la aplicación usando elstart
comando. Ej:C:\"my app name.exe" -service
no funcionaría para mí. En cambio, solíaC:\start /wait "" "my app name.exe" -service
A veces es importante analizar lo que sucede durante el inicio del servicio. Adjuntar al proceso no ayuda aquí, porque no es lo suficientemente rápido como para adjuntar el depurador mientras se inicia el servicio.
La respuesta corta es que estoy usando las siguientes 4 líneas de código para hacer esto:
Estos se insertan en el
OnStart
método del servicio de la siguiente manera:Para aquellos que no lo han hecho antes, he incluido consejos detallados a continuación , porque pueden atascarse fácilmente. Las siguientes sugerencias se refieren a Windows 7x64 y Visual Studio 2010 Team Edition , pero también deberían ser válidas para otros entornos.
Importante: Implemente el servicio en modo "manual" (utilizando la
InstallUtil
utilidad desde el símbolo del sistema VS o ejecute un proyecto de instalador de servicio que haya preparado). Abra Visual Studio antes de iniciar el servicio y cargue la solución que contiene el código fuente del servicio, configure puntos de interrupción adicionales según lo requiera en Visual Studio, luego inicie el servicio a través del Panel de control del servicio.Debido al
Debugger.Launch
código, esto generará un cuadro de diálogo "Se produjo una excepción no controlada de Microsoft .NET Framework en Servicename.exe ". a aparecer. Haga clic como se muestra en la captura de pantalla: Yes, debug Servicename.exePosteriormente, especialmente en Windows 7 UAC puede solicitarle que ingrese las credenciales de administrador. Ingrese y proceda con Yes:
Después de eso, aparece la conocida ventana del depurador Just-In-Time de Visual Studio . Le pregunta si desea depurar utilizando el depurador eliminado. Antes de hacer clic Yes, seleccione que no desea abrir una nueva instancia (segunda opción); una nueva instancia no sería útil aquí, porque el código fuente no se mostraría. Entonces, seleccione la instancia de Visual Studio que abrió anteriormente:
Después de hacer clic Yes, Visual Studio mostrará la flecha amarilla justo en la línea donde está la
Debugger.Launch
instrucción y podrá depurar su código (métodoMyInitOnStart
, que contiene su inicialización).Al presionar F5continúa la ejecución de inmediato, hasta que se alcanza el siguiente punto de interrupción que ha preparado.
Sugerencia: para mantener el servicio en funcionamiento, seleccione Depurar -> Separar todo . Esto le permite ejecutar un cliente que se comunica con el servicio después de que se haya iniciado correctamente y haya terminado de depurar el código de inicio. Si presiona Shift+F5 (detener la depuración), esto terminará el servicio. En lugar de hacer esto, debe usar el Panel de control de servicio para detenerlo.
Tenga en cuenta que
Si crea una versión, el código de depuración se elimina automáticamente y el servicio se ejecuta normalmente.
Estoy usando
Debugger.Launch()
, que inicia y adjunta un depurador . También lo probéDebugger.Break()
, lo que no funcionó , porque todavía no hay un depurador conectado al iniciar el servicio (causando el "Error 1067: El proceso finalizó inesperadamente" ).RequestAdditionalTime
establece un largo tiempo de espera para el inicio del servicio (se no retrasar el código en sí mismo, sino que continuará inmediatamente con laDebugger.Launch
declaración). De lo contrario, el tiempo de espera predeterminado para iniciar el servicio es demasiado corto y el servicio falla si no llamabase.Onstart(args)
lo suficientemente rápido desde el depurador. Prácticamente, un tiempo de espera de 10 minutos evita que vea el mensaje " el servicio no respondió ..." inmediatamente después de que se inicia el depurador.Una vez que te acostumbras, este método es muy fácil porque solo requiere que agregues 4 líneas a un código de servicio existente, lo que te permite obtener rápidamente control y depuración.
fuente
base.RequestAdditionalTime(600000)
evitará que el control del servicio termine el servicio durante 10 minutos si no llamabase.OnStart(args)
dentro de ese intervalo de tiempo). Aparte de eso, recuerdo que UAC también abortará si no ingresa las credenciales de administrador después de un tiempo (no sé cuántos segundos exactamente, pero creo que debe ingresarlo en un minuto, de lo contrario, UAC cancela) , que finalizará la sesión de depuración.Lo que generalmente hago es encapsular la lógica del servicio en una clase separada y comenzar eso desde una clase 'runner'. Esta clase de corredor puede ser el servicio real o simplemente una aplicación de consola. Entonces su solución tiene (al menos) 3 proyectos:
fuente
Este video de YouTube de Fabio Scopel explica cómo depurar un servicio de Windows bastante bien ... el método real de hacerlo comienza a las 4:45 en el video ...
Aquí está el código explicado en el video ... en su archivo Program.cs, agregue las cosas para la sección de Depuración ...
En su archivo Service1.cs, agregue el método OnDebug () ...
Básicamente, debe crear un
public void OnDebug()
que llame alOnStart(string[] args)
ya que está protegido y no es accesible desde el exterior. Elvoid Main()
programa se agrega con#if
preprocesador con#DEBUG
.Visual Studio define
DEBUG
si el proyecto se compila en modo de depuración. Esto permitirá que la sección de depuración (a continuación) se ejecute cuando la condición sea verdaderaY se ejecutará como una aplicación de consola, una vez que las cosas salgan bien, puede cambiar el modo
Release
y laelse
sección normal activará la lógicafuente
ACTUALIZAR
Este enfoque es, con mucho, el más fácil:
http://www.codeproject.com/KB/dotnet/DebugWinServices.aspx
Dejo mi respuesta original a continuación para la posteridad.
Mis servicios tienden a tener una clase que encapsula un temporizador, ya que quiero que el servicio verifique a intervalos regulares si hay algún trabajo que hacer.
Actualizamos la clase y llamamos a StartEventLoop () durante el inicio del servicio. (Esta clase también podría usarse fácilmente desde una aplicación de consola).
El agradable efecto secundario de este diseño es que los argumentos con los que configura el temporizador se pueden usar para tener un retraso antes de que el servicio realmente comience a funcionar, de modo que tenga tiempo para adjuntar un depurador manualmente.
También solía hacer lo siguiente (ya se mencionó en respuestas anteriores pero con los indicadores del compilador condicional [#if] para ayudar a evitar que se active en una versión de lanzamiento).
Dejé de hacerlo de esta manera porque a veces nos olvidamos de compilar en Release y tener una interrupción del depurador en una aplicación que se ejecuta en una demostración de cliente (¡vergonzoso!).
fuente
// do something
tarda más de 30 minutos en completarse?fuente
OnStart
esprotected
y no puedes modificar el nivel de acceso :(También puede iniciar el servicio a través del símbolo del sistema (sc.exe).
Personalmente, ejecutaría el código como un programa independiente en la fase de depuración, y cuando se solucionen la mayoría de los errores, cambiaría a ejecutar como servicio.
fuente
Lo que solía hacer era tener un interruptor de línea de comando que iniciara el programa como un servicio o como una aplicación normal. Luego, en mi IDE, configuraría el interruptor para poder pasar por mi código.
Con algunos idiomas, puede detectar si se está ejecutando en un IDE y realizar este cambio automáticamente.
Qué idioma estás usando?
fuente
Use la biblioteca TopShelf .
Cree una aplicación de consola y luego configure la configuración en su Main
Para depurar su servicio, simplemente presione F5 en Visual Studio.
Para instalar el servicio, escriba cmd "console.exe install"
Luego puede iniciar y detener el servicio en el administrador de servicios de Windows.
fuente
Creo que depende del sistema operativo que esté utilizando, Vista es mucho más difícil de conectar a los Servicios, debido a la separación entre sesiones.
Las dos opciones que he usado en el pasado son:
Espero que esto ayude.
fuente
Me gusta poder depurar todos los aspectos de mi servicio, incluida cualquier inicialización en OnStart (), mientras lo ejecuto con un comportamiento de servicio completo en el marco del SCM ... sin modo "consola" o "aplicación".
Hago esto creando un segundo servicio, en el mismo proyecto, para usar para la depuración. El servicio de depuración, cuando se inicia como de costumbre (es decir, en el complemento MMC de servicios), crea el proceso de host del servicio. Esto le proporciona un proceso para adjuntar el depurador a pesar de que aún no ha comenzado su servicio real. Después de adjuntar el depurador al proceso, inicie su servicio real y podrá acceder a él en cualquier parte del ciclo de vida del servicio, incluido OnStart ().
Debido a que requiere una intrusión de código muy mínima, el servicio de depuración se puede incluir fácilmente en su proyecto de configuración del servicio, y se elimina fácilmente de su versión de producción comentando una sola línea de código y eliminando un solo instalador del proyecto.
Detalles:
1) Suponiendo que está implementando
MyService
, también creeMyServiceDebug
. Agregue ambos a laServiceBase
matriz de la siguienteProgram.cs
manera:2) Agregue el servicio real Y el servicio de depuración al instalador del proyecto para el proyecto de servicio:
Ambos servicios (real y depuración) se incluyen cuando agrega la salida del proyecto de servicio al proyecto de configuración para el servicio. Después de la instalación, ambos servicios aparecerán en el complemento service.msc MMC.
3) Inicie el servicio de depuración en MMC.
4) En Visual Studio, adjunte el depurador al proceso iniciado por el servicio de depuración.
5) Inicie el servicio real y disfrute de la depuración.
fuente
Cuando escribo un servicio pongo toda la lógica del servicio en un proyecto dll y creo dos "hosts" que llaman a este dll, uno es un servicio de Windows y el otro es una aplicación de línea de comandos.
Utilizo la aplicación de línea de comandos para depurar y adjunto el depurador al servicio real solo para errores que no puedo reproducir en la aplicación de línea de comandos.
Si utiliza este enfoque, recuerde que debe probar todo el código mientras se ejecuta en un servicio real, mientras que la herramienta de línea de comandos es una buena ayuda para la depuración, es un entorno diferente y no se comporta exactamente como un servicio real.
fuente
Al desarrollar y depurar un servicio de Windows, normalmente lo ejecuto como una aplicación de consola agregando un parámetro de inicio / console y verificando esto. Hace la vida mucho más fácil.
fuente
¿Qué hay de Debugger.Break () en la primera línea?
fuente
Para depurar los servicios de Windows combino GFlags y un archivo .reg creado por regedit.
O guarde los siguientes fragmentos y reemplace servicename.exe con el nombre ejecutable deseado.
debugon.reg:
debugoff.reg:
fuente
Para la programación rutinaria de cosas pequeñas, he hecho un truco muy simple para depurar fácilmente mi servicio:
Al inicio del servicio, verifico si hay un parámetro de línea de comando "/ debug". Si se llama al servicio con este parámetro, no hago el inicio del servicio habitual, sino que inicio a todos los oyentes y solo visualizo un cuadro de mensaje "Depuración en progreso, presiono ok para finalizar".
Entonces, si mi servicio se inicia de la manera habitual, comenzará como servicio, si se inicia con el parámetro / depuración de la línea de comando, actuará como un programa normal.
En VS simplemente agregaré / depuraré como parámetro de depuración e iniciaré el programa de servicio directamente.
De esta manera, puedo depurar fácilmente la mayoría de los problemas pequeños. Por supuesto, algunas cosas aún deberán ser depuradas como servicio, pero para el 99% esto es lo suficientemente bueno.
fuente
fuente
Yo uso una variación en la respuesta de JOP. Con los parámetros de la línea de comandos, puede establecer el modo de depuración en el IDE con las propiedades del proyecto o mediante el administrador de servicios de Windows.
fuente
Para solucionar problemas en el programa de servicio de Windows existente, use 'Debugger.Break ()' como sugirieron otros chicos.
Para el nuevo programa de servicio de Windows, sugeriría utilizar el método de James Michael Hare http://geekswithblogs.net/BlackRabbitCoder/archive/2011/03/01/c-toolbox-debug-able-self-installable-windows-service-template- redux.aspx
fuente
Simplemente ponga su almuerzo de depuración en cualquier lugar y adjunte Visualstudio al inicio
También debe iniciar VS como Administatrator y debe permitir que un usuario diferente pueda depurar un proceso (como se explica aquí ):
fuente
Use el proyecto de plantilla de servicio de Windows C # para crear una nueva aplicación de servicio https://github.com/HarpyWar/windows-service-template
Hay modo de consola / servicio detectado automáticamente, instalador automático / desinstalador de su servicio y se incluyen varias de las funciones más utilizadas.
fuente
Aquí está el método simple que utilicé para probar el servicio, sin ningún método adicional de "depuración" y con pruebas de unidad VS integradas.
fuente
fuente
Tienes dos opciones para hacer la depuración.
Consulte ESTA publicación de blog que creé para el tema.
fuente
Solo pegar
en cualquier parte de tu código.
Por ejemplo ,
Golpeará
Debugger.Break();
cuando ejecutes tu programa.fuente
La mejor opción es usar el espacio de nombres ' System.Diagnostics '.
Incluya su código en el bloque if if para el modo de depuración y el modo de liberación como se muestra a continuación para cambiar entre el modo de depuración y liberación en Visual Studio,
fuente