2009-06-24 3 views
4

Ich habe ein Projekt, das als Windows-Dienst für die Produktion bereitgestellt wird. Für lokale Entwicklungszwecke wäre es jedoch nützlich, es als Konsolenanwendung auszuführen. Im Moment habe ich eine Klasse namens ReportingHost, die meine Kernfunktionalität bietet, und eine Klasse namens ReportingServiceHost, die von ServiceBase erbt und ermöglicht es mir, die Anwendung als Dienst auszuführen. Es gibt auch eine Programmklasse mit einer Hauptmethode, die auf meinem ReportingServiceHost ServiceBase.Run aufruft.Was ist das akzeptierte Muster für eine Anwendung, die als Dienst oder als Konsolenanwendung ausgeführt werden kann

Ich denke, ich muss eine ReportingConsoleHost Klasse schreiben, die es mir ermöglicht, die Funktionalität in einer Konsole auszuführen. Dann muss ich meine Main ändern, um auf einen Befehlszeilenschalter zu reagieren und das eine oder andere auszuwählen. Das sind die zwei Bits, mit denen ich Probleme habe.

Ich habe mir this angesehen und versucht, diesen Code zu verwenden, aber meine App wird sofort beendet, sie zeigt kein Konsolenfenster an und wartet nicht vor dem Schließen auf Enter.

Ein Teil des Problems ist, dass ich kein tiefes Verständnis davon habe, wie diese Dinge funktionieren. Ein definitives Muster zum Aufspalten meiner Funktionalität, meine zwei verschiedenen Möglichkeiten, diese Funktionalität auszuführen, und eine Hauptmethode, die eine dieser Möglichkeiten auf der Basis eines Befehlszeilenarguments auswählt, möchte ich erreichen.

Antwort

9

Ich vermute, Ihr Test-Projekt wurde als Windows-Exe, nicht als eine Konsole exe konfiguriert. Mit einer Windows-Exe Console.ReadLine wird sofort zurückkehren.

Um eine Konsole exe zu haben, die sowohl als Dienst und in der Befehlszeile funktioniert, ist es als Service-Projekt (in Visual Studio) beginnen - und auf Environment.UserInteractive einen Scheck hinzufügen - dh

static void Main() { 
    if(Environment.UserInteractive) { 
     // code that starts the listener and waits on ReadLine 
    } else { 
     // run the service code that the VS template injected 
    } 
} 

Sie können Verwenden Sie natürlich auch einen Befehlszeilenschalter. Ich habe beispielsweise auf microsoft.public.dotnet.languages.csharp die als wirkt:

  • ein Installations-/Deinstallationsprogramm

abhängig von den Schaltern

+0

Damit VS ein Konsolenfenster für Sie erzeugt, wenn Sie F5 mit dieser Lösung drücken, müssen Sie die Projekteigenschaften ändern, indem Sie auf der Registerkarte Anwendung die Option Ausgabe an Konsole festlegen. Soweit ich das beurteilen kann, wird es sich trotzdem als Service installieren lassen. –

+0

@Carl ... ja, ich sagte "Konsole exe" in der Antwort ... –

2

I dies getan haben

  • ein Dienst
  • ein Konsolenmodus app zuvor durch Implementieren eines normalen Windows-Dienstes (durch Ableiten von ServiceBase), aber Einchecken der Hauptmethode, um nach einem Befehlszeilenargument zu suchen.

    Wenn die Argumente /console enthalten, starten Sie die Konsolenversion, andernfalls starten Sie den Dienst.

    Etwas wie folgt aus:

    internal class MyService : ServiceBase 
    { 
        internal static void Main(string[] args) 
        { 
         if (args.Length == 0) 
         { 
          // run as a service.... 
          ServiceBase[] servicesToRun = new ServiceBase[] {new MyService()}; 
          Run(servicesToRun); 
         } 
         else 
         { 
          // run as a console application.... 
         } 
        } 
    } 
    

  • 2

    Mein Rat? Stellen Sie all Ihre Logik für Ihren Service in einer separaten Baugruppe bereit. (Eine Klassenbibliothek oder eine DLL.) Erstellen Sie dann ein Projekt als Dienst, der auf Ihre Klassenbibliothek verweist und den Code als Dienst verwendet. Erstellen Sie ein zweites Konsolenprojekt, das ebenfalls auf Ihre Klassenbibliothek verweist, dieses jedoch als Konsolenanwendung verfügbar macht. Sie würden drei verschiedene Projekte in Ihrer Lösung haben, aber es erlaubt Ihnen, die Dinge getrennt zu halten. Dies würde es tatsächlich ermöglichen, Ihren Service in mehreren anderen Formen zu erweitern.Sie könnten beispielsweise ein viertes Projekt als Web-Service erstellen und Ihren Service von einem Web-Browser auf einem Client-System aus aufrufen. Da die Softwarelogik von der Nutzungslogik getrennt ist, haben Sie viel Kontrolle darüber.

    Beachten Sie, dass ein Dienst möglicherweise mit mehr Einschränkungen ausgeführt wird als eine Konsolenanwendung. Im Allgemeinen haben Dienste standardmäßig keinen Netzwerkzugriff, ihnen ist kein Monitor zugewiesen, um Fehlermeldungen anzuzeigen, und sie werden im Allgemeinen mit einem eingeschränkten Benutzerkonto oder Systemkonto ausgeführt. Ihr Dienst funktioniert möglicherweise als Konsole und schlägt dennoch als Dienst fehl.

    1

    Es gibt bereits zwei gute Antworten oben - aber ich dachte, ich würde einen Link zu Brian Noyes' Debuggable Self-Host Windows Service Project Blog-Post veröffentlichen - es spricht über WCF, sollte aber für jeden 'Windows Service' gelten.

    Die beste Sache ist der Beispielcode - wenn Sie nicht herausfinden können, wo die obigen Beispiele "passen", ergreifen Sie das komplette Projekt und sehen, wie es funktioniert. Danke Brian!

    Verwandte Themen