Una manera más fácil de depurar un servicio de Windows


¿Hay una forma más fácil de pasar por el código que iniciar el servicio a través del Administrador de Control de Servicio de Windows y luego adjuntar el depurador al subproceso? Es un poco engorroso y me pregunto si hay un enfoque más sencillo.

Author: Matthias, 2008-09-24

29 answers

Si quiero depurar rápidamente el servicio, simplemente coloco un Debugger.Break() allí. Cuando se alcance esa línea, me dejará de nuevo en VS. No te olvides de quitar esa línea cuando hayas terminado.

ACTUALIZAR: Como alternativa a #if DEBUG pragmas, también puede usar el atributo Conditional("DEBUG_SERVICE").

[Conditional("DEBUG_SERVICE")]
private static void DebugMode()
{
    Debugger.Break();
}

En su OnStart, simplemente llame a este método:

public override void OnStart()
{
     DebugMode();
     /* ... do the rest */
}

Allí, el código solo se habilitará durante las compilaciones de depuración. Mientras estás en ello, podría ser útil crear una configuración de compilación separada para la depuración del servicio.

 259
Author: jop,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-14 04:16:48

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 comandos separado para ese propósito?

¿No podrías simplemente hacer:

public static int Main(string[] args)
{
  if (!Environment.UserInteractive)
  {
    // Startup as service.
  }
  else
  {
    // Startup as application
  }
}

Que tendría el "beneficio", que solo puede iniciar su aplicación a través de doubleclick (OK, si realmente lo necesita) y que solo puede golpear F5 en Visual Studio (sin la necesidad de modificar la configuración del proyecto para incluir que /console Opcion).

Técnicamente, el Environment.UserInteractive comprueba si el indicador WSF_VISIBLE está establecido para la estación de ventana actual, pero ¿hay alguna otra razón por la que regresaría false, aparte de ser ejecutado como un servicio (no interactivo)?

 206
Author: Christian.K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-07 06:57:23

Cuando configuré un nuevo proyecto de servicio hace unas semanas encontré este post. Si bien hay muchas sugerencias geniales, todavía no encontré la solución que quería: La posibilidad de llamar a los métodos OnStart y OnStop de las clases de servicio sin ninguna modificación a las clases de servicio.

La solución que se me ocurrió utiliza el Environment.Interactive el modo select running, como sugieren otras respuestas a este post.

static void Main()
{
    ServiceBase[] servicesToRun;
    servicesToRun = new ServiceBase[] 
    {
        new MyService()
    };
    if (Environment.UserInteractive)
    {
        RunInteractive(servicesToRun);
    }
    else
    {
        ServiceBase.Run(servicesToRun);
    }
}

El ayudante RunInteractive usa la reflexión para llamar a los protegidos OnStart y OnStop métodos:

static void RunInteractive(ServiceBase[] servicesToRun)
{
    Console.WriteLine("Services running in interactive mode.");
    Console.WriteLine();

    MethodInfo onStartMethod = typeof(ServiceBase).GetMethod("OnStart", 
        BindingFlags.Instance | BindingFlags.NonPublic);
    foreach (ServiceBase service in servicesToRun)
    {
        Console.Write("Starting {0}...", service.ServiceName);
        onStartMethod.Invoke(service, new object[] { new string[] { } });
        Console.Write("Started");
    }

    Console.WriteLine();
    Console.WriteLine();
    Console.WriteLine(
        "Press any key to stop the services and end the process...");
    Console.ReadKey();
    Console.WriteLine();

    MethodInfo onStopMethod = typeof(ServiceBase).GetMethod("OnStop", 
        BindingFlags.Instance | BindingFlags.NonPublic);
    foreach (ServiceBase service in servicesToRun)
    {
        Console.Write("Stopping {0}...", service.ServiceName);
        onStopMethod.Invoke(service, null);
        Console.WriteLine("Stopped");
    }

    Console.WriteLine("All services stopped.");
    // Keep the console alive for a second to allow the user to see the message.
    Thread.Sleep(1000);
}

Este es todo el código requerido, pero también escribí tutorial con explicaciones.

 114
Author: Anders Abel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-31 17:12:43

Lo que normalmente hago es encapsular la lógica del servicio en una clase separada y comenzar desde una clase 'runner'. Esta clase runner puede ser el servicio real o simplemente una aplicación de consola. Así que su solución tiene (al menos) 3 proyectos:

/ConsoleRunner
   /....
/ServiceRunner
   /....
/ApplicationLogic
   /....
 40
Author: Paul van Brenk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-24 08:14:07

A veces es importante analizar lo que está pasando durante la puesta en marcha del servicio. Adjuntar al proceso no ayuda aquí, porque no es lo suficientemente rápido para adjuntar el depurador mientras el servicio se está iniciando.

La respuesta corta es, estoy usando las siguientes 4 líneas de código para hacer esto:

#if DEBUG
    base.RequestAdditionalTime(600000); // 600*1000ms = 10 minutes timeout
    Debugger.Launch(); // launch and attach debugger
#endif

Se insertan en el método OnStart del servicio de la siguiente manera:

protected override void OnStart(string[] args)
{
    #if DEBUG
       base.RequestAdditionalTime(600000); // 10 minutes timeout for startup
       Debugger.Launch(); // launch and attach debugger
    #endif
    MyInitOnstart(); // my individual initialization code for the service
    // allow the base class to perform any work it needs to do
    base.OnStart(args);
}

Para aquellos que no lo han hecho antes, tengo incluido consejos detallados a continuación, porque puede quedarse atascado 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" (usando la utilidad InstallUtil desde el símbolo del sistema VS o ejecute un proyecto de instalador de servicios 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 los necesite en Visual Studio - luego inicie el servicio a través del Panel de control del servicio .

Debido al código Debugger.Launch, esto causará un diálogo "Una excepción de Microsoft.NET Framework no controlada ocurrió en Servicename.exe ." aparecer. Haga clic en Elevar Sí, depuración Servicename.exe como se muestra en la captura de pantalla:
Excepción del marco

Después, especialmente en Windows 7 UAC podría pedirle que introduzca las credenciales de administrador. Entrar en ellos y proceder con :

UACPrompt

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 en Yes, seleccione que no desea abrir una nueva instancia (2a opción) - una nueva instancia no sería útil aquí, porque el código fuente no se mostraría. Por lo tanto, seleccione la instancia de Visual Studio que abrió anteriormente: VSDebuggerPrompt

Después de hacer clic en Yes, después de un tiempo Visual Studio mostrará la flecha amarilla a la derecha en la línea donde está la instrucción Debugger.Launch y podrá depurar su código (método MyInitOnStart, que contiene su inicialización). VSDebuggerBreakpoint

Presionando F5 continúa la ejecución inmediatamente, hasta el siguiente punto de interrupción que tenga preparado se alcanza.

Sugerencia: Para mantener el servicio en funcionamiento, seleccione Debug -> Detach all. Esto le permite ejecutar un cliente que se comunica con el servicio después de que se inicie correctamente y haya terminado de depurar el código de inicio. Si presionas Shift+F5 (detener depuración), esto terminará el servicio. En lugar de hacer esto, debe usar el Panel de Control de Servicio para detenerlo.

Obsérvese que

  • Si compila una Versión, el código de depuración se elimina automáticamente y el servicio se ejecuta normalmente.

  • Yo he utilizado Debugger.Launch(), que inicia y adjunta un depurador. He probado Debugger.Break() también, que no funcionó, porque todavía no hay ningún depurador conectado al inicio del servicio (causando el error "1067: El proceso terminó inesperadamente.").

  • RequestAdditionalTime conjuntos a tiempo de espera más largo para el inicio del servicio (no está retrasando el código en sí, sino que continuará inmediatamente con la instrucción Debugger.Launch). De lo contrario, el tiempo de espera predeterminado para iniciar el servicio es demasiado corto y el inicio del servicio falla si no llama a base.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 iniciar el depurador.

  • Una Vez que te acostumbras para ello, este método es muy fácil porque solo requiere que agregue 4 líneas a un código de servicio existente, lo que le permite obtener rápidamente el control y la depuración.

 38
Author: Matt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-30 16:42:14

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 tu Programa.archivo CS, añadir las cosas para la sección de depuración...

namespace YourNamespace
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main()
        {
#if DEBUG
            Service1 myService = new Service1();
            myService.OnDebug();
            System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
#else
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[]
            {
                new Service1()
            };
            ServiceBase.Run(ServicesToRun);
#endif

        }
    }
}

En su Service1.cs file, añade el método OnDebug ()...

    public Service1()
    {
        InitializeComponent();
    }

    public void OnDebug()
    {
        OnStart(null);
    }

    protected override void OnStart(string[] args)
    {
        // your code to do something
    }

    protected override void OnStop()
    {
    }
 22
Author: Jason Miller,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-11 02:16:25

UPDATE

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.

Creamos una nueva clase y llamamos a StartEventLoop() durante el inicio del servicio. (Esta clase podría ser fácilmente también se usa desde una aplicación de consola.)

El efecto secundario agradable 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.

P. s. Cómo adjuntar el depurador manualmente a un proceso en ejecución...?

using System;
using System.Threading;
using System.Configuration;    

public class ServiceEventHandler
{
    Timer _timer;
    public ServiceEventHandler()
    {
        // get configuration etc.
        _timer = new Timer(
            new TimerCallback(EventTimerCallback)
            , null
            , Timeout.Infinite
            , Timeout.Infinite);
    }

    private void EventTimerCallback(object state)
    {
        // do something
    }

    public void StartEventLoop()
    {
        // wait a minute, then run every 30 minutes
        _timer.Change(TimeSpan.Parse("00:01:00"), TimeSpan.Parse("00:30:00");
    }
}

También solía hacer lo siguiente (ya mencionado en respuestas anteriores, pero con el compilador condicional [#if] banderas para ayuda a evitar que se dispare en una versión de lanzamiento).

Dejé de hacerlo de esta manera porque a veces nos olvidamos de construir en la liberación y tener un descanso depurador en una aplicación que se ejecuta en una demostración de cliente (vergonzoso!).

#if DEBUG
if (!System.Diagnostics.Debugger.IsAttached)
{
    System.Diagnostics.Debugger.Break();
}
#endif
 14
Author: rohancragg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-20 14:20:03

static void Main()
{
#if DEBUG
                // Run as interactive exe in debug mode to allow easy
                // debugging.

                var service = new MyService();
                service.OnStart(null);

                // Sleep the main thread indefinitely while the service code
                // runs in .OnStart

                Thread.Sleep(Timeout.Infinite);
#else
                // Run normally as service in release mode.

                ServiceBase[] ServicesToRun;
                ServicesToRun = new ServiceBase[]{ new MyService() };
                ServiceBase.Run(ServicesToRun);
#endif
}
 13
Author: Thomas Bratt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-29 21:43:46

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 la mayoría de los errores se resuelvan, cambiaría a ejecutar como servicio.

 10
Author: akauppi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-24 08:13:20

Lo que solía hacer era tener un interruptor de línea de comandos que iniciaría el programa ya sea como un servicio o como una aplicación regular. Luego, en mi IDE configuraría el interruptor para que pudiera pasar por mi código.

Con algunos lenguajes se puede detectar si se está ejecutando en un IDE, y realizar este cambio automáticamente.

¿Qué idioma está utilizando?

 10
Author: RB.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-24 08:13:57

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:

  • Use GFlags (en las Herramientas de depuración para Windows) para configurar un depurador permanente para un proceso. Esto existe en la clave de registro "Opciones de ejecución de archivos de imagen" y es increíblemente útil. Creo que tendrá que ajustar la configuración del servicio para habilitar "Interactuar con el escritorio". Yo uso esto para todo tipo de depuración, no solo servicios.
  • La otra opción, es separar un poco el código, para que la parte de servicio sea intercambiable con un inicio de aplicación normal. De esa manera, puede usar un indicador de línea de comandos simple y lanzarlo como un proceso (en lugar de un Servicio), lo que hace que sea mucho más fácil depurar.

Espero que esto ayude.

 8
Author: RichS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-24 08:14:42

Utilice la biblioteca TopShelf.

Crea una aplicación de consola y luego configura setup en tu

class Program
    {
        static void Main(string[] args)
        {
            HostFactory.Run(x =>
            {

                // setup service start and stop.
                x.Service<Controller>(s =>
                {
                    s.ConstructUsing(name => new Controller());
                    s.WhenStarted(controller => controller.Start());
                    s.WhenStopped(controller => controller.Stop());
                });

                // setup recovery here
                x.EnableServiceRecovery(rc =>
                {
                    rc.RestartService(delayInMinutes: 0);
                    rc.SetResetPeriod(days: 0);
                });

                x.RunAsLocalSystem();
            });
        }
}

public class Controller
    {
        public void Start()
        {

        }

        public void Stop()
        {

        }
    }

Para depurar su servicio, simplemente presione F5 en visual studio.

Para instalar el servicio, escriba cmd "console.exe install "

A continuación, puede iniciar y detener el servicio en el administrador de servicios de Windows.

 7
Author: Misterhex,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-11 07:35:59

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 utilizas este enfoque solo recuerda que tienes que probar todo el código mientras se ejecuta en un servicio real, mientras que el comando line tool es una buena ayuda de depuración, es un entorno diferente y no se comporta exactamente como un servicio real.

 5
Author: Nir,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-24 08:16:00

Me gusta ser capaz de depurar todos los aspectos de mi servicio, incluyendo cualquier inicialización en onStart(), mientras que todavía ejecutarlo con un comportamiento de servicio completo dentro del marco del SCM... no hay modo de" 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 plugin MMC de servicios), crea el proceso de host de servicio. Esto le da un proceso para adjuntar el depurador a pesar de que usted aún no has empezado tu verdadero servicio. Después de conectar el depurador al proceso, inicie su servicio real y podrá acceder a él en cualquier parte del ciclo de vida del servicio, incluida 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 de 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 proyecto instalador.

Detalles:

1) Asumiendo que está implementando MyService, también cree MyServiceDebug. Agregue ambos a la matriz ServiceBase en Program.cs de la siguiente manera:

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    static void Main()
    {
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] 
        { 
            new MyService(),
            new MyServiceDebug()
        };
        ServiceBase.Run(ServicesToRun);
    }

2) Agregue el servicio real Y el servicio de depuración al instalador del proyecto para el proyecto de servicio:

introduzca la descripción de la imagen aquí

Ambos servicios (real y debug) se incluyen cuando se agrega la salida del proyecto de servicio al proyecto de configuración del servicio. Después de la instalación, ambos servicios aparecerán en el servicio.msc MMC complemento.

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.

 5
Author: BitMask777,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-01 17:20:33

Al desarrollar y depurar un servicio de Windows, normalmente lo corro como una aplicación de consola agregando un parámetro de inicio /console y verificándolo. Hace la vida mucho más fácil.

static void Main(string[] args) {
    if (Console.In != StreamReader.Null) {
        if (args.Length > 0 && args[0] == "/console") {
            // Start your service work.
        }
    }
}
 4
Author: Maurice,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-24 08:17:38

¿Qué hay del depurador?Break() en la primera línea?

 4
Author: leppie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-24 08:18:22

Para depurar los servicios de Windows combino GFlags y a.archivo reg creado por regedit.

  1. Ejecute GFlags, especificando el exe-name y vsjitdebugger
  2. Ejecute regedit y vaya a la ubicación donde GFlags establece sus opciones
  3. Elija "Exportar clave" en el menú archivo
  4. Guarde ese archivo en algún lugar con el .reg extension
  5. En cualquier momento que desee depurar el servicio: haga doble clic en el .reg file
  6. Si desea detener la depuración, haga doble clic en el segundo .reg file

O guarde los siguientes fragmentos de código y reemplace servicename.exe con el nombre del ejecutable.


Depurar.reg:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\servicename.exe]
"GlobalFlag"="0x00000000"
"Debugger"="vsjitdebugger.exe"

[2] Debugoff.reg:
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\servicename.exe]
"GlobalFlag"="0x00000000"
 2
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-24 13:30:19

Para la programación rutinaria de cosas pequeñas he hecho un truco muy simple para depurar fácilmente mi servicio:

Al iniciar el servicio, compruebo si hay un parámetro de línea de comandos "/debug". Si el servicio se llama con este parámetro, no hago el inicio del servicio habitual, sino que inicio todos los oyentes y solo muestro un messagebox "Debug in progress, pulse ok para finalizar".

Así que si mi servicio se inicia de la manera habitual, se iniciará como servicio, si se inicia con la línea de comandos parameter / debug actuará como un programa normal.

En VS simplemente agregaré /debug 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 de tipo pequeño. Por supuesto, algunas cosas todavía tendrán que ser depuradas como servicio, pero para el 99% esto es lo suficientemente bueno.

 1
Author: Sam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-24 08:15:24
#if DEBUG
    System.Diagnostics.Debugger.Break();
#endif
 1
Author: Ervin Ter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-11-24 07:49:37

Utilizo una variación en la respuesta de JOP. Mediante 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 a través del administrador de servicios de Windows.

protected override void OnStart(string[] args)
{
  if (args.Contains<string>("DEBUG_SERVICE"))
  {
    Debugger.Break();
  }
  ...
}
 1
Author: nh99,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-27 23:27:33

Esto es bastante después de la pregunta, pero podría ser útil para futuras referencias.

Si puedes, te sugiero usar el excelente proyecto TopShelf. Hace que el desarrollo y la depuración de un servicio de Windows sea mucho más fácil y agrega hace que la implementación sea algo más fácil también.

Compruébalo: http://topshelf-project.com /

 1
Author: Jeremy Wiebe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-16 15:45:27

Para solucionar problemas en un programa de servicio Windows existente, use 'Debugger.Break () ' como otros chicos sugirieron.

Para el nuevo programa de Servicio de Windows, sugeriría usar 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

 1
Author: yyou,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-19 23:02:36

Simplemente coloque su almuerzo de depurador en cualquier lugar y adjunte Visualstudio al inicio

#if DEBUG
    Debugger.Launch();
#endif

También necesita iniciar VS as Administratrator y debe permitir que un proceso pueda ser depurado automáticamente por un usuario diferente (como se explica aquí):

reg add "HKCR\AppID{E62A7A31-6025-408E-87F6-81AEB0DC9347}" /v AppIDFlags /t REG_DWORD /d 8 /f
 1
Author: wotanii,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-01 05:33:24

Utilice la plantilla de servicio de Windows Proyecto C # para crear una nueva aplicación de servicio https://github.com/HarpyWar/windows-service-template

Hay modo de consola/servicio detectado automáticamente, auto instalador/desinstalador de su servicio y varias características más utilizadas se incluyen.

 1
Author: HarpyWar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-02 09:38:10

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.

[TestMethod]
public void TestMyService()
{
    MyService fs = new MyService();

    var OnStart = fs.GetType().BaseType.GetMethod("OnStart", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);

    OnStart.Invoke(fs, new object[] { null });
}

// As an extension method
public static void Start(this ServiceBase service, List<string> parameters)
{
     string[] par = parameters == null ? null : parameters.ToArray();

     var OnStart = service.GetType().GetMethod("OnStart", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);

     OnStart.Invoke(service, new object[] { par });
}
 1
Author: MisterDr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-27 08:15:48
static class Program
{
    static void Main()
    {
        #if DEBUG

        // TODO: Add code to start application here

        //    //If the mode is in debugging
        //    //create a new service instance
        Service1 myService = new Service1();

        //    //call the start method - this will start the Timer.
        myService.Start();

        //    //Set the Thread to sleep
        Thread.Sleep(300000);

        //    //Call the Stop method-this will stop the Timer.
        myService.Stop();

         #else
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] 
        { 
            new Service1() 
        };

        ServiceBase.Run(ServicesToRun);
         #endif
    }
}
 1
Author: Mansoor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-14 10:23:31

Tiene dos opciones para hacer la depuración.

  1. crear un archivo de registro : Personalmente prefiero un archivo de registro separado como archivo de texto en lugar de usar el registro de la aplicación o el registro de eventos.Pero esto le costará mucho en nombre del tiempo, porque su todavía difícil de calcular nuestro donde la ubicación exacta del error es
  2. Convertir la aplicación a la aplicación de consola: esto le permitirá, todas las herramientas de depuración que podemos utilizar en VS.

Por favor refiérase ESTA entrada de blog que yo creado para el tema.

 0
Author: Sandaru,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-21 08:19:22

Solo pega

Debugger.Break();

Cualquier lugar en tu código.

Por Ejemplo,

internal static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        private static void Main()
        {
            Debugger.Break();
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[]
            {
                new Service1()
            };
            ServiceBase.Run(ServicesToRun);
        }
    }

Llegará a Debugger.Break(); cuando ejecute su programa.

 0
Author: Chutipong Roobklom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-16 09:59:02

La mejor opción es utilizar el sistema '.Diagnostics ' espacio de nombres.

Encierre su código en if else block 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,

#if DEBUG  // for debug mode
       **Debugger.Launch();**  //debugger will hit here
       foreach (var job in JobFactory.GetJobs())
            {
                //do something 
            }

#else    // for release mode
      **Debugger.Launch();**  //debugger will hit here
     // write code here to do something in Release mode.

#endif
 0
Author: Amey P Naik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-16 06:36:28