Wednesday, December 12, 2007 11:21 PM

Chegamos ao último capítulo da série. Até agora já implementamos o monitor de diretórios, o executor de tarefas e ligamos eles à camada de negócios através da controller. No caminho, fizemos uma breve pausa para mostrar como testar a controller. Agora é a hora de finalmente criar o Windows services e juntar todas as peças da solução.

Quem utiliza o VSTS tem a vantagem de ter um template para criar Windows services. Quem utiliza as outras versões do VS, precisa implementar serviço na unha, do zero, como farei aqui.

Começamos criando um novo projeto, do tipo class library, chamado WinServiceSample. Na configuração do projeto, em Project > Properties ..., vamos alterar o output type de “Class library” para “Console Application”. Adicionamos referência à dll System.ServiceProcess. Neste projeto criamos a classe WinService, que herda de System.ServiceProcess.ServiceBase. Esta classe abstrata já nos fornece tudo o que precisamos para que a classe se torne um serviço.

Para colocar o serviço para funcionar temos que sobrescrever dois métodos da classe mãe: OnStart e OnStop. Com eles definimos o que acontece quando o serviço inicia e pára. Outros métodos também podem ser sobrescritos, como OnPause ou OnContinue, mas isto é opcional. Fundamental são os dois primeiros, sem eles, o serviço roda, mas não faz nada.

Utilizamos o método construtor para configurar o serviço e fornecer algumas informações importantes para a infra-estrutura, como o nome do serviço e a definição de quais operações são permitidas.

Por último é necessário criar um método estático main, que será o responsável por criar uma instância de si próprio e incluí-la na lista de serviço, através do método Run da classe ServiceBase.

Este foi todo o código necessário para o serviço. Agora sim vamos implementar a nossa parte, que é colocar o serviço para trabalhar para gente.

Como precisamos do Windsor para criar a instância da controller, precisamos adicionar a referência ao Castle.MicroKernel e Castle.Windsor. Precisamos ainda de duas variáveis, um container, do tipo WindsorContainer e um controller, do tipo IWinSvcController. Depois, no construtor, utilizo o container para instanciar um controller. Por último, simplesmente chamo os métodos Start e Stop da controller nos devidos momentos.

public class WinService : ServiceBase
{
    public static void Main()
    {
        Run(new WinService());
    }

    private readonly IWinSrvController controller;
    private readonly WindsorContainer container = new WindsorContainer(new XmlInterpreter());

    public WinService()
    {
        ServiceName = "Meu servico";
        CanStop = true;
        CanPauseAndContinue = false;
        AutoLog = true;

        controller = container.Resolve<IWinSrvController>();
    }

    protected override void OnStart(string[] args)
    {
        controller.Start();
    }

    protected override void OnStop()
    {
        controller.Stop();
    }
}

Pronto, meu serviço está pronto. Falta pouco para acabar, preciso apenas incluir os instaladores do serviço. No “Solution Explorer” clique com o botão direito sobre a classe WinService e selecione “View designer” . Na janela “Properties” aparecerá um link Add service, não é muito visível, por isto a figura abaixo. Antes de clicar preencha o nome do serviço na propriedade ServiceName, caso contrário ocorrerá um erro no processo.

 

image

 

O VS irá incluir uma classe, com dois componentes, no projeto. No componente ServiceInstaller você deve configurar:

  • Se o seu serviço iniciará manual ou automaticamente.
  • O DisplayName, com o nome que seu serviço terá no Service manager

Clicando no outro componente, ServiceProcessInstaller, você deve configurar:

  • Que usuário irá rodar o serviço e, conseqüentemente, o seu contexto de segurança.

 

image 

 

Compilando a solução tenho em mãos o executável WinService.exe. Mas para este aplicativo ser executado como um Windows service eu preciso instalá-lo e não executá-lo. Para fazer isto utilizo um utilitário do .Net Framework SDK, chamado installutil. Como mostra a figura abaixo, basta chamar o installutil, mandando o caminho para o executável. Para desinstalá-lo, basta adiocionar o parâmetro “/u”.

Na linha seguinte inicio meu serviço com o comando “net start”. Também posso fazer isto através do Service manager, em Start > Administrative Tools > Services.

 

Conclusão

Chegamos ao final da jornada, um pouco mais longa do que alguns esperavam, mas espero que recompensadora. Como resultado, temos uma solução que tem boa capacidade de manutenção e extensão. É inegável que a solução é mais complexa do que simplesmente criar um Windows service e jogar tudo o que você precisa lá dentro. A pergunta é: Você precisa de tudo isto para a sua solução? E resposta só você sabe, pois ela varia caso a caso.

 

< Exemplos >

Comments

At 12/14/2007 11:37 AM, Eduardo Costa said:

# re: Criando um Windows Service em C# - Parte 4 / 4

Oi, Eduardo!
Excelente artigo-em-série. Muito bom mesmo.

Abraço.
At 8/12/2008 4:34 PM, johans said:

# re: Criando um Windows Service em C# - Parte 4 / 4

Olá, gostaria de saber como fazer para que minha aplicação desktop passe como parâmetros para o serviço o diretório a ser monitorado, ou no meu caso a URL a ser chamada de tempo em tempo. receber esses parâmetros da aplicação e grava-las, para depois se o usuario quiser mudar a URL, ele abre a aplicação, muda a URL e reinicia o serviço.

Obrigado
At 9/19/2008 3:12 PM, Luiz Carlos de Paula Junior said:

# re: Criando um Windows Service em C# - Parte 4 / 4

Ola Eduardo, primeiramente foi um ótimo trabalho realizado referente a este tema.

Agora é o seguinte, criei um Windows Service para monitorar certas aplicações, até ai tudo tranquilo. O problema está quando vou levantar alguma aplicação. Pude perceber que toda aplicação executada por um Windows Service se comporta com um Windows Service, ou seja, fica rodando em backgraund, por exemplo, se chamo a Calculadora (Shell("calc.exe", AppWinStyle.MinimizedFocus)) por windows service ela aparece no gerenciador de tarefa como Processo e não como Aplicativo.
Então lhe pergunto, é esse o comportamento normal de uma aplicação chamada por Win.Ser. ou tem algum outro detalhe a fazer????

Um grande abraço...
Luiz
Post Comment
Title *
Name *
Email (never displayed)
Website
Comment * (Allowed tags: blockquote, a, strong, em, p, u, strike, super, sub, code)  
Please add 3 and 3 and type the answer here: