Démarrer automatiquement un service Windows lors de l'installation

119

J'ai un service Windows que j'installe en utilisant InstallUtil.exe. Même si j'ai défini la méthode de démarrage sur Automatique, le service ne démarre pas une fois installé, je dois ouvrir manuellement les services et cliquer sur Démarrer. Existe-t-il un moyen de le démarrer soit via la ligne de commande, soit via le code du Service?

mickyjtwin
la source

Réponses:

218

Dans votre classe Installer, ajoutez un gestionnaire pour l'événement AfterInstall. Vous pouvez ensuite appeler le ServiceController dans le gestionnaire d'événements pour démarrer le service.

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

Maintenant, lorsque vous exécutez InstallUtil sur votre programme d'installation, il installera puis démarrera le service automatiquement.

codemonkey
la source
40
(commentaire d'une modification proposée): Mieux vaut utiliser serviceInstaller.ServiceName, si le nom du service est changé, il utilisera le nom correct sans avoir besoin de le changer dans le code.
Marc Gravell
1
Cela ne ferait pas de mal non plus de placer le ServiceControllerdans une instruction using.
ChrisO
3
Comment obtenez-vous serviceInstaller?
Philip Rego
1
serviceInstaller est censé être la ServiceInstallervariable de votre classe. Une telle classe doit implémenter System.Configuration.Install.Installer. Consultez ce guide msdn pour plus d'informations.
Sergio Basurco
4
@PhilipRego serviceInstallerest probablement l' ServiceInstallerobjet auquel se réfère senderle gestionnaire d'événements, qui est normalement instancié dans le ServiceInstaller()constructeur. Par conséquent, vous pouvez ajouter ServiceInstaller serviceInstaller = (ServiceInstaller)sender;avant la usingdéclaration.
khargoosh
28

Après une petite refactorisation, voici un exemple de programme d'installation de service Windows complet avec démarrage automatique:

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
la source
2
Ce code m'a donné les erreurs suivantes: Une exception s'est produite lors de la phase d'installation. System.InvalidOperationException: une exception s'est produite dans le gestionnaire d'événements OnAfterInstall de System.ServiceProcess.ServiceInstaller. L'exception interne System.InvalidOperationException a été levée avec le message d'erreur suivant: Impossible de démarrer le service serviceName sur l'ordinateur '.' .. L'exception interne System.ComponentModel.Win32Exception a été levée avec le message d'erreur suivant: Le programme exécutable pour lequel ce service est configuré run in n'implémente pas le service.
goamn
2
Les erreurs saisies une fois que j'ai commenté la ligne "InitializeComponent ()". Je crois que cette ligne duplique toutes les autres lignes car les journaux semblent montrer deux choses identiques qui se produisent ensemble avant l'erreur: Installation du service serviceName ... Service serviceName a été installé avec succès. Création de la source EventLog serviceName dans le journal Application ... Installation du service serviceName ... Création de la source EventLog serviceName dans le journal Application ... Une exception s'est produite dans le gestionnaire d'événements OnAfterInstall de System.ServiceProcess.ServiceInstaller.
goamn
Tu as vraiment sauvé ma journée :) Merci pour ce commentaire utile. Après avoir commenté l'appel InitializeComponent (), mon service a également démarré parfaitement
Konstantin
7

Que diriez-vous de suivre les commandes?

net start "<service name>"
net stop "<service name>"
Hemant
la source
Cool. J'ai écrit ceci dans mon fichier de commandes d'installation juste après l'installation.
M. Fawad Surosh le
5

Options programmatiques pour contrôler les services:

  • Le code natif peut être utilisé, "Démarrage d'un service" . Contrôle maximum avec un minimum de dépendances mais le plus de travail.
  • WMI: Win32_Service a unStartService méthode. C'est bon pour les cas où vous devez être en mesure d'effectuer d'autres traitements (par exemple pour sélectionner quel service).
  • PowerShell: exécutez Start-Servicevia RunspaceInvokeou en créant le vôtre Runspaceet en utilisant sa CreatePipelineméthode pour exécuter. C'est bon pour les cas où vous devez être en mesure d'effectuer d'autres traitements (par exemple pour sélectionner quel service) avec un modèle de codage beaucoup plus simple que WMI, mais dépend de l'installation de PSH.
  • Une application .NET peut utiliser ServiceController
Richard
la source
4

Vous pouvez utiliser la ligne de commande suivante pour démarrer le service:

net start *servicename*
AlexDrenea
la source
2

Utilisez ServiceController pour démarrer votre service à partir du code.

Mise à jour: Et une manière plus correcte de démarrer le service à partir de la ligne de commande est d'utiliser la commande "sc" ( Service Controller ) au lieu de "net".

arbitre
la source
6
Pourquoi "sc" est-il un moyen "plus correct"? Quel est le problème avec "net start" (et l'applet de commande PSH start-service)?
Richard
1
Parce que sc peut être appelé depuis une machine distante, cela fonctionne toujours.
MacGyver
1

Bien que suivant exactement la réponse acceptée, je n'étais toujours pas en mesure de démarrer le service - j'ai reçu à la place un message d'échec lors de l'installation indiquant que le service qui venait d'être installé ne pouvait pas être démarré, car il n'existait pas, malgré l'utilisation this.serviceInstaller.ServiceName plutôt qu'un littéral ...

J'ai finalement trouvé une solution alternative qui utilise la ligne de commande:

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.
la source
0

Le démarrage automatique signifie que le service est automatiquement démarré au démarrage de Windows. Comme d'autres l'ont mentionné, pour le démarrer à partir de la console, vous devez utiliser le ServiceController.

Michael Klement
la source
Je ne souhaite pas faire cela. Je cherche à le faire en une seule fois à partir de la ligne de commande ou à partir des classes de service Windows.
mickyjtwin
Désolé, mon mauvais, j'ai raté le point où vous avez explicitement exclu la possibilité de le démarrer sur le panneau de contrôle.
Michael Klement
0

Vous pouvez utiliser la GetServicesméthode de la classe ServiceController pour obtenir un tableau de tous les services. Ensuite, trouvez votre service en vérifiant la ServiceNamepropriété de chaque service. Lorsque vous avez trouvé votre service, appelez la Startméthode pour le démarrer.

Vous devriez également vérifier la Statuspropriété pour voir dans quel état elle se trouve avant d'appeler start (elle peut être en cours d'exécution, en pause, arrêtée, etc.).

Adrianbanks
la source
0

Vous avez corrompu votre designer. Ajoutez à nouveau votre composant d'installation. Il doit avoir un serviceInstaller et un serviceProcessInstaller. Le serviceInstaller avec la propriété Méthode de démarrage définie sur Automatique démarre une fois installé et après chaque redémarrage.

Guillaume Massé
la source
0

Juste une remarque: vous avez peut-être configuré votre service différemment en utilisant l'interface des formulaires pour ajouter un programme d'installation de service et un programme d'installation de projet. Dans ce cas, remplacez l'endroit où il est indiqué serviceInstaller.ServiceName par "nom du concepteur" .ServiceName.

Vous n'avez pas non plus besoin des membres privés dans ce cas.

Merci pour l'aide.

IanUniacke
la source