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?

mickyjtwin
fonte

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.

codemonkey
fonte
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();
    }
}
}
Pedro Pereira
fonte
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>"
Hemant
fonte
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
Richard
fonte
4

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

net start *servicename*
AlexDrenea
fonte
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".

árbitro
fonte
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();
    }
Matsu Q.
fonte
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.

Michael Klement
fonte
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.).

adrianbanks
fonte
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.

Guillaume Massé
fonte
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.

IanUniacke
fonte