2010-03-25 3 views
23

Voglio eseguire il debug di un servizio scritto in C# e il vecchio stile è troppo lungo. Devo interrompere il servizio, avviare la mia applicazione che utilizza il servizio in modalità di debug (Visual Studio 2008), avviare il servizio, collegarlo al processo del servizio e quindi navigare nella mia applicazione Asp.Net per attivare il servizio.Avvolgere un servizio C# in un'app console per eseguirne il debug

Fondamentalmente ho il servizio in esecuzione in background, in attesa di un compito. L'applicazione Web attiverà un'attività da ritirare dal servizio.

Quello che mi piacerebbe fare è avere un'applicazione di console che spari il servizio nel tentativo di eseguire il debug. C'è qualche semplice demo che qualcuno conosce?

Grazie Jack

risposta

1

Ecco un blog post su come eseguire il servizio di Windows come una console app.

Si potrebbe anche solo creare una nuova applicazione console che fa riferimento la stessa logica il vostro servizio per testare metodi, o impostare unit test sulla logica i propri servizi

1

ho usato unit test per eseguire il debug di configurazioni difficili del passato, basta scrivere un test unitario che chiama qualunque metodo di servizio con qualsiasi parametro e imposta i punti di interruzione di debug nel test unitario.

L'utilizzo di testdriven.net o testina giramotore rende più semplice.

2

tendo ad avere sia un ambiente di configurazione o utilizzare una direttiva per il build di debug:

#if DEBUG 
    Debugger.Break(); 
#endif 

o

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

ho messo che nel metodo OnStart del componente di servizio. Quindi viene richiesto automaticamente e allegato al processo.

20

Si può fare qualcosa di simile nel principale punto di ingresso:

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 
} 

e nel vostro gestore OnStart evento:

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

+1 - Ho quasi lo stesso codice in un paio di servizi che ho scritto. – 37Stars

15

L'approccio che prendere sempre è quello di isolare tutte le tue applicazioni la logica di tion in librerie di classi. Questo rende il tuo progetto di servizio davvero solo una shell che ospita le tue librerie di classi come servizio.

In questo modo, è possibile eseguire facilmente il test dell'unità e il debug del codice, senza dover affrontare il problema del debug di un servizio collegandosi a un processo. Consiglierei ovviamente i test delle unità, ma se non lo fai, aggiungere la console che chiama lo stesso punto di accesso del tuo servizio è la strada da percorrere.

3

TopShelf è un altro progetto perfetto per questo approccio. Ti consente di eseguire un processo come un servizio o come una normale applicazione da console con una configurazione minima.

10

Per evitare l'utilizzo di impostazioni globali, in genere eseguo il test in fase di esecuzione, sia che si tratti di un servizio o di un'applicazione normale tramite la proprietà 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

Non dimenticare di impostare il tipo di output come applicazione console nelle proprietà del progetto, se si desidera che la console venga visualizzata. Il programma può ancora essere eseguito come un servizio di Windows, indipendentemente dal fatto che si tratti di un'applicazione console o di un'applicazione Windows, quindi non preoccuparti. –

0

Io lo uso per verificare se il mio processo è in esecuzione come servizio o meno.

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

È possibile chiamare i metodi di servizio tramite riflessione come illustrato di seguito.

L'utilizzo di Environment.UserInteractive ci consente di sapere se stiamo eseguendo come app di console o come servizio.

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(); 
    } 
} 
Problemi correlati