Service applications usando Delphi
Criando um serviço do windows podemos passar a responsabilidade de iniciar a aplicação para o próprio windows, deixando de ter a intervenção do usuário.
Vamos fazer um exemplo de um serviço que gera logs dos eventos disponível nele.
Então vamos começar basta ir em File >> New >> Other >> Delphi Projects >> Service Application:
Salve tudo projeto. O nome da Unit para Sistema e o Projeto para Log. Sua aplicação deverá ficar de acordo com a figura abaixo
Essa Unit criada contem uma espécie de DataModule que possui alguns eventos e propriedades cruciais para o funcionamento do serviço. Vejamos alguns dos principais funcionalidades:
Os eventos mais importantes são:
- OnStart: Este evento é executado assim que o serviço é iniciado.
- OnExecute: Este é o evento onde será implementado a funcionalidade do serviço, ele é executado logo após o evento OnStart, ou seja, quando o serviço entrar em execução definitiva. Funciona semelhante ao execute das threads.
- OnStop: Este evento é executado assim que o serviço é parado.
- OnPause: Este evento é executado quando o serviço é pausado.
- OnContinue: Este evento é executando quando o serviço voltar a ser executado após uma pausa.
Eventos de instalação do serviço:
- BeforeInstall / AfterInstall: Eventos executados antes (before) ou depois (after) da instalação do serviço
Propriedades cruciais para o bom funcionamento de um serviço do windows:
- StartType: Esta propriedade define o modo de iniciação do serviço, por padrão essa opção vem marcada como stAuto que significa que o serviço será iniciado junto com o windows. Além da opção stAuto destaco a opção stManual que define que o serviço deverá ser iniciado manualmente e a opção stDisabled que define que somente um administrador pode iniciar o serviço.
- DisplayName: Esta propriedade define o nome que será apresentado para o serviço no gerenciador de serviços do windows.
- Dependencies: Define uma lista de dependências para a execução do serviço, ou seja, o serviço só será iniciado se todas as suas dependências (outros serviços) já estejam iniciados.
Então vamos começar a desenvolver:
Na propriedade DisplayName vamos colocar o nome do serviço que irá aparecer no Gerenciar de Serviços após sua execução.
Caso seja necessário que o serviço seja executado com credencias de um usuário que tem privilégios especiais você deverá informar o conteúdo das propriedades ServiceStartName (nome do usuário) e Password (sua senha).
const LOCAL_LOG = 'C:\Log.Text';
Agora que fizemos a função que ira gravar o Log, vamos implementar os eventos que irão gravar no log
procedure ServiceController(CtrlCode: DWord); stdcall; begin FPrincipal.Controller(CtrlCode); end; function TFPrincipal.GetServiceController: TServiceController; begin Result := ServiceController; end; procedure TFPrincipal.SalvarLog(AMensagem: String); var wLog: TStringList; begin wLog := TStringList.Create; try try if FileExists(LOCAL_LOG) then wLog.LoadFromFile(LOCAL_LOG); wLog.Add(TimeToStr(Date) + ':' + AMensagem); except on e: exception do wLog.Add(TimeToStr(Date) + ':' + E.Message); end; wLog.SaveToFile(LOCAL_LOG); finally wLog.Free; end; end; procedure TFPrincipal.ServiceAfterInstall(Sender: TService); begin SalvarLog('ServiceAfterInstall'); end; procedure TFPrincipal.ServiceAfterUninstall(Sender: TService); begin SalvarLog('ServiceAfterUninstall'); end; procedure TFPrincipal.ServiceBeforeInstall(Sender: TService); begin SalvarLog('ServiceBeforeInstall'); end; procedure TFPrincipal.ServiceBeforeUninstall(Sender: TService); begin SalvarLog('ServiceBeforeUninstall'); end; procedure TFPrincipal.ServiceContinue(Sender: TService; var Continued: Boolean); begin SalvarLog('ServiceContinue'); end; procedure TFPrincipal.ServiceCreate(Sender: TObject); begin SalvarLog('ServiceCreate'); end; procedure TFPrincipal.ServiceDestroy(Sender: TObject); begin SalvarLog('ServiceDestroy'); end; procedure TFPrincipal.ServiceExecute(Sender: TService); begin SalvarLog('ServiceExecute'); while not self.Terminated do ServiceThread.ProcessRequests(true); end; procedure TFPrincipal.ServicePause(Sender: TService; var Paused: Boolean); begin SalvarLog('ServicePause'); end; procedure TFPrincipal.ServiceShutdown(Sender: TService); begin SalvarLog('ServiceShutdown'); end; procedure TFPrincipal.ServiceStart(Sender: TService; var Started: Boolean); begin SalvarLog('ServiceStart'); end; procedure TFPrincipal.ServiceStop(Sender: TService; var Stopped: Boolean); begin SalvarLog('ServiceStop'); end;
Instalação do serviço
procedure TFInstalar.BtnInstalarClick(Sender: TObject); var wLista: TStringList; begin try wLista := TStringList.Create; if Sender = BtnDesinstalar then wLista.Text := 'Log /uninstall' else wLista.Text := 'Log /install'; wLista.SaveToFile('Service.bat'); Sleep(2000); ShellExecute(Application.Handle, nil, PChar('Service.bat'), nil, nil, 0); finally FreeAndNil(wLista); Sleep(2000); DeleteFile('Service.bat'); end; end; procedure TFInstalar.ExibirNotificacao(const aMensagem: string); var Notification: TNotification; begin Notification := NotificationCenter.CreateNotification; try Notification.Title := 'Serviço'; Notification.AlertBody := aMensagem; NotificationCenter.PresentNotification(Notification); finally Notification.Free; end; end;
Exemplo acima
Pode ser instalado por meio de linhas de comando
c:\windows | abra o prompt
Agora dispare o seguinte comando:
C:\>Log.exe /install
Se o serviço for instalado com sucesso você verá a mensagem "Service installed successfully".
Para desinstalar o serviço basta disparar:
C:\>Log.exe /uninstall
Se o serviço for desinstalado com sucesso teremos a mensagem "Service uninstalled successfully".
Criado e Instalado, vamos verificar se ele está funcionando, vá em Painel de Controle -> Ferramentas administrativas -> Serviços e veja se o serviço já está na lista de serviços e qual seu status.
C:\>Log.exe /uninstall
Se o serviço for desinstalado com sucesso teremos a mensagem "Service uninstalled successfully".
Boa tarde. Estamos em 2020! rs brincadeiras à parte...
ResponderExcluirEstou com um exemplo simples, totalmente idêntico ao seu, mas está apresentando uma mensagem toda vez que inicializo o serviço. A mensagem é: "O Windows não pôde iniciar o serviço MyServiceTeste em Computador local. Erro 1067: O processo foi finalizado de forma inesperada."
Boa tarde, hahha! Verificou o antivirus ou se algum ou processo do Windows esta barrando ele?
ExcluirBom dia! Fiz um serviço e está funcionando bem, mas preciso colocar outras tarefas em um serviço. É possível criar um serviço que execute várias tarefas diferente com intervalos diferentes? Ou seria preciso criar um serviço diferente para cada tarefa?
ResponderExcluirBom dia! Um serviço pode executar varias tarefas com intervalos diferentes! Mas se as tarefas foram bem distinta uma da outra eu sempre acabo criado um serviço para cada tarefa para ter um melhor controle na hora de atualizar.
ExcluirBom dia, já teve esse tipo de problema?
Excluirquando tentamos executar um exe externo o mesmo aparece no gerenciador de tarefas mas não é exibido(show)? ex: se usarmos ShellExecute(Application.Handle, nil, PChar('C:\Windows\System32\calc.exe'), nil, nil, 0); porque a calculadora não é exibida mas dica no processo do windows?
porque quando tentamos executar um exe externo o mesmo aparece no gerenciador de tarefas mas não é exibido(show)? ex: se usarmos ShellExecute(Application.Handle, nil, PChar('C:\Windows\System32\calc.exe'), nil, nil, 0); porque a calculadora não é exibida mas dica no processo do windows?
ResponderExcluirBoa tarde! Isso ele não da o Show, mas pode fazer aparecer um icone no canto direito da barra (Perto da Data e hora) onde fica os serviços e dai fazer uma tela para dar o show de um form
Excluirapenas quero que o serviço execute um exe e esse exe fique visivel.
Excluir