2010-03-25 19 views
23

Quiero depurar un servicio escrito en C# y la forma antigua es demasiado larga. Tengo que detener el servicio, iniciar mi aplicación que usa el servicio en modo de depuración (Visual Studio 2008), iniciar el servicio, adjuntarlo al proceso del servicio y luego navegar en mi aplicación Asp.Net para activar el servicio.Envolviendo un servicio de C# en una aplicación de consola para depurarlo

Básicamente tengo el servicio ejecutándose en segundo plano, esperando una tarea. La aplicación web activará una tarea para ser recogido por el servicio.

Lo que me gustaría hacer es tener una aplicación de consola que dispare el servicio en un esfuerzo por depurarme. ¿Hay alguna demostración simple que cualquiera sepa?

Gracias Jack

Respuesta

1

Aquí está una blog post sobre el funcionamiento de su servicio de Windows como una aplicación de consola.

También puede simplemente crear una nueva aplicación de consola que hace referencia a la misma lógica que su servicio de probar métodos, o la creación de pruebas unitarias en la lógica de sus servicios

1

He utilizado las pruebas unitarias para depurar configuraciones difíciles en el pasado, simplemente escriba una prueba unitaria que llame a cualquier método de servicio con cualquier parámetro y establezca puntos de corte de depuración en la prueba unitaria.

El uso de testdriven.net o jetbrains testrunner lo hace más fácil.

2

que tienden a tener ya sea un entorno de configuración o utilizar una directiva para versiones de depuración:

#if DEBUG 
    Debugger.Break(); 
#endif 

o

if(Settings.DebugBreak) 
      Debugger.Break(); 

pongo que en el método OnStart del componente de servicio. Luego se le solicita automáticamente y se adjunta al proceso.

20

Usted puede hacer algo como esto en el principal punto de entrada:

static void Main() 
{ 
#if DEBUG 
    Service1 s = new Service1(); 
    s.Init(); // Init() is pretty much any code you would have in OnStart(). 
#else 
    ServiceBase[] ServicesToRun; 
    ServicesToRun=new ServiceBase[] 
    { 
     new Service1() 
    }; 
    ServiceBase.Run(ServicesToRun); 
#endif 
} 

y en el controlador OnStart Evento:

protected override void OnStart(string[] args) 
{ 
    Init(); 
} 
+0

+1 - Tengo casi el mismo código exacto en un par de servicios que he escrito. – 37Stars

15

El enfoque que Siempre tomar es aislar a todos sus aplicaciones lógica de la lógica en las bibliotecas de clase. Esto hace que su proyecto de servicio realmente solo sea un shell que aloja sus bibliotecas de clase como un servicio.

Al hacer esto, puede probar y depurar su código fácilmente, sin tener que lidiar con el dolor de cabeza de depurar un servicio adjuntando un proceso. Recomiendo pruebas unitarias, por supuesto, pero si no estás haciendo eso, entonces agregar una aplicación de consola que llame al mismo punto de entrada que tu servicio es el camino a seguir.

3

TopShelf es otro proyecto que es perfecto para este enfoque. Le permite ejecutar un proceso como un servicio, o como una aplicación de consola normal con una configuración mínima.

10

Para evitar el uso de las definiciones globales, generalmente pruebo en tiempo de ejecución si soy un servicio o una aplicación normal a través de la propiedad Environment.UserInteractive.

[MTAThread()] 
    private static void Main() 
    { 
     if (!Environment.UserInteractive) 
     { 
      ServiceBase[] aServicesToRun; 

      // More than one NT Service may run within the same process. To add 
      // another service to this process, change the following line to 
      // create a second service object. For example, 
      // 
      // ServicesToRun = New System.ServiceProcess.ServiceBase() {New ServiceMain, New MySecondUserService} 
      // 
      aServicesToRun = new ServiceBase[] {new ServiceMain()}; 

      Run(aServicesToRun); 
     } 
     else 
     { 
      var oService = new ServiceMain(); 
      oService.OnStart(null); 
     } 
    } 
+8

No olvide configurar su Tipo de salida como Aplicación de consola en las propiedades de su proyecto, si desea que aparezca la consola. El programa aún se puede ejecutar como un servicio de Windows, independientemente de si es una aplicación de consola o una aplicación de Windows, así que no se preocupe. –

0

Lo uso para verificar si mi proceso se está ejecutando como un servicio o no.

public class ServiceDiagnostics 
{ 
    readonly bool _isUserService; 
    readonly bool _isLocalSystem; 
    readonly bool _isInteractive; 

    public ServiceDiagnostics() 
    { 
     var wi = WindowsIdentity.GetCurrent(); 
     var wp = new WindowsPrincipal(wi); 

     var serviceSid = new SecurityIdentifier(WellKnownSidType.ServiceSid, null); 
     var localSystemSid = new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null); 
     var interactiveSid = new SecurityIdentifier(WellKnownSidType.InteractiveSid, null); 

     this._isUserService = wp.IsInRole(serviceSid); 

     // Neither Interactive or Service was present in the current user's token, This implies 
     // that the process is running as a service, most likely running as LocalSystem. 
     this._isLocalSystem = wp.IsInRole(localSystemSid); 

     // This process has the Interactive SID in its token. This means that the process is 
     // running as a console process. 
     this._isInteractive = wp.IsInRole(interactiveSid); 
    } 

    public bool IsService 
    { 
     get { return this.IsUserService || this.IsLocalSystem || !this.IsInteractive; }  
    } 

    public bool IsConsole 
    { 
     get { return !this.IsService; } 
    } 

    /// <summary> 
    /// This process has the Service SID in its token. This means that the process is running 
    /// as a service running in a user account (not local system). 
    /// </summary> 
    public bool IsUserService 
    { 
     get { return this._isUserService; } 
    } 

    /// <summary> 
    /// Neither Interactive or Service was present in the current user's token, This implies 
    /// that the process is running as a service, most likely running as LocalSystem. 
    /// </summary> 
    public bool IsLocalSystem 
    { 
     get { return this._isLocalSystem; } 
    } 

    /// <summary> 
    /// This process has the Interactive SID in its token. This means that the process is 
    /// running as a console process. 
    /// </summary> 
    public bool IsInteractive 
    { 
     get { return this._isInteractive; } 
    } 
} 
2

Puede llamar a los métodos de servicio a través de la reflexión como se ve a continuación.

El uso de Environment.UserInteractive nos permite saber si estamos funcionando como una aplicación de consola o como un servicio.

ServiceBase[] ServicesToRun; 
ServicesToRun = new ServiceBase[] 
{ 
    new MyService() 
}; 

if (!Environment.UserInteractive) 
{ 
    // This is what normally happens when the service is run. 
    ServiceBase.Run(ServicesToRun); 
} 
else 
{ 
    // Here we call the services OnStart via reflection. 
    Type type = typeof(ServiceBase); 
    BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic; 
    MethodInfo method = type.GetMethod("OnStart", flags); 

    foreach (ServiceBase service in ServicesToRun) 
    { 
     Console.WriteLine("Running " + service.ServiceName + ".OnStart()"); 
     // Your Main method might not have (string[] args) but you could add that to be able to send arguments in. 
     method.Invoke(service, new object[] { args }); 
    } 

    Console.WriteLine("Finished running all OnStart Methods."); 

    foreach (ServiceBase service in ServicesToRun) 
    { 
     Console.WriteLine("Running " + service.ServiceName + ".OnStop()"); 
     service.Stop(); 
    } 
} 
Cuestiones relacionadas