Visual Basic em Português

Página pessoal de Jorge Paulino sobre o Visual Basic (VB.NET, ASP.NET, VB6, VBA) e algumas noticias de tecnologia

VB.NET: Windows Service + FileSystemWatcher

Os Windows Services, normalmente conhecidos por Serviços NT, permite criar aplicações executáveis que correm junto dos serviços do sistema operativo do Windows. Estes serviços arrancam com o sistema operativo, independentemente do utilizador activo, e não são visíveis (correm em background), sendo portanto indicados para operações em servidores ou operações que não interferem com o utilizador. Antes do lançamento do.Net este processo era apenas conseguido por aplicações em C++, complicadas e não acessíveis a todos.

Como os Windows Services correm como serviço, não é possível utilizar controlos, mostrar mensagens ao utilizador através de msgbox’s, etc. Também não é possível validar o código criado, sendo aconselhável criar um programa normal “Windows Project”, testar e só depois colocar o código no serviço.

Para um exemplo de como criar e instalar um Windows Service, será utilizado outro componente do .Net Framework, o FileSystemWatcher.

O FileSystemWatcher é um componente no namespace System.IO que permite observar uma directoria específica. Ele verifica alterações nos ficheiros e sub-directorias de acordo com um determinado filtro e detecta se um ficheiro foi apagado, criado, modificado, etc, sendo uma excelente ferramenta de monitorização.

Neste exemplo será criado um serviço que irá monitorizar numa directoria os ficheiros mp3 e gravar num ficheiro log todas as alterações efectuadas.

Para criar o serviço é necessário executar os seguintes passo:

1 - Criar um novo projecto e seleccionar um “Windows Service”. Alterar o nome do projecto para myWindowsService. Irá ser criado um novo serviço com o nome Service1.vb


2 – Criar com o botão direito do rato sobre a área criada e seleccionar “Add Installer”. O Visual Studio irá criar dois itens: ServiceInstaller1 e ServiceProcessInstaller1.


O ServiceInstaller não faz parte do serviço em si, servindo apenas para registar o serviço quando este for instalado. É através dele que se especifica que tipo de arranque o serviço tem (Manual, Automatic ou Disabled), qual o nome visível, qual a descrição geral do serviço, entre outras definições.

O ServiceProcessInstaller é chamado pelo aplicativo de instalação e serve para escrever no registry do Windows informações sobre o serviço que se vai instalar.

Em conjunto estas duas classes permitem instalar um serviço de uma forma bastante simples.

3 – Seleccionado o ServiceInstaller1 alterar alguns dados, como a Description e DisplayName na janela Properties. Seleccionar o ServiceProcessInstaller1 e alterar a propriedade Account para LocalService.

4 – Seleccionar o Service1.vb e mudar para o código. É aqui que se desenvolve o código que o serviço irá executar. Utilizar o seguinte código.

Nota: Criar a directoria “c:\mp3\” ou alterar a localização no código do serviço

 

Imports System.IO

Public Class Service1

    ' Indicação do nome do ficheiro log
    Private Const logFileName As String = "c:\mp3\history.log"
    Private watcher As FileSystemWatcher

    ' No arranque do serviço 
    Protected Overrides Sub OnStart(ByVal args() As String)

        ' Cria uma nova instância do FileSystemWatcher
        watcher = New FileSystemWatcher

        ' Atribui eventos ao FileSystemWatcher
        AddHandler watcher.Deleted, AddressOf OnChanged
        AddHandler watcher.Created, AddressOf OnChanged
        AddHandler watcher.Renamed, AddressOf OnRenamed

        ' Indicação do filtro, caminho e activação
        With watcher
            .NotifyFilter = NotifyFilters.FileName
            .Path = "c:\mp3"
            .Filter = "*.mp3"
            .EnableRaisingEvents = True
        End With

        ' Mensagem inicial de arranque do serviço
        Dim logMsg As String = "Serviço iniciado em " & DateTime.Now.ToString
        My.Computer.FileSystem.WriteAllText(logFileName, logMsg & vbNewLine, True)

    End Sub

 

    ' Quando o serviço for parado
    Protected Overrides Sub OnStop()
        Dim logMsg As String = "Serviço parado em " & DateTime.Now.ToString
        My.Computer.FileSystem.WriteAllText(logFileName, logMsg & vbNewLine, True)
    End Sub


   
' Quando um ficheiro for renomeado
    Sub OnRenamed(ByVal sender As Object, ByVal e As System.IO.RenamedEventArgs)

        Try

            ' Mensagem com o nome anterior e o novo nome do ficheiro
            Dim logMsg As String = _
                String.Format("Ficheiro renomeado de ""{0}"" para ""{1}"" em {2}", _
                e.OldName, e.Name, DateTime.Now.ToString)

            ' Escreve no ficheiro log
            My.Computer.FileSystem.WriteAllText(logFileName, logMsg & vbNewLine, True)

        Catch ex As Exception
            ' Em caso de erro, escreve a mensagem geral com o erro
            Dim logError As String = ex.Message.ToString & " - " & DateTime.Now.ToString
            My.Computer.FileSystem.WriteAllText(logFileName, logError & vbNewLine, True)

        End Try

    End Sub

 

    ' Caso algum ficheiro seja apagado ou criado
    Private Sub OnChanged(ByVal source As Object, ByVal e As FileSystemEventArgs)

        Try 

            Dim logMsg As String = String.Empty

            ' Verifica qual a acção e cria a mensagem
            Select Case e.ChangeType
                Case WatcherChangeTypes.Created
                    logMsg = String.Format("Ficheiro ""{0}"" criado em {1}", e.Name, DateTime.Now.ToString)

                Case WatcherChangeTypes.Deleted
                    logMsg = String.Format("Ficheiro ""{0}"" apagado em {1}", e.Name, DateTime.Now.ToString)

            End Select

            ' Escreve no ficheiro log
            My.Computer.FileSystem.WriteAllText(logFileName, logMsg & vbNewLine, True)

        Catch ex As Exception
            ' Em caso de erro, escreve a mensagem geral com o erro
            Dim logError As String = ex.Message.ToString & " - " & DateTime.Now.ToString
            My.Computer.FileSystem.WriteAllText(logFileName, logError & vbNewLine, True)

        End Try

      End Sub

End Class


5 – Compilar o programa (build) e irá ser criado o myWindowsService.exe

Com o serviço já criado é apenas necessário instalá-lo. Para instalar um serviço é necessário utilizar um utilitário disponível com o .Net Framework e que corre em ambiente DOS - o InstallUtil.exe. Este ficheiro encontra-se na directoria de instalação da plataforma .Net Framework, como por exemplo para a versão 2.0 em C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\

6 – Ir ao menu do Windows Start – Run e escrever cmd para abrir uma janela do DOC


7 – Indicar a localização do ficheiro e do serviço criado para proceder à instalação. Exemplo:

Instalar:

<localização do ficheiro>\InstallUtil.exe <localização do serviço>\myWindowsService.exe

Desinstalar:

<localização do ficheiro>\InstallUtil.exe /u <localização do serviço>\myWindowsService.exe


 

Nota: Uma solução mais simples é copiar o ficheiro executável do serviço e o ficheiro InstallUtil.exe para o mesmo directório/pasta simplificando o comando no DOS.


8 – Para terminar ir ao Control PanelAdministrative ToolsServices e iniciar o serviço criado.


Para testar o serviço é só copiar ficheiros mp3 para dentro da directoria c:\mp3\, apaga-los, alterar os nomes e verificar o registo no ficheiro log. Caso seja necessário alterar algum código ao serviço é preciso desinstala-lo (ver ponto 7), efectuar as alterações, compilar o projecto e instalar novamente.

Este é um exemplo de como criar Windows Services e como são úteis para diversas aplicações. O FileSystemWatcher é utilizado no exemplo mas pode, obviamente, ser utilizado numa aplicação normal para o Windows.

 

PS: Como  sempre, qualquer dúvida, comentário ou correcção ao artigo é sempre bem vinda!

9 comentários:

António Silva disse...

E existe a possibilidade de no evento change vermos o processo que está a criar/alterar o ficheiro? Vermos o PID ou o nome dele?

Jorge Paulino disse...

Ola,

Não estou a entender a questão. No evento OnChange consegue-se saber o tipo de alteração através do e.ChangeType.

No entanto se não for essa a questão, utilize o email que está no final do blog para enviar mais detalhes.

Anónimo disse...

Boas!...

É interessante mas... e, com o VB2005 Express como faço isso?
Pelo que percebi só funciona se tiver o componente do Visual Studio.
Por outras palavras: Não dá para criar serviços com as versões Express?

Jorge Paulino disse...

"VB2005 Express como faço isso?"

Olá, nunca usei a versão Express mas penso que não permita a criação de Windows Services, baseando-me nesta informação http://en.wikipedia.org/wiki/Microsoft_Visual_Studio_Express#Visual_Basic_Express

Anónimo disse...

dar para acrescentar dá, mas eu usei o vb express 2008, olha aqui
http://michaelellerbeck.com/2009/01/12/creating-a-service-for-visual-basic-2008-express/

Walcyr Rafael disse...

Ótimo!! Artigo simples, mas me auxilio muito para conhecer melhor como criar, instalar e remover um serviço para o Windows.
Parabéns!! E obrigado!

Anónimo disse...

Boas,

O artigo está muito bom, já testei o programa, e inclusive fiz a minha propria variante. Agora seria interessante que este filesystem watcher podesse logar mais informações, incluindo o user_name, ip, maquina, entre outras coisas. Acho que isto pode ser uma excelente ferramenta. O artigo está optimo, mas uma "parte 2" seria "ouro sobre azul"

Cumprimentos

António Santos

Anónimo disse...

Boas sou novo na utilização do visual basic e de momento nºao consigo instalar o basic 2008 no meu pc com windows 7 o ke sera
agradecia uma ajudinha

Jorge Paulino disse...

@António Santos,

Essas informações podem ser obtidas de uma forma bastante simples, utilizando o My Namespace. Por exemplo:

My.Computer.Name.ToString
My.User.Name.ToString
etc

@Anónimo,

Relativamente à instalação do Visual Basic no Windows 7, julgo que não existe qualquer problema de compatibilidade. Tenho a funcionar várias versões no Windows 7 e sem problemas.

Coloque a questão, com mais informação, em Portugal-A-Programar



Microsoft Office Especialist

Membro da Comunidade
Experts-Exchange


Administ. da Comunidade
Portugal-a-Programar



Twitter

Artigos no CodeProject

Artigos no CodeProject
Google-Translate-ChineseGoogle-Translate-Portuguese to FrenchGoogle-Translate-Portuguese to GermanGoogle-Translate-Portuguese to ItalianGoogle-Translate-Portuguese to JapaneseGoogle-Translate-Portuguese to EnglishGoogle-Translate-Portuguese to RussianGoogle-Translate-Portuguese to Spanish

Subscrever Novidades

Endereço de Email:

Delivered by FeedBurner

Seguidores

Histórico