Avvia automaticamente un servizio Windows durante l'installazione


119

Ho un servizio Windows che installo utilizzando InstallUtil.exe. Anche se ho impostato il Metodo di avvio su Automatico, il servizio non si avvia una volta installato, devo aprire manualmente i servizi e fare clic su Avvia. C'è un modo per avviarlo tramite la riga di comando o tramite il codice del servizio?

Risposte:


218

Nella tua classe Installer, aggiungi un gestore per l'evento AfterInstall. È quindi possibile chiamare ServiceController nel gestore eventi per avviare il servizio.

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

Ora, quando esegui InstallUtil sul tuo programma di installazione, verrà installato e quindi avvierà il servizio automaticamente.


40
(commento da una modifica proposta): meglio usare serviceInstaller.ServiceName, se il nome del servizio viene modificato, utilizzerà il nome corretto senza bisogno di modificarlo nel codice.
Marc Gravell

1
Inoltre non farebbe male racchiudere il messaggio ServiceControllerin un'istruzione using.
ChrisO

3
Come stai ottenendo serviceInstaller?
Philip Rego

1
serviceInstaller dovrebbe essere la ServiceInstallervariabile nella tua classe. Tale classe deve essere implementata System.Configuration.Install.Installer. Consulta questa guida di msdn per ulteriori informazioni.
Sergio Basurco

4
@PhilipRego Presumibilmente serviceInstallerè l' ServiceInstalleroggetto a cui fa riferimento sendernel gestore eventi, che normalmente viene istanziato nel ServiceInstaller()costruttore. Quindi potresti aggiungere ServiceInstaller serviceInstaller = (ServiceInstaller)sender;prima della usingdichiarazione.
khargoosh

28

Dopo un po 'di refactoring, questo è un esempio di un programma di installazione del servizio Windows completo con avvio automatico:

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

2
Questo codice mi ha dato i seguenti errori: Si è verificata un'eccezione durante la fase di installazione. System.InvalidOperationException: si è verificata un'eccezione nel gestore di eventi OnAfterInstall di System.ServiceProcess.ServiceInstaller. L'eccezione interna System.InvalidOperationException è stata generata con il seguente messaggio di errore: Impossibile avviare il servizio serviceName sul computer "." .. L'eccezione interna System.ComponentModel.Win32Exception è stata generata con il seguente messaggio di errore: Il programma eseguibile per cui questo servizio è configurato run in non implementa il servizio.
goamn

2
Gli errori sequestrati dopo aver commentato la riga "InitializeComponent ()". Credo che questa riga stia duplicando tutte le altre righe poiché i log sembrano mostrare due cose identiche che accadono insieme prima dell'errore: Installazione del servizio serviceName ... Il servizio serviceName è stato installato con successo. Creazione di EventLog source serviceName nel log Applicazione ... Installazione del servizio serviceName ... Creazione di EventLog source serviceName nel log Application ... Si è verificata un'eccezione nel gestore di eventi OnAfterInstall di System.ServiceProcess.ServiceInstaller.
goamn

Mi hai davvero salvato la giornata :) Grazie per questo utile commento. Dopo aver commentato la chiamata InitializeComponent (), anche il mio servizio è iniziato perfettamente
Konstantin,

7

Che ne dici di seguire i comandi?

net start "<service name>"
net stop "<service name>"

Freddo. L'ho scritto nel file batch di installazione subito dopo l'installazione.
M. Fawad Surosh il

5

Opzioni programmatiche per il controllo dei servizi:

  • Il codice nativo può essere utilizzato, "Avvio di un servizio" . Massimo controllo con minime dipendenze ma il massimo lavoro.
  • WMI: Win32_Service dispone di un fileStartService metodo. Ciò è utile nei casi in cui è necessario essere in grado di eseguire altre elaborazioni (ad esempio per selezionare quale servizio).
  • PowerShell: eseguire Start-Servicetramite RunspaceInvokeo creando il proprio Runspacee utilizzando il suo CreatePipelinemetodo per eseguire. Ciò è utile per i casi in cui è necessario essere in grado di eseguire altre elaborazioni (ad esempio per selezionare quale servizio) con un modello di codifica molto più semplice rispetto a WMI, ma dipende da PSH installato.
  • Può utilizzare un'applicazione .NET ServiceController

4

È possibile utilizzare la seguente riga di comando per avviare il servizio:

net start *servicename*

2

Usa ServiceController per avviare il servizio dal codice.

Aggiornamento: E il modo più corretto per avviare il servizio dalla riga di comando è utilizzare il comando "sc" ( Service Controller ) invece di "net".


6
Perché "sc" è un modo "più corretto"? Cosa c'è di sbagliato in "net start" (e nel cmdlet PSH del servizio di avvio)?
Richard

1
Perché sc può essere chiamato da una macchina remota, quindi funziona sempre.
MacGyver

1

Nonostante avessi seguito esattamente la risposta accettata, non ero ancora in grado di avviare il servizio - Mi è stato invece dato un messaggio di errore durante l'installazione che indicava che il servizio che era stato appena installato non poteva essere avviato, poiché non esisteva, nonostante l'utilizzo this.serviceInstaller.ServiceNamepiuttosto di un letterale ...

Alla fine ho trovato una soluzione alternativa che utilizza la riga di comando:

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

0

Avvio automatico significa che il servizio viene avviato automaticamente all'avvio di Windows. Come altri hanno già detto, per avviarlo dalla console è necessario utilizzare ServiceController.


Non desidero farlo. Sto cercando di farlo in una volta sola dalla riga di comando o dalle classi del servizio Windows.
mickyjtwin

Scusa, colpa mia, ho perso il punto in cui hai esplicitamente escluso la possibilità di avviarlo dal pannello di controllo.
Michael Klement,

0

È possibile utilizzare il GetServicesmetodo della classe ServiceController per ottenere un array di tutti i servizi. Quindi, trova il tuo servizio controllando la ServiceNameproprietà di ogni servizio. Quando hai trovato il tuo servizio, chiama il Startmetodo per avviarlo.

Dovresti anche controllare la Statusproprietà per vedere in quale stato si trova già prima di chiamare start (potrebbe essere in esecuzione, in pausa, arrestata, ecc.).


0

Hai corrotto il tuo designer. Aggiungi di nuovo il componente di installazione. Dovrebbe avere un serviceInstaller e un serviceProcessInstaller. Il serviceInstaller con la proprietà Metodo di avvio impostato su Automatico verrà avviato quando installato e dopo ogni riavvio.


0

Solo una nota: potresti aver impostato il tuo servizio in modo diverso utilizzando l'interfaccia dei moduli per aggiungere un programma di installazione del servizio e un programma di installazione del progetto. In tal caso, sostituire dove si dice serviceInstaller.ServiceName con "name from designer" .ServiceName.

Inoltre, in questo caso non sono necessari i membri privati.

Grazie per l'aiuto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.