Starten Sie bei der Installation automatisch einen Windows-Dienst

119

Ich habe einen Windows-Dienst, den ich mit InstallUtil.exe installiere. Obwohl ich die Startmethode auf Automatisch eingestellt habe, wird der Dienst bei der Installation nicht gestartet. Ich muss die Dienste manuell öffnen und auf Start klicken. Gibt es eine Möglichkeit, es entweder über die Befehlszeile oder über den Code des Dienstes zu starten?

mickyjtwin
quelle

Antworten:

218

Fügen Sie in Ihrer Installer-Klasse einen Handler für das AfterInstall-Ereignis hinzu. Sie können dann den ServiceController im Ereignishandler aufrufen, um den Dienst zu starten.

using System.ServiceProcess;
public ServiceInstaller()
{
    //... Installer code here
    this.AfterInstall += new InstallEventHandler(ServiceInstaller_AfterInstall);
}

void ServiceInstaller_AfterInstall(object sender, InstallEventArgs e)
{
    ServiceInstaller serviceInstaller = (ServiceInstaller)sender;

    using (ServiceController sc = new ServiceController(serviceInstaller.ServiceName))
    {
             sc.Start();
    }
}

Wenn Sie nun InstallUtil auf Ihrem Installationsprogramm ausführen, wird es installiert und der Dienst wird automatisch gestartet.

codemonkey
quelle
40
(Kommentar aus einer vorgeschlagenen Bearbeitung): Verwenden Sie besser serviceInstaller.ServiceName. Wenn der Servicename geändert wird, wird der richtige Name verwendet, ohne dass der Code geändert werden muss.
Marc Gravell
1
Es würde auch nicht schaden, das ServiceControllerin eine using-Anweisung zu packen .
ChrisO
3
Wie erhalten Sie serviceInstaller?
Philip Rego
1
serviceInstaller soll die ServiceInstallerVariable in Ihrer Klasse sein. Diese Klasse muss implementieren System.Configuration.Install.Installer. Weitere Informationen finden Sie in diesem MSDN-Handbuch .
Sergio Basurco
4
@PhilipRego Vermutlich serviceInstallerist dies das ServiceInstallerObjekt, auf das senderim Ereignishandler verwiesen wird , das normalerweise im ServiceInstaller()Konstruktor instanziiert wird . Daher können Sie ServiceInstaller serviceInstaller = (ServiceInstaller)sender;vor der usingAnweisung hinzufügen .
Khargoosh
28

Nach einigem Refactoring ist dies ein Beispiel für ein vollständiges Windows Service-Installationsprogramm mit automatischem Start:

using System.ComponentModel;
using System.Configuration.Install;
using System.ServiceProcess;

namespace Example.of.name.space
{
[RunInstaller(true)]
public partial class ServiceInstaller : Installer
{
    private readonly ServiceProcessInstaller processInstaller;
    private readonly System.ServiceProcess.ServiceInstaller serviceInstaller;

    public ServiceInstaller()
    {
        InitializeComponent();
        processInstaller = new ServiceProcessInstaller();
        serviceInstaller = new System.ServiceProcess.ServiceInstaller();

        // Service will run under system account
        processInstaller.Account = ServiceAccount.LocalSystem;

        // Service will have Start Type of Manual
        serviceInstaller.StartType = ServiceStartMode.Automatic;

        serviceInstaller.ServiceName = "Windows Automatic Start Service";

        Installers.Add(serviceInstaller);
        Installers.Add(processInstaller);
        serviceInstaller.AfterInstall += ServiceInstaller_AfterInstall;            
    }
    private void ServiceInstaller_AfterInstall(object sender, InstallEventArgs e)
    {
        ServiceController sc = new ServiceController("Windows Automatic Start Service");
        sc.Start();
    }
}
}
Pedro Pereira
quelle
2
Dieser Code gab mir die folgenden Fehler: Während der Installationsphase ist eine Ausnahme aufgetreten. System.InvalidOperationException: Im OnAfterInstall-Ereignishandler von System.ServiceProcess.ServiceInstaller ist eine Ausnahme aufgetreten. Die innere Ausnahme System.InvalidOperationException wurde mit der folgenden Fehlermeldung ausgelöst: Der Dienst serviceName kann auf dem Computer nicht gestartet werden. Die innere Ausnahme System.ComponentModel.Win32Exception wurde mit der folgenden Fehlermeldung ausgelöst: Das ausführbare Programm, für das dieser Dienst konfiguriert ist run in implementiert den Dienst nicht.
Goamn
2
Die Fehler wurden behoben, als ich die Zeile "InitializeComponent ()" auskommentierte. Ich glaube, diese Zeile dupliziert alle anderen Zeilen, da die Protokolle zwei identische Dinge zu zeigen scheinen, die vor dem Fehler zusammen passieren: Installieren von service serviceName ... Service serviceName wurde erfolgreich installiert. Erstellen des EventLog-Quelldienstnamens in der Protokollanwendung ... Installieren des Dienstdienstnamens ... Erstellen des EventLog-Quelldienstnamens in der Protokollanwendung ... Im OnAfterInstall-Ereignishandler von System.ServiceProcess.ServiceInstaller ist eine Ausnahme aufgetreten.
Goamn
Du hast meinen Tag wirklich gerettet :) Danke für diesen nützlichen Kommentar. Nachdem ich den Aufruf von InitializeComponent () auskommentiert hatte, startete mein Dienst ebenfalls perfekt
Konstantin
7

Wie wäre es mit folgenden Befehlen?

net start "<service name>"
net stop "<service name>"
Hemant
quelle
Cool. Ich habe dies direkt nach Abschluss der Installation in meine Installations-Batch-Datei geschrieben.
M. Fawad Surosh
5

Programmatische Optionen zur Steuerung von Diensten:

  • Es kann nativer Code "Starten eines Dienstes" verwendet werden . Maximale Kontrolle mit minimalen Abhängigkeiten, aber am meisten Arbeit.
  • WMI: Win32_Service hat eine StartServiceMethode. Dies ist gut für Fälle, in denen Sie in der Lage sein müssen, eine andere Verarbeitung durchzuführen (z. B. um den Dienst auszuwählen).
  • PowerShell: Ausführung Start-Serviceüber RunspaceInvokeoder durch Erstellen einer eigenen Runspaceund Verwendung der CreatePipelineMethode zur Ausführung. Dies ist gut für Fälle, in denen Sie in der Lage sein müssen, eine andere Verarbeitung (z. B. zur Auswahl des Dienstes) mit einem viel einfacheren Codierungsmodell als WMI durchzuführen, dies hängt jedoch von der installierten PSH ab.
  • Eine .NET-Anwendung kann verwenden ServiceController
Richard
quelle
4

Sie können die folgende Befehlszeile verwenden, um den Dienst zu starten:

net start *servicename*
AlexDrenea
quelle
2

Verwenden Sie ServiceController , um Ihren Dienst mit Code zu starten.

Update: Der korrektere Weg, um den Dienst über die Befehlszeile zu starten, ist die Verwendung des Befehls "sc" ( Service Controller ) anstelle von "net".

Schiedsrichter
quelle
6
Warum ist "sc" ein "richtigerer" Weg? Was ist falsch an "net start" (und dem PSH-Cmdlet "start-service")?
Richard
1
Da sc von einem Remotecomputer aus aufgerufen werden kann, funktioniert es immer.
MacGyver
1

Trotz nach der akzeptierten Antwort genau, war ich noch nicht in der Lage , den Dienst erreiche ich start-- stattdessen eine Fehlermeldung bei der Installation angegeben wurde die besagt , dass der Dienst, der gerade installiert wurde kann nicht gestartet werden, da es nicht gäbe, trotz Verwendung von this.serviceInstaller.ServiceNameeher als ein wörtliches ...

Ich habe schließlich eine alternative Lösung gefunden, die die Befehlszeile verwendet:

private void serviceInstaller_AfterInstall(object sender, InstallEventArgs e) {
        ProcessStartInfo startInfo = new ProcessStartInfo();
        startInfo.WindowStyle = ProcessWindowStyle.Hidden;
        startInfo.FileName = "cmd.exe";
        startInfo.Arguments = "/C sc start " + this.serviceInstaller.ServiceName;

        Process process = new Process();
        process.StartInfo = startInfo;
        process.Start();
    }
Matsu Q.
quelle
0

Automatischer Start bedeutet, dass der Dienst beim Start von Windows automatisch gestartet wird. Wie bereits erwähnt, sollten Sie zum Starten über die Konsole den ServiceController verwenden.

Michael Klement
quelle
Ich möchte das nicht tun. Ich möchte dies auf einmal über die Befehlszeile oder innerhalb der Windows Service-Klassen tun.
Mickyjtwin
Entschuldigung, mein Schlechtes, ich habe den Punkt verpasst, an dem Sie die Möglichkeit, es über das Control Panel zu starten, ausdrücklich ausgeschlossen haben.
Michael Klement
0

Sie können die GetServicesMethode der ServiceController- Klasse verwenden, um ein Array aller Dienste abzurufen. Suchen Sie dann Ihren Dienst, indem Sie die ServiceNameEigenschaft jedes Dienstes überprüfen . Wenn Sie Ihren Dienst gefunden haben, rufen Sie die StartMethode auf, um ihn zu starten.

Sie sollten die StatusEigenschaft auch überprüfen, um festzustellen, in welchem ​​Zustand sie sich bereits befindet, bevor Sie start aufrufen (sie wird möglicherweise ausgeführt, angehalten, gestoppt usw.).

adrianbanks
quelle
0

Sie haben Ihren Designer beschädigt. Fügen Sie Ihre Installer-Komponente erneut hinzu. Es sollte einen serviceInstaller und einen serviceProcessInstaller haben. Der serviceInstaller mit der Eigenschaft Startmethode auf Automatisch wird bei der Installation und nach jedem Neustart gestartet.

Guillaume Massé
quelle
0

Nur ein Hinweis: Möglicherweise haben Sie Ihren Dienst über die Formularschnittstelle anders eingerichtet, um ein Dienstinstallationsprogramm und ein Projektinstallationsprogramm hinzuzufügen. Ersetzen Sie in diesem Fall serviceInstaller.ServiceName durch "name from designer" .ServiceName.

Sie brauchen in diesem Fall auch keine privaten Mitglieder.

Danke für die Hilfe.

IanUniacke
quelle