Iniciar automaticamente um serviço do Windows na instalação


119

Eu tenho um serviço do Windows que instalo usando o InstallUtil.exe. Mesmo tendo definido o método de inicialização como automático, o serviço não inicia quando instalado, preciso abrir os serviços manualmente e clicar em iniciar. Existe uma maneira de iniciá-lo através da linha de comando ou através do código do Serviço?

Respostas:


218

Na sua classe Installer, adicione um manipulador para o evento AfterInstall. Você pode chamar o ServiceController no manipulador de eventos para iniciar o serviço.

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

Agora, quando você executa o InstallUtil no seu instalador, ele instala e inicia o serviço automaticamente.


40
(comentário de uma edição proposta): É melhor usar serviceInstaller.ServiceName, se o nome do serviço for alterado, ele usará o nome correto sem precisar alterá-lo no código.
Marc Gravell

1
Também não faria mal envolver a ServiceControllerdeclaração usando.
ChrisO

3
Como você está obtendo o serviceInstaller?
Philip Rego

1
serviceInstaller deve ser a ServiceInstallervariável em sua classe. Essa classe deve ser implementada System.Configuration.Install.Installer. Veja este guia msdn para mais informações.
Sergio Basurco 17/01

4
@PhilipRego Presumivelmente, serviceInstalleré o ServiceInstallerobjeto referido senderno manipulador de eventos, que normalmente é instanciado no ServiceInstaller()construtor. Portanto, você pode adicionar ServiceInstaller serviceInstaller = (ServiceInstaller)sender;antes da usingdeclaração.
Khargoosh

28

Após refatorar um pouco, este é um exemplo de um instalador completo de serviços do Windows com inicialização automática:

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
Esse código me forneceu os seguintes erros: Ocorreu uma exceção durante a fase de instalação. System.InvalidOperationException: ocorreu uma exceção no manipulador de eventos OnAfterInstall do System.ServiceProcess.ServiceInstaller. A exceção interna System.InvalidOperationException foi lançada com a seguinte mensagem de erro: Não é possível iniciar o serviço serviceName no computador '.' .. A exceção interna System.ComponentModel.Win32Exception foi lançada com a seguinte mensagem de erro: O programa executável para o qual este serviço está configurado executar em não implementa o serviço.
Goamn

2
Os erros apreendidos depois que comentei a linha "InitializeComponent ()". Acredito que esta linha esteja duplicando todas as outras linhas, pois os logs parecem mostrar duas coisas idênticas acontecendo juntas antes do erro: Instalando o serviço serviceName ... O serviço serviceName foi instalado com êxito. Criando EventLog de origem serviceName no log Aplicativo ... Instalando o serviço serviceName ... Criando EventLog de origem serviceName no log Aplicativo ... Ocorreu uma exceção no manipulador de eventos OnAfterInstall do System.ServiceProcess.ServiceInstaller.
Goamn

Você realmente salvou meu dia :) Obrigado por este comentário útil. Depois que eu tinha comentado InitializeComponent () chamada, o meu serviço também começou perfeitamente
Konstantin

7

Que tal seguir os comandos?

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

Legal. Eu escrevi isso no meu arquivo em lotes de instalação logo após a instalação.
M. Fawad Surosh 16/01

5

Opções programáticas para controle de serviços:

  • Código nativo pode ser usado, "Iniciando um Serviço" . Controle máximo com dependências mínimas, mas com mais trabalho.
  • WMI: Win32_Service tem um StartServicemétodo Isso é bom para casos em que você precisa executar outro processamento (por exemplo, para selecionar qual serviço).
  • PowerShell: execute Start-Servicevia RunspaceInvokeou criando seu próprio Runspacee usando seu CreatePipelinemétodo para executar. Isso é bom para os casos em que você precisa executar outro processamento (por exemplo, para selecionar qual serviço) com um modelo de codificação muito mais fácil que o WMI, mas depende da instalação do PSH.
  • Um aplicativo .NET pode usar ServiceController

4

Você pode usar a seguinte linha de comando para iniciar o serviço:

net start *servicename*

2

Use ServiceController para iniciar seu serviço a partir do código.

Atualização: E a maneira mais correta de iniciar o serviço na linha de comando é usar o comando "sc" ( Controlador de serviço ) em vez de "net".


6
Por que "sc" é uma maneira "mais correta"? O que há de errado com "net start" (e cmdlet PSH de serviço inicial)?
Richard

1
Como o sc pode ser chamado de uma máquina remota, ele sempre funciona.
MacGyver

1

Apesar de seguir exatamente a resposta aceita, ainda não consegui iniciar o serviço - recebi uma mensagem de falha durante a instalação informando que o serviço recém-instalado não pôde ser iniciado, pois não existia, apesar de usar this.serviceInstaller.ServiceNamebastante do que um literal ...

Acabei encontrando uma solução alternativa que faz uso da linha 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();
    }

0

Inicialização automática significa que o serviço é iniciado automaticamente quando o Windows é iniciado. Como outros já mencionaram, para iniciá-lo no console, você deve usar o ServiceController.


Eu não desejo fazer isso. Eu estou olhando para fazer isso de uma só vez a partir da linha de comando ou de dentro das classes de serviço do Windows.
24710 mickyjtwin

Sinto muito, perdi o ponto em que você excluiu explicitamente a possibilidade de iniciá-lo no painel de controle.
Michael Klement

0

Você pode usar o GetServicesmétodo da classe ServiceController para obter uma matriz de todos os serviços. Em seguida, encontre seu serviço verificando a ServiceNamepropriedade de cada serviço. Quando você encontrar seu serviço, ligue para oStart método para iniciá-lo.

Você também deve verificar a Statuspropriedade para ver em que estado ela já está antes de chamar o início (pode estar em execução, pausado, parado, etc.).


0

Você corrompeu seu designer. Adicione novamente o componente instalador. Ele deve ter um serviceInstaller e um serviceProcessInstaller. O serviceInstaller com a propriedade Startup Method definida como Automatic será inicializado quando instalado e após cada reinicialização.


0

Apenas uma observação: você pode ter configurado seu serviço de maneira diferente usando a interface de formulários para adicionar um instalador de serviço e instalador de projeto. Nesse caso, substitua onde diz serviceInstaller.ServiceName por "name from designer" .ServiceName.

Você também não precisa de membros privados neste caso.

Obrigado pela ajuda.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.