2009-07-28 31 views
48

Tengo un código escrito en .NET que solo falla cuando se instala como un servicio de Windows. La falla no permite que el servicio siquiera comience. No puedo entender cómo puedo entrar en el método OnStart.¿Cómo se puede depurar el método .NET Windows Service OnStart?

How to: Debug Windows Service Applications da una pista tentadora:

Colocación en el proceso del servicio permite depurar la mayoría, pero no todos del código del servicio; por ejemplo, debido a que el servicio ya se ha iniciado, no puede depurar el código en el método OnStart del servicio de esta manera, o el código en el método Principal que se utiliza para cargar el servicio. Una forma de evitar esto es crear un segundo servicio temporal en su aplicación de servicio que existe solo para ayudar en la depuración. Puede instalar ambos servicios y luego iniciar este servicio "ficticio" para cargar el proceso del servicio. Una vez que el servicio temporal haya comenzado el proceso, puede usar el menú Depurar en Visual Studio para adjuntarlo al proceso del servicio.

Sin embargo, no estoy seguro de cómo se supone que debe crear el servicio ficticio para cargar el proceso del servicio.

+0

Esto es un duplicado exacto. No puedo encontrar el original ahora. La respuesta fue la misma. – leppie

Respuesta

85

Una cosa que podría hacer como una solución temporal es poner en marcha el depurador como la primera línea de código en el OnStart

System.Diagnostics.Debugger.Launch() 

Esto le pedirá el depurador desea utilizar. Simplemente tenga la solución ya abierta en Visual Studio y elija esa instancia de la lista.

+0

Esto no funciona para mí. El error que recibo es excepción no controlada en 0x7c812aeb en xxxxService.exe: 0xC06D007E: No se encuentra el módulo y nunca se alcanzan los puntos de interrupción. Sin embargo, esto es bastante diferente del error que obtengo sin el depurador. Código de inicio incluido. – Nathan

+0

¿Tiene instalado Visual Studio en la máquina donde se está ejecutando el servicio? – palehorse

+0

Sí, tengo instalados Visual Studio 2005 Professional y Visual Studio 2008 Professional en la máquina. – Nathan

0

Trate de añadir Debugger.Break dentro del método problemático. Cuando el servicio comience, se lanzará una excepción y las viudas deberían ofrecerle depuración usando Visual Studio.

9

que tienden a añadir un método como este:

[Conditional("DEBUG")] 
    private void AttachDebugger() 
    { 
     Debugger.Break(); 
    } 

sólo se llamará en versiones de depuración de proyectar y va a hacer una pausa en la ejecución y permitirá conectar el depurador.

0

Normalmente tengo una aplicación de consola que pretende ser SCM, p. llama a Start, Stop para que yo solo pueda F5 en mis principales propósitos de codificación/depuración, y use Debugger.Break para la depuración cuando el servicio ha sido instalado e iniciado a través de SCM.

Significa un poco más de trabajo para empezar, tengo una lib de clase que contiene todo el código de servicio, con una clase que expone Start and Stop que la clase de servicio de Windows y la aplicación de consola pueden llamar.

Mate

6

Funciona bien!

protected override void OnStart(string[] args) 
{ 
    System.Diagnostics.Debugger.Launch(); 
} 
+0

agrego este código como dijiste en OnStart, pero cuando todavía no puedo depurar mi servicio, estoy usando VS 2013, ¿me puedes ayudar? – pejman

5

las opciones anteriores no parecen funcionar en Windows 8.

He añadido Thread.Sleep (15000); en mi método OnStart() y establecer un punto de interrupción en la siguiente línea del código. Esto me da 15 segundos para adjuntar depurador VS a mi proceso después de iniciar el servicio y me permitió depurar el método OnStart() muy bien.

+1

Mismo: adjuntar el depurador programáticamente en Windows 8 no parece funcionar:/ –

+0

en Windows 8.1 sí. Visual Studio 2013 Professional – LuckyLikey

1

Sé que es tarde, pero esta es la forma en que manejamos debuging servicios de Windows

En primer lugar crear una clase que actuará como el servicio.

Añadir los métodos apropiados para iniciar, detener, hacer una pausa, etc ...

Añadir una forma ventanas para el proyecto de servicio.

En el código de servicio crear la clase de servicio creada anteriormente y crea las llamadas necesarias para iniciar y detener el servicio en la clase ServiceBase

Abiertas las Program.cs y agregue el siguiente

#if DEBUG 
    [STAThread] 
#endif 
    static void Main() 
    { 
try 
     { 
#if DEBUG 
      Application.EnableVisualStyles(); 
      Application.SetCompatibleTextRenderingDefault(false); 
      Application.Run(new DebugForm()); 
#else 
      ServiceBase[] ServicesToRun; 
      ServicesToRun = new ServiceBase[] 
     { 
      new YourWindowsService() 
     }; 
      ServiceBase.Run(ServicesToRun); 
#endif 
     } 
     catch (Exception e) 
     { 
      logger.Error(DateTime.Now.ToString() + " - " + e.Source + " - " + e.ToString() + "\r\n------------------------------------\r\n"); 
     } 
} 

Cuando se ejecuta en modo DEBUG el formulario de Windows se iniciará. Solo recuerde construir en modo Release cuando termine. Por supuesto, la variable de compilación condicional puede ser lo que quieras. Incluso podría crear proyectos separados, por lo que el formulario de depuración es su propio proyecto.

Esperanza esto ayuda

1

También puede intentar System.Diagnostics.Debugger.Launch() método. Ayuda a tomar el puntero del depurador a la ubicación especificada y luego puede depurar el código.

Antes de este paso instale su service.exe usando la línea de comandos del símbolo del sistema de Visual Studio - installutil projectservice.exe

continuación, iniciar su servicio desde el panel de control -> Herramientas administrativas -> Administración de equipos -> Servicio y Aplicación -> Servicios -> Su nombre Servicio

7

Una vez que tenga un servicio que se instala usando installutil.exe, puede alterar la Start Parameters saltar al depurador si se inicia el servicio:

enter image description here

al iniciar el servicio manualmente con el parámetro -debugWithVisualStudio (o simplemente -d), detectará automáticamente el proyecto correcto, y el fuego de la depurador interactivo en Visual Studio:

enter image description here

Para apoyar esta funcionalidad, cambie OnStart() función del servicio:

/// <summary> 
///  Executed when the service is started. 
/// </summary> 
/// <param name="args">Command line arguments.</param> 
protected override void OnStart(string[] args) 
{ 
    try 
    { 
     //How to debug when running a Windows Service: 
     // 1. Right click on the service name in Windows Service Manager. 
     // 2. Select "Properties". 
     // 3. In "Start Parameters", enter "-d" (or "-debugWithVisualStudio"). 
     // 4. Now, when you start the service, it will fire up Visual Studio 2012 and break on the line below. 
     // 5. Make sure you have UAC (User Access Control) turned off, and have Administrator privileges. 
#if DEBUG 
     if (((ICollection<string>)args).Contains("-d") 
      || ((ICollection<string>)args).Contains("-debugWithVisualStudio")) 
     { 
      Debugger.Launch(); // Launches VS2012 debugger. 
     } 
#endif 
     ShellStart(args); 
     base.OnStart(args); 
    } 
    catch (Exception ex) 
    { 
     // Log exception here. 
    } 
} 

(opcional) Si desea reducir a la línea exacta de código donde el servicio arroja un error, active las excepciones del menú de Visual Studio DEBUG .. Exceptions. Cuando continúe depurando, se romperá en la línea exacta que arroja la excepción.

enter image description here

+0

Me encanta la idea de la línea de comando, voy a empezar a usar esto. Su condición de verificar si contiene args ("- d") debería ser suficiente para ambas comprobaciones ya que [-d] ebugWithVisualStudio contiene "-d", por lo que el OR en su condición no es necesario. ¡Gracias! –

+0

@ Adam Está en lo correcto, el código podría optimizarse eliminando la línea "-debugWithVisualStudio". Sin embargo, el propósito de esta línea es la claridad del código, por lo que la intención del código queda inmediatamente clara para cualquier otro programador. Normalmente agrego dos versiones de todos los parámetros de la línea de comandos: una versión corta y una versión detallada que explica exactamente lo que hace. – Contango

+0

@ Adam Plocher Creo que la llamada a Contains() en la colección está buscando si la colección contiene esas cadenas exactas. –

0

Si agrega Debugger.Launch() en el método de OnStart y no funciona, usted podría tener el mismo problema que tuve, a saber, la excepción se estaba produciendo en el constructor por lo que el era OnStart nunca llamado. (Slap cabeza)

