Click here to Skip to main content
15,867,330 members
Articles / Programming Languages / Visual Basic
Article

Using Windows Services to monitor folders and unzip files - VB.NET

Rate me:
Please Sign up or sign in to vote.
4.22/5 (17 votes)
25 Mar 20053 min read 148.4K   1.3K   66   10
How to use VB.NET to build a Windows Service that monitor folders looking for files in ZIP format (and unzip them).

Sample Image - screenshot3.jpg

Introduction

A friend, developing an application in VB 6.0 needed a solution with the following requirements:

  • Have to run all the time.
  • There is no need to any user to be logged on.
  • Must run in Win 2K, XP and may be in 2003 server.

The answer was: Windows Services.

What does the application do?

The application that generated this solution uploads mdb access files zipped into a file to decrease the size of the data base file, 'cause some of his clients use 56k modem connections.

When developing his application in ASP.NET, he needed some way to monitor directory for this special zipped files. As the files arrive, the solution must unzip the files and overwrite the file content in the same directories.

The easiest way to do this, we thought, was with VB 6. We started to look for some place to find information of how doing this in VB 6, but no success. Every article, tutorial and code I found used VB.NET, C# or any other .NET language.

We were convinced that VB.NET had to be the choice for developing the Windows service. Were fascinated with how easy is to build a Windows service with VB.NET. With VB 6, we tried to build a normal executable and run it against a series of tools (as many articles describe) but none of the tools did the job.

With VB.NET we only inherited from the System.ServiceProcess.ServiceBase class and completed the overloaded methods OnStart and OnStop. And the job was done... er... almost done.

In the beginning, I was using the D# IDE which has no facilities to build a Windows service, I had to manually type the definitions for the methods and so. I tried to set the Me.timer1.SynchronizingObject property to me (The W.Service) class and this lead me into a terrible error of crashing the stack. With some try-and-error debug, I discovered this and the Windows service started to run.

The Installer

The installer does nothing but to install the Windows service. We detected that the Installer class has no way to set up the description of the Windows service. Thanks to the Andy Hopper's Adding a description to a .NET Windows service article, we could set it up with a little code. In the Install overloaded method we did:

VB
'Open the HKEY_LOCAL_MACHINE\SYSTEM key
rgkSystem = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("System")
'Open CurrentControlSet
rgkCurrentControlSet = rgkSystem.OpenSubKey("CurrentControlSet")
'Go to the services key
rgkServices = rgkCurrentControlSet.OpenSubKey("Services")
'Open the key for your service, and allow writing
rgkService = rgkServices.OpenSubKey(si.ServiceName, True)
'Add your service's description as a REG_SZ value named "Description"
rgkService.SetValue("Description", m_Description)
'(Optional) Add some custom information your service will use...
rgkConfig = rgkService.CreateSubKey("Parameters")
rgkConfig.Close()
rgkService.Close()
rgkCurrentControlSet.Close()
rgkSystem.Close()

The approach

We used a timer object to monitor the directories listed in a .ini file in every three seconds.

VB
<System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponents()
        Me.timer1 = New System.Timers.Timer()
        Me.timer1.Interval = 3000
        Me.timer1.Enabled = True

        Me.ServiceName = "CheckWebDataBase"
    End Sub

In the OnStart and OnStop, we only had to enable or disable the timer.

VB
Protected Overrides Sub OnStart(ByVal args() As String)
    ' TODO: Add start code here (if required)
    '       to start your service.
    Me.timer1.Enabled = True
End Sub

Protected Overrides Sub OnStop()
    ' TODO: Add tear-down code here (if required)
    '       to stop your service.
    Me.timer1.Enabled = False
End Sub

The timer elapsed event is listed below:

VB
Private Sub Timer1Elapsed(ByVal sender As System.Object, _ 
          ByVal e As System.Timers.ElapsedEventArgs) _ 
          Handles timer1.Elapsed
  Dim qt As Integer, x As Integer

  Dim path As String = "c:\windows"
  Dim folder As String, date_ As String, ZIP As String
  Dim INIFile As String = path & "\Customer.ini"

  qt = CType(CheckWebDataBaseService.Ini.ReadIni(INIFile, _ 
    "General", "Number"), System.Int32)
  For x = 1 To qt
    folder = CheckWebDataBaseService.Ini.ReadIni(INIFile, "Folders", x)
    'Zip File name ZIP = folder & "DataBase.zip"
    date_ = CStr(FileDateTime(ZIP))
    If CheckWebDataBaseService.Ini.ReadIni(INIFile, "Dates", x) <> date_ Then
      Me.ExtractArchive(ZIP, folder)
      CheckWebDataBaseService.Ini.WriteIni(INIFile, "Dates", x, date_)
    End If
  Next
End Sub

We used the ini approach for the usability, 'cause it's easy to add new customers. Note that the name of the zipped file is hard-coded as "DataBase.zip" See the contents for Customer.ini:

