Iniciar automáticamente un servicio de Windows en la instalación

119

Tengo un servicio de Windows que instalo usando InstallUtil.exe. Aunque configuré el Método de inicio en Automático, el servicio no se inicia cuando se instala, tengo que abrir manualmente los servicios y hacer clic en Iniciar. ¿Hay alguna forma de iniciarlo a través de la línea de comandos o mediante el código del Servicio?

mickyjtwin
fuente

Respuestas:

218

En su clase Installer, agregue un controlador para el evento AfterInstall. A continuación, puede llamar al ServiceController en el controlador de eventos para iniciar el servicio.

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

Ahora, cuando ejecute InstallUtil en su instalador, se instalará y luego iniciará el servicio automáticamente.

codemonkey
fuente
40
(comentario de una edición propuesta): Es mejor usar serviceInstaller.ServiceName, si se cambia el nombre del servicio, usará el nombre correcto sin necesidad de cambiarlo en el código.
Marc Gravell
1
Tampoco estaría de más envolver el ServiceControlleren una declaración de uso.
ChrisO
3
¿Cómo está obteniendo serviceInstaller?
Philip Rego
1
Se supone que serviceInstaller es la ServiceInstallervariable de su clase. Tal clase se implementará System.Configuration.Install.Installer. Consulte esta guía de msdn para obtener más información.
Sergio Basurco
4
@PhilipRego Presumiblemente serviceInstalleres el ServiceInstallerobjeto al que se hace referencia senderen el controlador de eventos, que normalmente se instancia en el ServiceInstaller()constructor. Por lo tanto, puede agregar ServiceInstaller serviceInstaller = (ServiceInstaller)sender;antes de la usingdeclaración.
khargoosh
28

Después de refactorizar un poco, este es un ejemplo de un instalador de servicios de Windows completo con inicio automático:

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
fuente
2
Este código me dio los siguientes errores: Se produjo una excepción durante la fase de instalación. System.InvalidOperationException: se produjo una excepción en el controlador de eventos OnAfterInstall de System.ServiceProcess.ServiceInstaller. La excepción interna System.InvalidOperationException fue lanzada con el siguiente mensaje de error: No se puede iniciar el servicio serviceName en la computadora '.' .. La excepción interna System.ComponentModel.Win32Exception se lanzó con el siguiente mensaje de error: El programa ejecutable para el que está configurado este servicio run in no implementa el servicio.
goamn
2
Los errores se incautaron una vez que comenté la línea "InitializeComponent ()". Creo que esta línea está duplicando todas las demás líneas, ya que los registros parecen mostrar dos cosas idénticas que suceden juntas antes del error: Instalando el servicio serviceName ... Service serviceName se ha instalado correctamente. Creando la fuente de EventLog serviceName en la aplicación de registro ... Instalando el servicio serviceName ... Creando la fuente de EventLog serviceName en la aplicación de registro ... Se produjo una excepción en el controlador de eventos OnAfterInstall de System.ServiceProcess.ServiceInstaller.
goamn
Realmente me salvaste el día :) Gracias por este útil comentario. Después de haber comentado la llamada InitializeComponent (), mi servicio también comenzó perfectamente
Konstantin
7

¿Qué hay de seguir los comandos?

net start "<service name>"
net stop "<service name>"
Hemant
fuente
Frio. Escribí esto en mi archivo por lotes de instalación justo después de que finalice la instalación.
M. Fawad Surosh
5

Opciones programáticas para controlar los servicios:

  • Se puede utilizar código nativo, "Iniciar un servicio" . Máximo control con mínimas dependencias pero más trabajo.
  • WMI: Win32_Service tiene unaStartService método. Esto es bueno para los casos en los que necesita poder realizar otro procesamiento (por ejemplo, para seleccionar qué servicio).
  • PowerShell: ejecute Start-Servicemediante RunspaceInvokeo creando el suyo propio Runspacey utilizando su CreatePipelinemétodo para ejecutar. Esto es bueno para los casos en los que necesita poder realizar otro procesamiento (por ejemplo, para seleccionar qué servicio) con un modelo de codificación mucho más fácil que WMI, pero depende de la instalación de PSH.
  • Una aplicación .NET puede usar ServiceController
Ricardo
fuente
4

Puede utilizar la siguiente línea de comando para iniciar el servicio:

net start *servicename*
AlexDrenea
fuente
2

Utilice ServiceController para iniciar su servicio desde el código.

Actualización: Y la forma más correcta de iniciar el servicio desde la línea de comandos es usar el comando "sc" ( controlador de servicio ) en lugar de "net".

árbitro
fuente
6
¿Por qué "sc" es una forma "más correcta"? ¿Qué hay de malo con "net start" (y el cmdlet PSH de inicio del servicio)?
Richard
1
Debido a que sc se puede llamar desde una máquina remota, siempre funciona.
MacGyver
1

A pesar de seguir exactamente la respuesta aceptada, todavía no pude hacer que el servicio se iniciara; en cambio, recibí un mensaje de falla durante la instalación que indicaba que el servicio que se acababa de instalar no se podía iniciar, ya que no existía, a pesar de usar this.serviceInstaller.ServiceName más bien que un literal ...

Finalmente encontré una solución alternativa que hace uso de la línea de 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();
    }
Matsu Q.
fuente
0

El inicio automático significa que el servicio se inicia automáticamente cuando se inicia Windows. Como han mencionado otros, para iniciarlo desde la consola debe usar ServiceController.

Michael Klement
fuente
No deseo hacer esto. Estoy buscando hacer esto de una vez desde la línea de comandos o desde las clases de servicio de Windows.
mickyjtwin
Lo siento, mal, me perdí el punto en el que excluyó explícitamente la posibilidad de iniciarlo desde el panel de control.
Michael Klement
0

Puede utilizar el GetServicesmétodo de la clase ServiceController para obtener una matriz de todos los servicios. Luego, encuentre su servicio marcando la ServiceNamepropiedad de cada servicio. Cuando haya encontrado su servicio, llame al Startmétodo para iniciarlo.

También debe verificar la Statuspropiedad para ver en qué estado ya se encuentra antes de llamar al inicio (puede estar en ejecución, en pausa, detenido, etc.).

adrianbanks
fuente
0

Corrompiste a tu diseñador. Vuelva a agregar su componente de instalación. Debe tener un serviceInstaller y un serviceProcessInstaller. El serviceInstaller con la propiedad Método de inicio establecido en Automático se iniciará cuando se instale y después de cada reinicio.

Guillaume Massé
fuente
0

Solo una nota: es posible que haya configurado su servicio de manera diferente utilizando la interfaz de formularios para agregar un instalador de servicios y un instalador de proyectos. En ese caso, reemplace donde dice serviceInstaller.ServiceName con "nombre del diseñador" .ServiceName.

Tampoco necesita los miembros privados en este caso.

Gracias por la ayuda.

IanUniacke
fuente