(lo siento si esto debería haber sido un comentario en respuesta a alguien otra cosa', pero no tienen suficiente credibilidad para hacer comentarios)

0

Antes de entrar en el tema de un consejo. Utilice siempre el registro especialmente si es desarrollador del lado del servidor. Debido a que hay ciertas condiciones que no podrá producir al depurar el código en Visual Studio.

Volviendo al tema, utilizar el indicador de Envoirnment.UserInteractive esto es muy útil ver a mi código de abajo

public static void Main(string[] args) 
{ 

    if (System.Environment.UserInteractive) 
    { 
     string parameter = string.Concat(args); 

     switch (parameter) 
     { 
      case "--install": 
       ManagedInstallerClass.InstallHelper(new string[] { Assembly.GetExecutingAssembly().Location }); 
       break; 
      case "--uninstall": 
       ManagedInstallerClass.InstallHelper(new string[] { "/u", Assembly.GetExecutingAssembly().Location }); 
       break; 
      default: 
       WindowsService service = new WindowsService(); 
       service.OnStart(args); 
       Console.ReadKey(); 
       service.OnStop(); 
       break; 
     } 
    } 
    else 
    { 
     ServiceBase.Run(new WindowsService()); 
    } 
} 

De Visual Studio que se consigue el indicador UserInteractive establecer lo que voy a ejecutar como aplicación de consola, además incluso si puede ejecutar la creación del producto haciendo doble clic en él y adjuntando el depurador si desea probarlo.

1

Uso siguiente Código de Servicio OnStart Método:

System.Diagnostics.Debugger.Launch(); 

Elija la opción Visual Studio de mensaje emergente. Recuerde ejecutar Visual Studio como administrador.

Nota: Para usarlo solo en el modo de depuración, se puede usar la directiva #if DEBUG compiler, de la siguiente manera. Esto evitará errores accidentales o depuración en el modo de lanzamiento en el servidor de producción.

#if DEBUG 
    System.Diagnostics.Debugger.Launch(); 
#endif 
2

Como otros han señalado, hay que añadir un salto de depurador al OnStart-Método:

#if DEBUG 
    System.Diagnostics.Debugger.Break() 
#endif 

también comienzan VisualStudio como administrador y permitir, que un proceso de forma automática se puede depurar por una diverso usuario (como se explica here):

reg add "HKCR\AppID\{E62A7A31-6025-408E-87F6-81AEB0DC9347}" /v AppIDFlags /t REG_DWORD /d 8 /f 

(que también se explica esto aquí: https://stackoverflow.com/a/35715389/5132456)

0

que tienen una forma interesante de hacer esto añado otra configuración llamado DebugNoService

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugNoService|AnyCPU' "> 
    <OutputPath>.\</OutputPath> 
    <AllowUnsafeBlocks>false</AllowUnsafeBlocks> 
    <BaseAddress>285212672</BaseAddress> 
    <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow> 
    <ConfigurationOverrideFile> 
    </ConfigurationOverrideFile> 
    <DefineConstants>DEBUG;TRACE;DEBUGNOSERVICE</DefineConstants> 
    <DocumentationFile> 
    </DocumentationFile> 
    <DebugSymbols>true</DebugSymbols> 
    <FileAlignment>4096</FileAlignment> 
    <NoStdLib>false</NoStdLib> 
    <NoWarn> 
    </NoWarn> 
    <Optimize>false</Optimize> 
    <RegisterForComInterop>false</RegisterForComInterop> 
    <RemoveIntegerChecks>false</RemoveIntegerChecks> 
    <TreatWarningsAsErrors>false</TreatWarningsAsErrors> 
    <WarningLevel>4</WarningLevel> 
    <DebugType>full</DebugType> 
    <ErrorReport>prompt</ErrorReport> 
    <UseVSHostingProcess>false</UseVSHostingProcess> 
    </PropertyGroup> 

utilizo la directiva #if. ProjectInstaller.cs

#if !DEBUGNOSERVICE  
    static void Main() 
    { 
     System.ServiceProcess.ServiceBase[] ServicesToRun; 
     ..... 
    } 
#endif 

añado una forma ventanas y también envuelven la forma ventanas en

#if DEBUGNOSERVICE 
... 
static void Main() 
{ 
    Form  form; 

    Application.EnableVisualStyles(); 
    Application.DoEvents(); 

    form = new <the name of the form>(); 

    Application.Run(form); 
} 
... 
#endif 

dependiendo de la configuración seleccionada o bien el código se ejecuta como una aplicación de Windows Forms que puede ser fácilmente eliminado errores o como un servicio.

Parece mucho trabajo pero siempre ha funcionado y hace que depurar el código sea muy fácil. Puede agregar todo tipo de resultados al formulario para que pueda verlo funcionar.

Cuestiones relacionadas