[General] 
Number=2 

[Folders] 
1=c:\dev\test\ 
2=c:\dev\test2\ 

[Dates] 
1=6/1/2005 10:40:19 
2=6/1/2005 10:25:49

In Number, we have the numbers of customers. In Folders, we have the customers' folders. And in Dates, we have the last updated date of the file in the folder. To unzip the files, we have used the excellent library SharpZipLib from ICsharpCode (the same for the SharpDevelop or #D).

VB
Public Sub ExtractArchive(ByVal zipFilename As String, ByVal ExtractDir As String)
  Dim Redo As Integer = 1
  Dim MyZipInputStream As ZipInputStream
  Dim MyFileStream As FileStream
  MyZipInputStream = New ZipInputStream(New FileStream(zipFilename, _ 
    FileMode.Open, FileAccess.Read))
  Dim MyZipEntry As ZipEntry = MyZipInputStream.GetNextEntry
  Directory.CreateDirectory(ExtractDir)
  While Not MyZipEntry Is Nothing
    If (MyZipEntry.IsDirectory) Then
      Directory.CreateDirectory(ExtractDir & "\" & MyZipEntry.Name)
    Else
      If Not Directory.Exists(ExtractDir & "\" & _
      Path.GetDirectoryName(MyZipEntry.Name)) Then
        Directory.CreateDirectory(ExtractDir & "\" & _
        Path.GetDirectoryName(MyZipEntry.Name))
      End If
      MyFileStream = New FileStream(ExtractDir & "\" & _ 
        MyZipEntry.Name, FileMode.OpenOrCreate, FileAccess.Write)
      Dim count As Integer
      Dim buffer(4096) As Byte
      count = MyZipInputStream.Read(buffer, 0, 4096)
      While count > 0
        MyFileStream.Write(buffer, 0, count)
        count = MyZipInputStream.Read(buffer, 0, 4096)
      End While
      MyFileStream.Close()
    End If
    Try
      MyZipEntry = MyZipInputStream.GetNextEntry
    Catch ex As Exception
      MyZipEntry = Nothing
    End Try
  End While
  If Not (MyZipInputStream Is Nothing) Then MyZipInputStream.Close()
    If Not (MyFileStream Is Nothing) Then MyFileStream.Close()
  End Sub
End Class

Screenshots

Before

After

Ending

And that's all. We hope you find this code useful.

Future

We plan to substitute ini files for config files. If anyone do it for me, please keep me updated.

Thanks

To Nirondes for the idea to build that Windows service. I am sure we learned too much.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Brazil Brazil
Personal
-----------
I'm 26 years old and have a son named Davih. My main hobby is play guitar.

Professional
------------
I work in a government work and do many "in-house" extra-work in free time.
I started with QBasic at 15.
Programmed in VB 4, 5, 6 and VB.NET.
Very many familiar with assembly, C, C++.
Used perl for 2 or 3 months.
Today, I'm a web developer using PHP/Javascript/JSON/Ajax.
Nowadays, involved with a little bit of XNA programming and Playstation 2 programming.
Love play games and 'rom hacking' its.

-------------------------
Sharing knowledge is the best way to grow up.

Comments and Discussions

 
Generalclass ini.vb Pin
rt200813-Oct-08 11:16
rt200813-Oct-08 11:16 
QuestionHow can I execute Installutil.exe Pin
lestralv10-May-06 12:31
lestralv10-May-06 12:31 
AnswerRe: How can I execute Installutil.exe Pin
Nbranquinho1-Jun-06 10:25
Nbranquinho1-Jun-06 10:25 
AnswerRe: How can I execute Installutil.exe Pin
DigiOz Multimedia25-Aug-07 12:36
DigiOz Multimedia25-Aug-07 12:36 
GeneralServi&#231;o no WindowsNT Pin
roberto lapolli3-Aug-05 11:28
professionalroberto lapolli3-Aug-05 11:28 
QuestionWhy not FileSystemWatcher? Pin
Thomas Freudenberg25-Mar-05 22:57
Thomas Freudenberg25-Mar-05 22:57 
AnswerRe: Why not FIleSystemWatcher? Pin
Pablo Robert28-Mar-05 9:22
Pablo Robert28-Mar-05 9:22 
GeneralRe: Why not FIleSystemWatcher? Pin
The Silence2-Apr-05 0:29
The Silence2-Apr-05 0:29 
GeneralRe: Why not FIleSystemWatcher? Pin
Pablo Robert2-Apr-05 13:25
Pablo Robert2-Apr-05 13:25 
Really it is. Plan for future changes.

Coming soon.

Thanks for feedback.

Pablo Robert
Programmer - Brazil
AnswerRe: Why not FileSystemWatcher? Pin
UR-IT11-Apr-05 20:20
UR-IT11-Apr-05 20:20 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.