Skip to main content
Email Password   helpLost your password?

Sample Image - screenshot3.jpg

Introduction

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

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:

   '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.

    <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.

        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:

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).

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.

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
Generalclass ini.vb Pin
rt2008
12:16 13 Oct '08  
GeneralHow can I execute Installutil.exe Pin
lestralv
13:31 10 May '06  
GeneralRe: How can I execute Installutil.exe Pin
branc
11:25 1 Jun '06  
GeneralRe: How can I execute Installutil.exe Pin
DigiOz Multimedia
13:36 25 Aug '07  
GeneralServiço no WindowsNT Pin
roberto lapolli
12:28 3 Aug '05  
GeneralWhy not FileSystemWatcher? Pin
Thomas Freudenberg
23:57 25 Mar '05  
GeneralRe: Why not FIleSystemWatcher? Pin
Pablo Robert
10:22 28 Mar '05  
GeneralRe: Why not FIleSystemWatcher? Pin
The Silence
1:29 2 Apr '05  
GeneralRe: Why not FIleSystemWatcher? Pin
Pablo Robert
14:25 2 Apr '05  
GeneralRe: Why not FileSystemWatcher? Pin
UR-IT
21:20 11 Apr '05  


Last Updated 25 Mar 2005 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2009