visual studio start servicio puede net linea instalar instalador iniciar desde depurar depurador debuggear crear comandos c# c++ debugging windows-services

c# - studio - ¿Cómo se depura un servicio de Windows?



no se puede iniciar un servicio desde la linea de comandos o un depurador net start (15)

Leí el artículo de MSDN sobre el tema. Citar:

Como un servicio se debe ejecutar desde el contexto del Administrador de control de servicios en lugar de desde Visual Studio, la depuración de un servicio no es tan sencilla como la depuración de otros tipos de aplicaciones de Visual Studio. Para depurar un servicio, debe iniciar el servicio y luego adjuntar un depurador al proceso en el que se está ejecutando. Luego puede depurar su aplicación usando todas las funciones de depuración estándar de Visual Studio.

Ahora mi problema es que mi servicio no se inicia en primer lugar. Primero se cuelga y dice:

Se produjo una excepción no controlada (System.Runtime.InteropServices.COMException) en MyServiceName.exe [3596])

y me sugiere que lo depure (la instancia del depurador se bloquea al instante cuando elijo uno). Entonces dice

No se pudo iniciar el servicio MyServiceName en la computadora local. Error 1053: el servicio no respondió a la solicitud de inicio o control de manera oportuna

Entonces, ¿cómo puedo investigar / depurar el motivo por el que mi servicio no se iniciará? El caso es que creé una aplicación de consola que hace EXACTAMENTE lo que hace el servicio y funciona bien. (Quiero decir que acabo de copiar el método OnStart () y el contenido del ciclo principal a main).

Cualquier ayuda sería apreciada.

El servicio está escrito en C # con un uso intensivo de interoperabilidad. Estoy usando VS2008


Agregue muchos registros detallados en su OnStart. Es doloroso y vieja escuela, pero funciona.


Consulte esta pregunta , que trata sobre cómo detectar excepciones no controladas en un servicio de ventana.


La depuración de servicios es un problema, especialmente desde el inicio parece ser cuando muchos de los problemas se manifiestan (al menos para nosotros).

Lo que normalmente hacemos es extraer tanta lógica como sea posible a una clase única que tiene métodos de inicio y detención. Esos métodos de clase son todo lo que el servicio llama directamente. Luego creamos una aplicación WinForm que tiene dos botones: uno para invocar inicio, otro para invocar detener. A continuación, podemos ejecutar esta aplicación WinForm directamente desde el depurador y ver qué está sucediendo.

No es la solución más elegante, pero funciona para nosotros.


Le robé esto a C. Lawrence Wenham, así que realmente no puedo atribuirme el mérito, pero puede conectar mediante programación un depurador a un servicio, SIN interrumpir la ejecución en ese momento, con el siguiente código:

System.Diagnostics.Debugger.Launch();

Coloque esto en el método OnStart () de su servicio, como la primera línea, y le pedirá que elija una instancia de VS para adjuntar su depurador. A partir de ahí, el sistema se detendrá en los puntos de interrupción que establezca y en las excepciones descartadas. #if DEBUG una cláusula #if DEBUG alrededor del código para que una versión de lanzamiento no lo incluya; o puedes quitarlo después de que encuentres el problema.


Lo que hice fue implementado por OnStart () para que se vea así:

_myBusinessObject = new MyBusinessObject();

Después de que se ha construido el objeto comercial, los temporizadores y los manejadores de IPC realizan todo el trabajo real (de servicio).

Hacerlo de esta manera le permite crear una aplicación Forms / WPF que llame al mismo código anterior en el controlador Form_Loaded. De esta manera, la depuración de la aplicación Forms es exactamente lo mismo que la depuración del Servicio.

El único problema es que si está utilizando los valores de app.config, habrá un segundo archivo app.config que deberá mantenerse actualizado.


Para adjuntar un depurador al Servicio de Windows, primero debe iniciarse. La razón por la cual el servicio no pudo iniciarse puede verificarse en el Registro de eventos de Windows.

Después de eso, el proceso de adjuntar un depurador es bastante directo desde Visual Studio Debug-> Attach To Process.


Parece que el problema es con el contexto del usuario. Permítanme confirmar si mis suposiciones son correctas.

  1. Cuando dice que el código funciona perfectamente desde la aplicación de la consola, asumo que está ejecutando la aplicación de la Consola bajo el mismo usuario que había iniciado sesión.

  2. Cuando dice que el mismo código falla mientras se llama desde el servicio de Windows, asumo que el servicio se está ejecutando en la cuenta "Sistema local" en su máquina de desarrollo.

Si mis dos suposiciones son correctas, pruebe los siguientes pasos.

  1. En la lista de servicios, haga clic derecho en su servicio, seleccione propiedades y luego la pestaña "Iniciar sesión".

  2. Seleccione la opción "Esta cuenta" y proporcione el nombre de usuario y la contraseña existentes.

  3. Ahora intenta comenzar el servicio. Ahora debería comenzar sin ningún error.

Lo siguiente podría ser la causa raíz de su error

  1. Si está utilizando SQL Server, asegúrese de no estar utilizando la autenticación SSPI.

  2. Si está intentando leer cualquier carpeta compartida / recurso que no tiene permiso cuando usa la cuenta "sistema local".

  3. Si alguna de las dependencias requeridas por la aplicación se encuentra en una carpeta diferente a la que el usuario del "Sistema local" no tiene permiso de acceso.

  4. Si está utilizando la automatización VBA que no funcionará en la cuenta "Sistema local".

  5. Intenta deshabilitar tu firewall o antivirus.


Por lo general, solo configuro manualmente un punto de interrupción, luego lo señalo al proyecto actualmente abierto en c #. El código para establecer un punto de interrupción es:

System.Diagnostics.Debugger.Break();

Eso debería hacerte comenzar, luego puedes pasar por tu código y ver qué está pasando realmente.


Puede agregar un registro de las llamadas de interoperabilidad para averiguar cuál falla.

Además, los servicios por defecto no están asociados con un escritorio; si abre el applet del panel de control services.msc, obtenga las propiedades de su servicio, vaya a la pestaña "Iniciar sesión", puede marcar "Permitir que el servicio interactúe con el escritorio". Esto podría solucionar el problema en algunos casos.


Puede usar WinDbg / NTSD (otro depurador del paquete "Herramientas de depuración para Windows") para iniciar un depurador junto con su servicio.

Para hacerlo, abra "gflags" (también disponible en el paquete mencionado anteriormente) en la pestaña "Archivo de imagen" y establezca la ruta al archivo ejecutable del depurador para su archivo de imagen (servicio);

Si su servicio está marcado como interactivo (solo es posible si se ejecuta bajo la cuenta SYSTEM) puede iniciar WinDbg directamente, simplemente configure el depurador en algo así como "PATH_TO_WINDBG / windbg.exe -g -G" (los -g / -G son necesario para que el depurador no rompa la ejecución al inicio o al final de la aplicación, el comportamiento predeterminado). Ahora, cuando inicie su servicio, la ventana de Windbg debería aparecer y capturará cualquier excepción no controlada.

Si su servicio no es interactivo, puede iniciar el depurador NTSD (un depurador de línea de comandos) en modo remoto y conectarse a él desde WinDbg (que incluso puede ejecutarse en otra PC). Para hacer esto, establezca el depurador en gflags en algo como "PATH_TO_NTSD / ntsd -remote tcp: port = 6666, server = localhost" . Luego, conéctese al depurador remoto iniciando windbg con algo como "windbg -remote tcp: port = 6666, server = localhost" y debería tener control completo sobre la otra sesión de depuración.

En cuanto a encontrar el origen de la excepción en sí, un tutorial windbg trata sobre el tema aquí pero, como inicio, intente ejecutar el comando "! Analyze -v" después de capturar la excepción. Con un poco de suerte, esta es toda la información que necesitará. .

Nota: tal vez esto sea excesivo para su caso, pero con este enfoque incluso puede depurar servicios durante el inicio del sistema (una vez tuve un problema de temporización con un servicio que solo tenía un problema al iniciar la primera vez con el sistema)


Puede usar un parámetro para que su aplicación decida si comenzar como servicio o aplicación regular (es decir, en este caso, mostrar un Formulario o iniciar el servicio):

static void Main(string[] args) { if ((1 == args.Length) && ("-runAsApp" == args[0])) { Application.Run(new application_form()); } else { System.ServiceProcess.ServiceBase[] ServicesToRun; ServicesToRun = new ServiceBase[] { new MyService() }; System.ServiceProcess.ServiceBase.Run(ServicesToRun); } }

Ahora, si pasa el parámetro "-runAsApp", puede depurar la aplicación normalmente, el SCM no pasará este parámetro, por lo que también puede usarlo como servicio sin cambio de código (siempre que ServiceBase de ServiceBase )

Editar:

La otra diferencia con los servicios de Windows es la identidad (esto puede ser especialmente importante con InterOp): quiere asegurarse de que está probando con la misma identidad en el modo "aplicación" y en el modo de servicio.

Para hacerlo, puede usar suplantación (puedo publicar un contenedor C # si ayuda, pero esto se puede buscar fácilmente en Google) en el modo de aplicación para usar la misma identidad con la que se ejecutará el servicio de Windows, es decir, normalmente Servicio local o Servicio de red.

Si se requiere otra identidad, puede agregar configuraciones al app.config que le permita decidir si usar credenciales, y si es el mismo usuario a suplantar, estas configuraciones estarían activas cuando se ejecuta como una aplicación, pero se apaga para el servicio de Windows ( ya que el servicio ya se está ejecutando con la identidad deseada):

<appSettings> <add key="useCredentials" value="false"/> <add key="user" value="Foo"/> <add key="password" value="Bar"/> </appSettings>


Supongo que la razón podría estar causando debido al uso intensivo de interoperabilidad. Entonces debes abordar este problema de manera diferente. Sugeriría crear una aplicación de Windows o consola con la misma lógica de tu servicio y asegurarte de que funciona primero sin ningún problema, y ​​luego puedes ir con la creación del servicio de Win.


Una cosa que hago (que puede ser una especie de truco) es poner un Thread.Sleep(10000) justo al comienzo de mi método OnStart() . Esto me da una ventana de 10 segundos para adjuntar mi depurador al servicio antes de que haga algo más.

Por supuesto, Thread.Sleep() sentencia Thread.Sleep() cuando terminé de depurar.

Otra cosa que puede hacer es lo siguiente:

public override void OnStart() { try { // all your OnStart() logic here } catch(Exception ex) { // Log ex.Message if (!EventLog.SourceExists("MyApplication")) EventLog.CreateEventSource("MyApplication", "Application"); EventLog.WriteEntry("MyApplication", "Failed to start: " + ex.Message); throw; } }

Cuando registra ex.Message , puede obtener un mensaje de error más detallado. Además, puede simplemente registrar ex.ToString() para obtener el seguimiento completo de la pila, y si sus archivos .pdb están en el mismo directorio que su ejecutable, incluso le indicará en qué línea se produjo la excepción.


Use el siguiente código en el método Service OnStart:

System.Diagnostics.Debugger.Launch();

Elija la opción de Visual Studio desde el mensaje emergente