Desenvolvimento - C#

Criando um Windows Service

Neste artigo veremos os conceitos de um Windows Service (serviço do Windows) e aprenderemos a criar um, que irá gravar em um arquivo texto de log toda vez que este serviço for iniciado e/ou parado pelo usuário. Acompanhem.

por Wellington Balbo de Camargo



Olá pessoal, neste artigo mostrarei como criar um serviço do Windows, de forma simples e rápida, que irá gravar em um arquivo de log quando o serviço for iniciado e quando ele for parado.

Faço este artigo com base na videoaula de Luiz Maia, do Portal Linha de Código, mediante autorização do mesmo. Acompanhem o passo-a-passo:

Para criarmos este serviço, usaremos a linguagem C#, o .NET Framework 3.5,  o namespace System.IO e o utilitário de instalação InstallUtil. Usaremos também os métodos OnStart e OnStop para criarmos nosso arquivo de log.

Como o Windows Service, como o próprio nome diz, é um serviço do Windows, ele não tem interface e roda em segundo plano em nossa máquina. Uma observação a se fazer é que o Windows Service não roda nos sistemas operacionais Windows 95, 98 e ME. Roda a partir do NT e 2000.

O Windows Service é essencial quando desejarmos monitorar o teclado, arquivos e pastas ou mesmo criar arquivos de log (que é o que faremos) quando determinados eventos ocorrerem. Ele roda em perfeita harmonia com o sistema operacional e usa um gerenciador de serviços. Para acessarmos este gerenciador no Windows XP, abra o menu Iniciar e clique em Executar ou tecle Windows + R e digite services.msc para que o gerenciador se abra:

Aqui vemos todos os serviços do sistema operacional, perceba que nem todos estão com o status Iniciado.

Abra o Visual Studio, vá em File > New Project (CTRL + SHIFT + N), escolha o template Windows Service, dê o nome de ExemploWindowsService e clique em OK.

Na tela que aparece, clique em cima da mensagem click here to switch to code view para ir à tela de códigos. Nela você verá os métodos OnStart e OnStop, são neles que iremos codificar. Antes disso, declare o namespace System.IO:

using System.IO;

Agora crie uma variável global, fora de qualquer método, do tipo da classe StreamWriter, que será nosso arquivo de log:

StreamWriter arquivoLog;

Agora no método OnStart, digite o seguinte código:

protected override void OnStart(string[] args)

        {

            //Instancie a variável criada, que receberá como parâmetro o caminho de meu arquivo de texto,

            //que será o log destes eventos do meu serviço, e o parâmetro encoding com o valor true.

            arquivoLog = new StreamWriter(@"C:\testeLog.txt", true);

            //Escrevo no arquivo texto no momento que o arquivo for iniciado

            arquivoLog.WriteLine("Serviço iniciado em: " + DateTime.Now);

            //Limpo o buffer com o método Flush

            arquivoLog.Flush();

        }

Assim, quando eu iniciar meu serviço pelo gerenciador de serviços (ou quando o sistema operacional for iniciado) será criado o arquivo testeLog.txt e escrito uma linha com a hora exata em que o serviço foi iniciado. Perceba que não fechamos o arquivo para que o mesmo torne-se acessível ao método OnStop, que codificaremos a seguir.

Agora no método OnStop, digite o seguinte código:

protected override void OnStop()

        {

            //Escrevo no arquivo texto no momento exato que o arquivo for encerrado

            arquivoLog.WriteLine("Serviço encerrado em: " + DateTime.Now);

            //Fecho o arquivo com o método Close

            arquivoLog.Close();

        }

Agora sim, neste método escrevo uma linha no momento que o serviço for finalizado e chamo o método Close() para fechar o arquivo.

Se mandarmos executar o projeto não será suficiente para vermos nosso serviço rodando, já que ele é um serviço, ou seja, não tem interface alguma. Precisamos instalá-lo e iniciá-lo para que o mesmo entre em ação.

Vamos então criar um instalador. Para isso, volte ao modo Design, clique com o botão direito em qualquer parte cinza da tela e clique em Add Installer. Será gerado dois componentes, um que é o instalador de processos de serviços e outro que é o instalador de serviços:

Quando o Windows instala um serviço ele usa um contexto, que é o de determinar quais privilégios este serviço pode e deve usar. Então precisamos incluir em nosso projeto a uma conta de sistema, que será o contexto que o Windows necessita para instalar o serviço. Os tipos de contas existentes são:

- Local Service – direciona o Windows para rodar o serviço no contexto de uma conta no sistema local que pode ter privilégios estendidos.

- Network Service – direciona o Windows para rodar o serviço no contexto de uma conta sem privilégios no sistema local. O serviço apresentará as credenciais a um servidor remoto (usado com vários computadores em uma rede, por exemplo).

- Local System – direciona o Windows para rodar o serviço no contexto de uma conta sem privilégios no sistema local. O serviço apresentará credenciais anônimas para o servidor remoto.

- User – direciona o Windows para rodar o serviço no contexto que solicita ao usuário um nome e senha válidos a cada momento que o serviço rodar.

Neste exemplo iremos usar a conta Local System.

Aperte F4 em cima do serviceInstaller1 e altere as propriedades DisplayName e ServiceName para ExemploServico, que será o nome do nosso serviço, que será exibido no gerenciador de serviços.

Aperte F4 em cima do serviceProcessInstaller1 e altere a propriedade Account para Local System, que será o tipo de conta que explicamos anteriormente.

Agora compile sua aplicação apertando CTRL + SHIFT + B.

Para instalarmos nosso serviço, temos que usar o InstallUtil, utilitário específico do .NET para instalar serviços no Windows. Ele se encontra na pasta do .NET Framework. Então, vá em Iniciar e clique em Executar e digite cmd para abrirmos o prompt de comando do MS-DOS.

Nele digite cd\ para irmos à raiz de nossa unidade. Nela digite o seguinte:

Acima digitei cd + o caminho para se chegar a pasta em que está meu utilitário InstallUtil, e na linha de baixo digitei o nome dele e teclei Enter.

Será apresentada uma lista de opções deste utilitário. Para instalarmos nosso serviço, temos que ir a pasta em que o mesmo foi compilado, dentro da pasta Debug, que por sua vez fica dentro da pasta Bin, que por sua vez fica dentro da pasta do seu projeto do Visual Studio, que nesse exemplo é a ExemploWindowsService. Dentro desta pasta arraste o executável para a janela de comando, não esquecendo de digitar installutil antes do caminho do arquivo. Seu prompt deverá ficar assim:

Pronto, serviço instalado. Agora vá ao gerenciador de serviços e procure pelo nome de seu serviço. Quando achá-lo clique em Iniciar do lado esquerdo ou clique com o botão direito em cima do serviço e clique em Iniciar.

Agora vá à raiz da unidade C: e veja que foi criado o arquivo testeLog.txt, abra-o e veja o texto:

Podemos perceber que o log funciona corretamente. Agora volte ao gerenciador de serviços, clique com o botão direito em cima do seu serviço e clique em Parar.

Abra novamente o testeLog.txt e veja a mensagem:

Se quisermos desinstalar este serviço, é só usar a mesma linha de código que usamos para instalá-lo, só com o adicional /u após o installutil, ficando assim:

Após a execução do comando acima, deverá aparecer no final esta mensagem:

Observação importante: se você tem o serviço instalado e deseja realizar alguma modificação nele, via código, é necessária que o serviço seja parado, a janela do gerenciador de serviços seja fechada, que seja desinstalado o serviço para só assim poder instalá-lo novamente com as modificações. Outra coisa: devemos evitar usar qualquer tipo de interface com o usuário, já que o serviço é feito exclusivamente para ser rodado em “segundo plano”, totalmente oculto da visão do usuário.

Assim finalizo o artigo.

Para quem se interessar, disponibilizo o código fonte desse projeto aqui.

Créditos à Luiz Maia, que fez as videoaulas e ao Portal Linha de Código, por onde pude baixá-las (mediante assinatura), estudá-las e posteriormente fazer este artigo.

Quaisquer dúvidas mandem emails para wellingtonbalbo@gmail.com ou deixem nos comentários deste artigo que responderei o mais rápido possível.

Até o próximo artigo

Wellington Balbo de Camargo

Wellington Balbo de Camargo - Desenvolvedor Web/Desktop em .NET, com pouco mais de 1 ano de experiência na área. Cursando o 4º Semestre de Análise de Sistemas, atualmente estuda para melhorar os conhecimentos em SQL Server e ASP.NET, buscando em um futuro próximo as certificações Microsoft nessas áreas. Mantém um blog com dicas e artigos para iniciantes em .NET no endereço http://programandodotnet.wordpress.com e nas horas vagas procura ajudar e aprender com o pessoal do Fórum daMSDN. Atualmente é editor de artigos da Linha de Código.