[Delphi] Debugando uma aplicação do “tipo” serviço do Windows

O problema em debugar um TService

Já tentou debugar uma aplicação do tipo serviço do Windows (Windows Services)? Um parto, não é? Eu mesmo já vi uma algumas tentativas bem interessantes: Alimentar um arquivo com os valores das variáveis (.txt, xml, .json… e até gerar logs no gerenciador de log do Windows.

Independente da “solução”, alimentar uma “área” externa é sempre muito trabalhoso, pois geralmente a massa de dados é enorme e nem sempre a informação que você precisa recuperar pode ser representada em forma de texto.

A luz no fim do túnel

Depurar o que acontece dentro das rotinas do form que “implementa” a classe TService não é possível, aceite isso. A execução desse “cara” depende de uma ação dentro do Service Mannger Windows que vai além do nosso famoso “F9”.

Precisamos separar a lógica que será executada em uma unit separada para que ela possa ser adicionada em outros “formulários” e executada a partir de lá.

A variável Application

Implementação inicial do .dpr de uma aplicação do “tipo TService”

Implementação inicial do .dpr de uma aplicação do “tipo VCL Forms Application”

É possível reparar que temos em comum a variável “Application“. Essa variável está presente nas “principais” units desses projetos. No caso “vcl” temos o Vcl.Forms.Application e no “service” temos o “Vcl.Svc.Mgr.

Independente do tipo da aplicação, temos a chamada do método .Run, e é aqui que mora o pulo do gato. O Application do Forms, consegue interagir com a interface gráfica do Windows e essa interação é o que torna possível dispararmos os métodos utilizados na nossa service application, dentro um formulário comum, por exemplo.

Implementando a execução do programa

O grande truque dessa técnica é a execução do programa. Vai ser possível, dentro do mesmo projeto, executarmos a aplicação tanto de forma visual quanto como um serviço. Tudo vai depender de como vamos abrir o aplicativo.

 

Colocando a mão na massa

A esmagadora maioria das aplicações feitas no modo “Windows services” são criadas para executarem uma rotina seguindo uma certa periodicidade. Geralmente o componente da classe TTimer resolve o problema, portanto, vou utiliza-lo no exemplo.

A classe TLogHoras

Lembra que devemos separar a nossa lógica em uma unit independente? Pois então, criei uma classe apenas para resolver o meu problema fictício de gerar logs.

Vou utilizar essa mesma classe para gerar logs na minha aplicação.

Dentro do meu formulário que implementa o TService, adicionei um TTimer com a seguinte implementação:

Feito isso, adicionei um novo arquivo ao projeto [File -> New -> VCL Form – Delphi]. Esse novo arquivo é o formulário onde vamos “emular” o comportamento do serviço e é exatamente ele quem torna o debug da nossa lógica de logs possível.

Depois de adicionar o novo formulário, também adicionei um TTimer nele e simplesmente implementei a mesma rotina do timer usado no TService:

Criei um botão para ativar o timer no formulário:

No modo serviço, esse timer poderia ser iniciado no evento OnStart do serviço:

Como ambos os formulários executam a mesma coisa em seus respectivos timers, teremos o mesmo comportamento: criar uma instancia da classe TLogHoras e chamar o método CriarArquivo.

Parâmetros de inicialização: conheça a função ParamStr

A função ParamStr permite a nós programadores capturarmos os parâmetros enviados na execução do programa através de uma string. Por exemplo, ao executarmos o seguinte comando:

Dentro da aplicação podemos recuperar esses valores acessando seus respectivos índices. Os parâmetros são separados por espaços. Por exemplo, no exemplo dado, os parâmetros são: 1 = -f, 2 = -r e 3 = -d. O índice 0 é reservado para o caminho absoluto do executável.

A diferença na execução

Após a implementação da “mesma lógica” nos dois formulários, devemos mudar a forma em que a aplicação é iniciada. Com o auxílio do ParamStr eu comparei se o primeiro parâmetro de execução tem o valor de -V e caso isso seja verdadeiro, a execução do programa é desviada para dentro do bloco onde o formulário que tem o “poder” de interagir com a camada visual do Windows é instanciado.

Na ausência do parâmetro -V, a aplicação instancia o a classe TService1 e “starta” o serviço do Windows normalmente.

Agora é só adicionar o break na linha desejada, executar no modo debug e aguardar.

Enviando parâmetros de execução através da IDE

O RAD Studio nos permite configurar quais parâmetros informar antes da execução do programa quando executado através da IDE.

No menu Run->Parameters temos a opção Parameters

menu config
Menu de configuração

 

Parâmetro de execução

 

 

 

O objetivo aqui não é abordar a criação de serviços do Windows e seus eventos. A ideia é apresentar uma alternativa viável para debugar uma aplicação do tipo “serviço do Windows” sem muita complicação.

Uma resposta para “[Delphi] Debugando uma aplicação do “tipo” serviço do Windows”

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *