2011-02-09 4 views
7

Chciałbym utworzyć i zarządzać aplikacją usługi systemu Windows bez "pomocy" od projektanta Visual Studio.Usługa Windows bez interferencji programu Visual Studio

Ponieważ jest to .NET, a sądząc po MSDN i co projektant ma, oznacza to dziedziczenie z Installer i konstruowania i radzenia sobie z ServiceProcessInstaller i ServiceInstaller aby móc zarządzać install-czas wykonanie serivce.

wykonawcza, to znaczy tworząc ServiceBase podklasy i uruchomienie z Main pomocą ServiceBase.Run (i nakładanie różnymi technikami manipulacji ServiceBase zdarzenia).

Jednak kiedy to robię, Visual Studio nalega na traktowanie podklas Installer i ServiceBase jako plików edytowanych przez projektanta. To nie pomaga dokładnie w czytelności, nie wspominając o tym, że w ogóle nie może w ogóle obsługiwać ręcznie pisanego kodu. Chciałbym uniknąć projektanta, aby zachować łatwość zarządzania (aby uniknąć mgławicowania, który-wie-co-uruchamia-kiedy, szczególnie w przypadku kodu, który jest trudny do testowania i debugowania, takich jak usługi Windows, które muszą być zainstalowane , w ogóle być uruchomione), a także móc określać nazwę usługi w czasie wykonywania, a nie podczas kompilacji - projektant tego nie obsługuje.

Jak mogę utworzyć aplikację usługi systemu Windows bez całego gangu?

+2

Czasami warto spojrzeć na Topshelf projektu - http://topshelf-project.com/ – stuartd

+0

hmm - schludny! Wygląda trochę przesadnie i nie do końca dojrzały, ale gdybym pisał nową aplikację, zdecydowanie bym to rozważył. –

Odpowiedz

-1

VS dodaje kilka dodatkowych rzeczy, ale nie martwiłbym się tym. Oto samouczek do ręcznego tworzenia prostej usługi w VS2005, powinien również działać dobrze dla nowych wersji.

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

+1

Projektant ulega awarii, gdy 'ServiceName' nie jest stała - i zmienia kod, który napisałem: naprawdę nie chcę projektanta.Ponadto kod, który generuje, jest z łatwością 5 razy większy niż wymagany kod i znacznie mniej zrozumiały. –

+1

Pozwolę sobie wyrazić to w następujący sposób: czy istnieje * jakaś użyteczna funkcja dla projektanta, która nie służy jako szablon początkowy, w tym wymagane typy? –

2

Cóż, po prostu usunąć InitializeComponent() połączenia w konstruktora i projektanta wygenerowany kod jest z włosami.

+0

To nie działa: visual studio jest "inteligentne": nie obchodzi, czy dodałeś plik jako klasę lub jako składnik - liczy się hierarchia dziedziczenia. Jeśli dziedziczysz po 'Installer', a tym samym' IComponent', otrzymasz projektanta - nawet jeśli pierwotnie został on utworzony przez "Add Class". –

+0

Próbowałem nawet dodać klasę nonsensu przed 'Instalatorem' - nadal używa projektanta. A (niesatysfakcjonujące) obejście polega na kliknięciu prawym przyciskiem: Otwórz za pomocą i wybierz Edytor CSharp i ustaw jako domyślny. Jest niesatysfakcjonujący, ponieważ kontrola nowego źródła na innym komputerze spowoduje utratę tego ustawienia użytkownika i powrót do projektanta, który mi się podoba-bałagan-mój-kod. –

+1

I repro. Irytujące, nieprawdaż? –

5

Ponieważ często tworzą usługi to zrobić tak:

Mam wspólnej klasy bazowej, który wygląda tak:

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); 
} 

Następnie tworzę wszystkie moje usługi, takie jak ten

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

Teraz mogę przetestować usługę, uruchamiając ją w debugerze lub wierszu poleceń.

Podczas instalacji używam wiersz polecenia

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

(I nie były w stanie powstrzymać projektanta z otworem na podwójne kliknięcie)

8

ServiceBase pochodzi z Component. Aby wyłączyć widok projektant można dołączyć atrybut tak:

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

} 
+0

to działa, projektant nie jest tworzony pod warunkiem, że dodasz tę linię przed dodaniem dziedziczenia. – Matthew

+0

To jest rzeczywiście poprawna odpowiedź, działa jak mistrz! – Ronald

+1

Pracowałem, ale musiałem usunąć i ponownie dodać odniesienie do "System.ServiceProcess", zanim zostanie to uwzględnione. –