2011-02-09 21 views
7

Mi piacerebbe creare e gestire un'applicazione di servizio Windows senza "aiuto" dal designer di Visual Studio.Servizio Windows senza interferenze di Visual Studio

Poiché questo è NET, e giudicare da MSDN e ciò fa il progettista, questo significa eredita da Installer, e la costruzione e trattare con ServiceProcessInstaller e ServiceInstaller per poter gestire l'esecuzione al momento dell'installazione del serivce.

runtime, questo significa creare una sottoclasse ServiceBase e partendo da Main usando ServiceBase.Run (e vari metodi di override movimentazione ServiceBase eventi).

Tuttavia, quando faccio questo, Visual Studio insiste sul trattamento delle sottoclassi Installer e ServiceBase come file di progettazione. Questo non aiuta di certo la leggibilità, per non parlare del fatto che in genere non è in grado di gestire il codice scritto a mano. Vorrei evitare che il progettista mantenga le cose gestibili (per evitare nebulosi who-knows-what-runs-when, in particolare per il codice che è difficile da testare e eseguire il debug come i servizi Windows che dopo tutto devono essere installati su essere eseguito a tutti), e anche di essere in grado di specificare il nome del servizio in fase di esecuzione, piuttosto che in fase di compilazione - il progettista non lo supporta.

Come posso creare un'applicazione di servizio Windows senza tutto il gunk?

+2

Si potrebbe desiderare di avere uno sguardo al progetto TopShelf - http://topshelf-project.com/ – stuartd

+0

hmm - pulito! Sembra un po 'eccessivo e non ancora maturo, ma se dovessi scrivere una nuova app, la considererei sicuramente. –

risposta

-1

VS aggiunge qualcosa in più ma non mi preoccuperei molto. Ecco un tutorial per creare manualmente un semplice servizio in VS2005, dovrebbe funzionare bene anche per le nuove versioni.

http://www.codeproject.com/KB/system/WindowsService.aspx

+1

Il progettista si arresta in modo anomalo quando 'ServiceName' non è costante e altera il codice che ho scritto: non voglio davvero il designer.Inoltre, il codice che produce è facilmente 5 volte più grande del codice necessario e molto meno comprensibile. –

+1

Lasciatemelo dire in questo modo: c'è * una * funzione utile per il designer oltre a servire come modello iniziale compresi i tipi richiesti? –

2

Beh, basta cancellare la chiamata InitializeComponent() nella funzione di costruzione e il designer codice generato è fuori dei vostri capelli.

+0

Questo non funziona: lo studio visivo è "intelligente": non importa se hai aggiunto un file come classe o come componente - ciò che conta è la gerarchia dell'ereditarietà. Se si eredita da 'Installer' e quindi' IComponent', si otterrà il designer, anche se originariamente il file è stato creato con "Aggiungi classe". –

+0

Ho anche provato ad aggiungere una classe senza senso prima di "Installer" - utilizza ancora il designer. Una soluzione (insoddisfacente) consiste nel fare clic con il tasto destro: Apri-con e seleziona Editor CSharp e impostalo come predefinito. Non è soddisfacente perché un nuovo controllo del codice sorgente su un altro computer perderà le impostazioni dell'utente e tornerà al progettista del codice "please-mess-up-my-code". –

+1

I repro. Fastidioso, non è vero? –

5

Dal momento che spesso creano servizi farlo in questo modo:

Ho una classe base comune che assomiglia a questo:

internal class ServiceRunner : ServiceBase { 
    protected static void Startup(string[] args, ServiceRunner instance, bool interactiveWait) {  
    if (instance == null) 
     throw new ArgumentNullException("instance"); 

    if (Environment.UserInteractive) { 
     instance.OnStart(args); 
     if (interactiveWait) { 
      Console.WriteLine("Press any key to stop service"); 
      Console.ReadKey(); 
     } 
     instance.OnStop(); 
    } 
    else 
     Run(instance); 
} 

Poi ho creare tutti i miei servizi come questo

internal class MyService : ServiceRunner 
{ 
    public MyService() { 
     ServiceName = ConfigurationManager.AppSettings["MyServiceName"]; 
    } 

    private static void Main(string[] args) { 
     Startup(args, new MyService(), true); 
    } 

    protected override void OnStart(string[] args) { 
     base.OnStart(args); 
     ... 
    } 

    protected override void OnStop() { 
     ... 
     base.OnStop(); 
    } 
} 

Ora posso testare il servizio semplicemente eseguendolo nel debugger o sulla riga di comando.

Quando si installa Io uso la linea di comando

sc create ServiceName binPath= C:\...\MyService.exe 

(non sono stato in grado di fermare la designer di apertura il doppio clic)

8

ServiceBase è derivato da Component. Per disattivare la visualizzazione di progettazione è possibile collegare l'attributo in questo modo:

[System.ComponentModel.DesignerCategory("Code")] 
public class MyService : ServiceBase 
{ 

} 
+0

funziona, il progettista non viene creato purché si aggiunga questa riga prima di aggiungere l'ereditarietà. – Matthew

+0

Questa è davvero la risposta corretta, funziona come un campione! – Ronald

+1

Lavorato, ma ho dovuto rimuovere e aggiungere nuovamente il riferimento a 'System.ServiceProcess' prima che questo avesse effetto. –

Problemi correlati