Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este artigo demonstra como criar um aplicativo de serviço do Windows do .NET Framework no Visual Studio. O serviço simplesmente grava mensagens em um log de eventos.
Observação
Este artigo não se aplica aos serviços hospedados no .NET. Para obter o conteúdo mais recente dos serviços Windows usando Microsoft.Extensions.Hosting.BackgroundService e o modelo do Serviço de Trabalho, consulte:
Criar um serviço
Para começar, crie o projeto e defina os valores necessários para que o serviço funcione corretamente.
No menu Arquivo do Visual Studio, selecione Novo>Projeto (ou pressione Ctrl+Shift+N) para abrir a janela Novo Projeto .
Localize e selecione o modelo de projeto Serviço Windows (.NET Framework).
Observação
Se você não vir o modelo do Serviço Windows, talvez seja necessário instalar o workload de Desenvolvimento da Área de Trabalho do .NET via Instalador do Visual Studio.
Para o nome do Projeto, insira MyNewService e, em seguida, selecione Criar.
A guia Design é exibida (Service1.cs [Design] ou Service1.vb [Design]).
O modelo de projeto inclui uma classe de componente chamada
Service1que herda de System.ServiceProcess.ServiceBase. Ele inclui grande parte do código de serviço básico, como o código para iniciar o serviço.
Renomear o serviço
Renomeie o serviço de Service1 para MyNewService.
No Gerenciador de Soluções, selecione Service1.cs ou Service1.vb e escolha Renomear no menu de atalho. Renomeie o arquivo para MyNewService.cs ou MyNewService.vb e pressione Enter.
Uma janela pop-up aparece perguntando se você gostaria de renomear todas as referências para o elemento de código Service1.
Na janela pop-up, selecione Sim.
Selecione Salvar Tudo no menu Arquivo .
Adicionar recursos ao serviço
Nesta seção, você adicionará um log de eventos personalizado ao serviço Windows. O EventLog componente é um exemplo do tipo de componente que você pode adicionar a um serviço windows.
Adicionar funcionalidade de log de eventos personalizado
Na janela Caixa de Ferramentas, expanda Componentes e arraste o componente EventLog para o designer Service1.cs [Design] ou Service1.vb [Design].
Dica
Se você não vir a janela Caixa de Ferramentas, selecione Exibir>Caixa de Ferramentas.
No Gerenciador de Soluções, no menu de atalho para MyNewService.cs ou MyNewService.vb, escolha Exibir Código.
Defina um log de eventos personalizado.
Para C#, edite o construtor existente
MyNewService(), conforme mostrado no snippet de código a seguir. Para o Visual Basic, adicione oNew()construtor conforme mostrado no trecho de código a seguir.public MyNewService() { InitializeComponent(); eventLog1 = new EventLog(); if (!EventLog.SourceExists("MySource")) { EventLog.CreateEventSource("MySource", "MyNewLog"); } eventLog1.Source = "MySource"; eventLog1.Log = "MyNewLog"; }' To access the constructor in Visual Basic, select New from the ' method name drop-down list. Public Sub New() MyBase.New() InitializeComponent() Me.EventLog1 = New System.Diagnostics.EventLog If Not System.Diagnostics.EventLog.SourceExists("MySource") Then System.Diagnostics.EventLog.CreateEventSource("MySource", "MyNewLog") End If EventLog1.Source = "MySource" EventLog1.Log = "MyNewLog" End SubSe ainda não existir, adicione uma
usingdiretiva a MyNewService.cs ou uma instruçãoImportspara MyNewService.vb, para o System.Diagnostics namespace:using System.Diagnostics;Imports System.DiagnosticsSelecione Salvar Tudo no menu Arquivo .
Definir o que ocorre quando o serviço é iniciado
No editor de código para MyNewService.cs ou MyNewService.vb, localize o OnStart método. O Visual Studio criou automaticamente uma definição de método vazia quando você criou o projeto. Adicione um código que grava uma entrada no log de eventos quando o serviço é iniciado:
protected override void OnStart(string[] args)
{
eventLog1.WriteEntry("In OnStart.");
}
' To access the OnStart in Visual Basic, select OnStart from the
' method name drop-down list.
Protected Overrides Sub OnStart(ByVal args() As String)
EventLog1.WriteEntry("In OnStart")
End Sub
Votação
Como um aplicativo de serviço foi projetado para ser de execução longa, ele geralmente sonda ou monitora o sistema, que você configurou no OnStart método. O OnStart método deve retornar ao sistema operacional após o início da operação do serviço para que o sistema não seja bloqueado.
Para configurar um mecanismo de sondeio simples, use o componente System.Timers.Timer. O temporizador gera um Elapsed evento em intervalos regulares, durante o qual seu serviço pode realizar o monitoramento. Use o componente Timer da seguinte maneira:
- Defina as propriedades do Timer componente no
MyNewService.OnStartmétodo. - Inicie o temporizador chamando o Start método.
Configurar o mecanismo de sondagem
Adicione uma
usingdiretiva a MyNewService.cs ou uma instruçãoImportspara MyNewService.vb, para o System.Timers namespace:using System.Timers;Imports System.TimersAdicione o seguinte código no
MyNewService.OnStartevento para configurar o mecanismo de sondagem:// Set up a timer that triggers every minute. Timer timer = new Timer { Interval = 60000 // 60 seconds }; timer.Elapsed += new ElapsedEventHandler(this.OnTimer); timer.Start();' Set up a timer that triggers every minute. Dim timer As Timer = New Timer() timer.Interval = 60000 ' 60 seconds AddHandler timer.Elapsed, AddressOf Me.OnTimer timer.Start()MyNewServiceNa classe, adicione uma variável de membro. Ele contém o identificador do próximo evento a ser gravado no log de eventos:private int eventId = 1;Private eventId As Integer = 1Na classe
MyNewService, adicione o métodoOnTimerpara manipular o evento Timer.Elapsed.public void OnTimer(object sender, ElapsedEventArgs args) { // TODO: Insert monitoring activities here. eventLog1.WriteEntry("Monitoring the System", EventLogEntryType.Information, eventId++); }Private Sub OnTimer(sender As Object, e As Timers.ElapsedEventArgs) ' TODO: Insert monitoring activities here. eventLog1.WriteEntry("Monitoring the System", EventLogEntryType.Information, eventId) eventId = eventId + 1 End Sub
Em vez de executar todo o trabalho no thread principal, você pode executar tarefas usando threads de trabalho em segundo plano. Para obter mais informações, consulte System.ComponentModel.BackgroundWorker.
Definir o que ocorre quando o serviço é interrompido
Insira uma linha de código no OnStop método que adiciona uma entrada ao log de eventos quando o serviço é interrompido:
protected override void OnStop()
{
eventLog1.WriteEntry("In OnStop.");
}
Protected Overrides Sub OnStop()
EventLog1.WriteEntry("In OnStop.")
End Sub
Definir outras ações para o serviço
Você pode sobrescrever os métodos OnPause, OnContinue e OnShutdown para definir processamento adicional para seu componente.
O código a seguir mostra como você pode sobrescrever o método na classe MyNewService.
protected override void OnContinue()
{
eventLog1.WriteEntry("In OnContinue.");
}
Protected Overrides Sub OnContinue()
EventLog1.WriteEntry("In OnContinue.")
End Sub
Definir o status do serviço
Os serviços relatam seu status ao Gerenciador de Controle de Serviços para que um usuário possa informar se um serviço está funcionando corretamente. Por padrão, um serviço que herda de ServiceBase relata um conjunto limitado de configurações de status, que incluem SERVICE_STOPPED, SERVICE_PAUSED e SERVICE_RUNNING. Se um serviço demorar um pouco para ser iniciado, será útil relatar um SERVICE_START_PENDING status.
Você pode implementar as configurações de status SERVICE_START_PENDING e SERVICE_STOP_PENDING adicionando código que chama a função Windows SetServiceStatus.
Adicione uma
usingdiretiva a MyNewService.cs ou uma instruçãoImportspara MyNewService.vb, para o System.Runtime.InteropServices namespace:using System.Runtime.InteropServices;Imports System.Runtime.InteropServicesAdicione a seguinte enumeração e estrutura a MyNewService.cs, ou MyNewService.vb, para declarar os
ServiceStatevalores e adicionar uma estrutura para o status, que você usará em uma chamada de invocação de plataforma:public enum ServiceState { SERVICE_STOPPED = 0x00000001, SERVICE_START_PENDING = 0x00000002, SERVICE_STOP_PENDING = 0x00000003, SERVICE_RUNNING = 0x00000004, SERVICE_CONTINUE_PENDING = 0x00000005, SERVICE_PAUSE_PENDING = 0x00000006, SERVICE_PAUSED = 0x00000007, } [StructLayout(LayoutKind.Sequential)] public struct ServiceStatus { public int dwServiceType; public ServiceState dwCurrentState; public int dwControlsAccepted; public int dwWin32ExitCode; public int dwServiceSpecificExitCode; public int dwCheckPoint; public int dwWaitHint; };Public Enum ServiceState SERVICE_STOPPED = 1 SERVICE_START_PENDING = 2 SERVICE_STOP_PENDING = 3 SERVICE_RUNNING = 4 SERVICE_CONTINUE_PENDING = 5 SERVICE_PAUSE_PENDING = 6 SERVICE_PAUSED = 7 End Enum <StructLayout(LayoutKind.Sequential)> Public Structure ServiceStatus Public dwServiceType As Long Public dwCurrentState As ServiceState Public dwControlsAccepted As Long Public dwWin32ExitCode As Long Public dwServiceSpecificExitCode As Long Public dwCheckPoint As Long Public dwWaitHint As Long End StructureObservação
O Service Control Manager usa os membros
dwWaitHintedwCheckpointda estrutura SERVICE_STATUS para determinar quanto tempo esperar para que um serviço Windows iniciar ou desligar. Se os métodosOnStarteOnStopforem longos, o seu serviço poderá solicitar mais tempo chamandoSetServiceStatusnovamente com um valordwCheckPointincrementado.MyNewServiceNa classe, declare a função SetServiceStatus usando a invocação de plataforma:[DllImport("advapi32.dll", SetLastError = true)] private static extern bool SetServiceStatus(System.IntPtr handle, ref ServiceStatus serviceStatus);Declare Auto Function SetServiceStatus Lib "advapi32.dll" (ByVal handle As IntPtr, ByRef serviceStatus As ServiceStatus) As BooleanPara implementar o
SERVICE_START_PENDINGstatus, adicione o seguinte código ao início do OnStart método:// Update the service state to Start Pending. ServiceStatus serviceStatus = new ServiceStatus { dwCurrentState = ServiceState.SERVICE_START_PENDING, dwWaitHint = 100000 }; SetServiceStatus(this.ServiceHandle, ref serviceStatus);' Update the service state to Start Pending. Dim serviceStatus As ServiceStatus = New ServiceStatus() serviceStatus.dwCurrentState = ServiceState.SERVICE_START_PENDING serviceStatus.dwWaitHint = 100000 SetServiceStatus(Me.ServiceHandle, serviceStatus)Adicione código ao final do
OnStartmétodo para definir o status comoSERVICE_RUNNING:// Update the service state to Running. serviceStatus.dwCurrentState = ServiceState.SERVICE_RUNNING; SetServiceStatus(this.ServiceHandle, ref serviceStatus);' Update the service state to Running. serviceStatus.dwCurrentState = ServiceState.SERVICE_RUNNING SetServiceStatus(Me.ServiceHandle, serviceStatus)(Opcional) Se OnStop for um método de execução longa, repita este procedimento no
OnStopmétodo. Implemente oSERVICE_STOP_PENDINGstatus e retorne oSERVICE_STOPPEDstatus antes que oOnStopmétodo seja encerrado.Por exemplo:
// Update the service state to Stop Pending. ServiceStatus serviceStatus = new ServiceStatus { dwCurrentState = ServiceState.SERVICE_STOP_PENDING, dwWaitHint = 100000 }; SetServiceStatus(this.ServiceHandle, ref serviceStatus); // Update the service state to Stopped. serviceStatus.dwCurrentState = ServiceState.SERVICE_STOPPED; SetServiceStatus(this.ServiceHandle, ref serviceStatus);' Update the service state to Stop Pending. Dim serviceStatus As ServiceStatus = New ServiceStatus() serviceStatus.dwCurrentState = ServiceState.SERVICE_STOP_PENDING serviceStatus.dwWaitHint = 100000 SetServiceStatus(Me.ServiceHandle, serviceStatus) ' Update the service state to Stopped. serviceStatus.dwCurrentState = ServiceState.SERVICE_STOPPED SetServiceStatus(Me.ServiceHandle, serviceStatus)
Adicionar instaladores ao serviço
Antes de executar um serviço Windows, você precisa instalá-lo, que o registra no Service Control Manager. Adicione instaladores ao seu projeto para lidar com os detalhes do registro.
No Gerenciador de Soluções, no menu de atalho para MyNewService.cs ou MyNewService.vb, escolha Designer de Exibição.
No modo design , selecione a área em segundo plano e, em seguida, escolha Adicionar Instalador no menu de atalho.
Por padrão, o Visual Studio adiciona uma classe de componente chamada
ProjectInstaller, que contém dois instaladores, ao seu projeto. Esses instaladores são para seu serviço e para o processo associado ao serviço.No modo design do ProjectInstaller, selecione serviceInstaller1 para um projeto C# ou ServiceInstaller1 para um projeto do Visual Basic e escolha Propriedades no menu de atalho.
Na janela Propriedades , defina a ServiceName propriedade como MyNewService.
Adicione texto à Description propriedade, como um serviço de exemplo.
Esse texto aparece na coluna Descrição da janela Serviços e descreve o serviço para o usuário.
Adicione texto à propriedade DisplayName. Por exemplo, Nome de Exibição MyNewService.
Esse texto aparece na coluna Nome de Exibição da janela Serviços . Esse nome pode ser diferente da ServiceName propriedade, que é o nome que o sistema usa (por exemplo, o nome usado para o
net startcomando iniciar seu serviço).Defina a propriedade StartType como Automatic na lista suspensa.
Quando terminar, as janelas Propriedades deverão ser semelhantes à seguinte figura:
No modo design do ProjectInstaller, escolha serviceProcessInstaller1 para um projeto C# ou ServiceProcessInstaller1 para um projeto do Visual Basic e escolha Propriedades no menu de atalho. Defina a propriedade Account para LocalSystem da lista suspensa.
Essa configuração instala o serviço e o executa usando a conta do sistema local.
Importante
A LocalSystem conta tem permissões amplas, incluindo a capacidade de registrar no log de eventos. Use essa conta com cuidado, pois pode aumentar o risco de ataques de software mal-intencionado. Para outras tarefas, considere usar a LocalService conta, que atua como um usuário sem privilégios no computador local e apresenta credenciais anônimas para qualquer servidor remoto. No entanto, este exemplo falhará se você tentar usar a LocalService conta, pois ela precisa de permissão para gravar no log de eventos.
Para obter mais informações sobre instaladores, consulte Como adicionar instaladores ao seu aplicativo de serviço.
(Opcional) Definir parâmetros de inicialização
Observação
Antes de decidir adicionar parâmetros de inicialização, considere se é a melhor maneira de passar informações para seu serviço. Embora sejam fáceis de usar e analisar, e um usuário possa substituí-los facilmente, pode ser mais difícil para um usuário descobrir e usar sem documentação. Em geral, se o serviço exigir mais do que apenas alguns parâmetros de inicialização, você deverá usar o registro ou um arquivo de configuração.
Um serviço windows pode aceitar argumentos de linha de comando, também conhecidos como parâmetros de inicialização. Quando você adiciona código para processar parâmetros de inicialização, um usuário pode iniciar seu serviço com seus próprios parâmetros de inicialização personalizados na janela de propriedades do serviço. No entanto, esses parâmetros de inicialização não serão persistidos na próxima vez que o serviço for iniciado.
Para definir parâmetros de inicialização permanentemente, defina-os no Registro. Cada serviço windows tem uma entrada de registro na subchave HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services . Na subchave de cada serviço, use a subchave Parâmetros para armazenar informações que seu serviço pode acessar. Você pode usar arquivos de configuração de aplicativo para um serviço Windows da mesma maneira que faz para outros tipos de programas. Para obter o código de exemplo, consulte ConfigurationManager.AppSettings.
Para adicionar parâmetros de inicialização
Em MyNewService.cs ou MyNewService.vb, altere o
MyNewServiceconstrutor para aceitar e processar um parâmetro de entrada:public MyNewService(string[] args) { InitializeComponent(); string eventSourceName = "MySource"; string logName = "MyNewLog"; if (args.Length > 0) { eventSourceName = args[0]; } if (args.Length > 1) { logName = args[1]; } eventLog1 = new EventLog(); if (!EventLog.SourceExists(eventSourceName)) { EventLog.CreateEventSource(eventSourceName, logName); } eventLog1.Source = eventSourceName; eventLog1.Log = logName; }Public Sub New(ByVal cmdArgs() As String) InitializeComponent() Dim eventSourceName As String = "MySource" Dim logName As String = "MyNewLog" If (cmdArgs.Count() > 0) Then eventSourceName = cmdArgs(0) End If If (cmdArgs.Count() > 1) Then logName = cmdArgs(1) End If eventLog1 = New EventLog() If (Not EventLog.SourceExists(eventSourceName)) Then EventLog.CreateEventSource(eventSourceName, logName) End If eventLog1.Source = eventSourceName eventLog1.Log = logName End SubEsse código define a origem do evento e o nome do log de acordo com os parâmetros de inicialização fornecidos pelo usuário. Se nenhum argumento for fornecido, ele usará valores padrão.
Selecione Program.cs ou MyNewService.Designer.vb e escolha Exibir Código no menu de atalho.
MainNo método, altere o código para adicionar um parâmetro de entrada e passá-lo para o construtor de serviço:static void Main(string[] args) { ServiceBase[] ServicesToRun; ServicesToRun = new ServiceBase[] { new MyNewService(args) }; ServiceBase.Run(ServicesToRun); }Shared Sub Main(ByVal cmdArgs() As String) Dim ServicesToRun() As System.ServiceProcess.ServiceBase = New System.ServiceProcess.ServiceBase() {New MyNewService(cmdArgs)} System.ServiceProcess.ServiceBase.Run(ServicesToRun) End SubPara especificar os argumentos de linha de comando, adicione o seguinte código à
ProjectInstallerclasse em ProjectInstaller.cs ou ProjectInstaller.vb:protected override void OnBeforeInstall(IDictionary savedState) { string parameter = "MySource1\" \"MyLogFile1"; Context.Parameters["assemblypath"] = "\"" + Context.Parameters["assemblypath"] + "\" \"" + parameter + "\""; base.OnBeforeInstall(savedState); }Protected Overrides Sub OnBeforeInstall(ByVal savedState As IDictionary) Dim parameter As String = "MySource1"" ""MyLogFile1" Context.Parameters("assemblypath") = """" + Context.Parameters("assemblypath") + """ """ + parameter + """" MyBase.OnBeforeInstall(savedState) End SubNormalmente, esse valor contém o caminho completo do executável do serviço Windows. Para que o serviço seja iniciado corretamente, o usuário deve utilizar aspas para o caminho e cada parâmetro individual. Um usuário pode alterar os parâmetros na entrada do Registro imagepath para alterar os parâmetros de inicialização do serviço Windows. No entanto, uma maneira melhor é alterar o valor programaticamente e expor a funcionalidade de maneira amigável, como usando um utilitário de configuração ou gerenciamento.
Construir o serviço
No Gerenciador de Soluções, escolha Propriedades no menu de atalho do projeto MyNewService .
Na guia Aplicativo , na lista de objetos de inicialização, escolha MyNewService.Program (ou Sub-Main para projetos do Visual Basic).
Para criar o projeto, no Gerenciador de Soluções, escolha Compilar no menu de atalho do projeto (ou pressione Ctrl+Shift+B).
Instalar o serviço
Agora que você criou o serviço Windows, você pode instalá-lo. Para instalar um serviço Windows, você deve ter credenciais de administrador no computador em que ele está instalado.
Abra o Prompt de Comando do Desenvolvedor para Visual Studio com credenciais administrativas.
No Prompt de Comando do Desenvolvedor para Visual Studio, navegue até a pasta que contém a saída do projeto (por padrão, o subdiretório \bin\Debug do seu projeto).
Insira o seguinte comando:
installutil MyNewService.exeSe o serviço for instalado com êxito, o comando relatará êxito.
Se o sistema não encontrar installutil.exe, verifique se ele existe no computador. Essa ferramenta é instalada com o .NET Framework na pasta %windir%\Microsoft.NET\Framework[64]\<framework version>.
Se o processo deinstallutil.exe falhar, verifique o log de instalação para descobrir o motivo. Por padrão, o log está na mesma pasta que o executável do serviço. A instalação poderá falhar se:
- A RunInstallerAttribute classe não está presente na
ProjectInstallerclasse. - O atributo não está definido como
true. - A
ProjectInstallerclasse não está definida comopublic. - Você não abriu o Prompt de Comando do Desenvolvedor para VS como administrador.
- A RunInstallerAttribute classe não está presente na
Para obter mais informações, consulte Como instalar e desinstalar serviços.
Iniciar e executar o serviço
No Windows, abra o aplicativo da área de trabalho dos Serviços : pressione o Windows+R para abrir a caixa Executar , insira services.msc e pressione Enter ou selecione OK.
Você deverá ver seu serviço listado em Serviços, exibido em ordem alfabética pelo nome de exibição que você definiu para ele.
Para iniciar o serviço, escolha Iniciar no menu de atalho do serviço.
Para interromper o serviço, escolha Parar no menu de atalho do serviço.
(Opcional) Na linha de comando, use os comandos net start <service name> e net stop <service name> para iniciar e parar o seu serviço.
Verifique a saída do log de eventos do seu serviço
No Windows, abra o aplicativo da área de trabalho do Visualizador de Eventos : insira o Visualizador de Eventos na barra de pesquisa do Windows e selecione Visualizador de Eventos nos resultados da pesquisa.
Dica
No Visual Studio, você pode acessar logs de eventos abrindo o Gerenciador de Servidores no menu Exibir (ou pressione Ctrl+Alt+S) e expandindo o nó Logs de Eventos para o computador local.
No Visualizador de Eventos, expanda os Logs de Aplicativos e Serviços.
Localize a listagem para MyNewLog (ou MyLogFile1 se você seguiu o procedimento para adicionar argumentos de linha de comando) e expanda-o. Você deve ver as entradas das duas ações (iniciar e parar) executadas pelo seu serviço.
Limpar os recursos
Se você não precisar mais do aplicativo de serviço do Windows, poderá removê-lo.
Abra o Prompt de Comando do Desenvolvedor para Visual Studio com credenciais administrativas.
Na janela Prompt de Comando do Desenvolvedor para Visual Studio, navegue até a pasta que contém o executável do seu projeto.
Insira o seguinte comando:
installutil.exe /u MyNewService.exeSe o serviço for desinstalado com êxito, o comando relatará que o serviço foi removido com êxito. Para obter mais informações, consulte Como instalar e desinstalar serviços.
Próximas etapas
Agora que você criou o serviço, você pode:
Crie um programa de instalação autônomo para outras pessoas usarem para instalar o serviço Windows. Use o Conjunto de Ferramentas do WiX para criar um instalador para um serviço windows. Para outras ideias, consulte Criar um pacote do instalador.
Explore o ServiceController componente, que permite enviar comandos para o serviço que você instalou.
Em vez de criar o log de eventos quando o aplicativo for executado, use um instalador para criar um log de eventos ao instalar o aplicativo. O log de eventos é excluído pelo instalador quando você desinstala o aplicativo. Para obter mais informações, consulte EventLogInstaller.