|
|
Migration - Creating Services in .NETUsing the .NET FileWatcher | | In VB6, writing a service was usually done by the C++ gurus. Also, watching directories for file creation, movement, etc., was not easy, to say the least. Under .NET, it's a breeze!
At the company, where I work, we have thousands of files offloaded and uploaded to our FTP Server. Our SQLServer database keeps a record of work processed through our company and file movement is a major tracking component. Therefore, we must see that we record the creation of every file, of certain types. We cannot afford to miss one!. This means that we have to come as close to 100% up-time for the FileWatcher application as possible.
When we first implemented the FileWatcher, as a stand-alone program, running on a client machine, we were periodically experiencing failures due to lost connections to the server, etc. Finally, it occured to us to put a Windows Service Application on the FTP server so that as long as the server is up, the FileWatcher is running. In addition, we kept the Service as "thin" as possible, simply creating a log file of created files. We placed the database update in another program, running on a client machine, so that the Service does not have to access any thing that is not on the host server.
In this article, I will show you how to create a Windows Service application, using the FileWatcher component. Just follow these simple steps.
1. Create a new VB.NET project, of type Windows Service. You will find this project type in the Template window for Visual Basic Projects.
2. Select a name and location for your new project. I called mine "FileWatcherService."
3. When the project opens, it will have a designer, but it will not have a form. You can use this designer surface to drop any components that you need, just as if it were a form designer.
4. Open the ToolBox and click on the Components tab. There you will see, among other components, the FileSystemWatcher. Double-click the FileSystemWatcher and it will be placed on your service designer.
5. In the property window of the service designer, set the Name to fwService, to set the name of the class. Next, set the ServiceName properties to fwService, which names the service itself. You can use different names, but I made them the same. Next, set the CanStop property to True, and the CanPauseAndContinue property to True. These property settings allow the service to be paused and stopped. Finally, set the AutoLog property to True. This will cause the service to write log entries in the Application event log when it starts and stops correctly, as well as insert entries when commands do not work.
Figure 1 is the abridged listing of the code generated by the designer. I have removed the full code for brevity's sake. The code automatically generated by the designer does include two events that are called when the service starts and stops. These two events are of interest to us because that is where we will start and stop the FileSystemWatcher component. I have added two private, declaration level variables to denote the path for the FileWatcher to watch and the path and file to which the log of created files will be written.
To start the FileSystemWatcher, I need set some properties for it. I do this in the OnStart event of the service. First, I set the path that is to be watched. Since I have set the whole D: Drive, I will be notified whenever a file is created on the drive, regardless of the type of file. Again, in the service, I am keeping it as thin and free of business logic as possible. The reason for this is that all I want this service to do is to record the creation of files on the server. Business logic regarding file types that are of interest will change periodically, and I do not want to have to take the service down for debugging new changes, etc. I need the service to be up 100% if possible. In another artice, I will describe the recovery process if the service/server fails. Next, I set the IncludeSubdirectories property to true so that the whole drive is watched. Next, I set the Filter property to watch all file types. Finally, I set the EnableRaisingEvents to True, which starts the FileSystemWatcher.
In the OnStop event, I simply turn off the FileSystemWatcher. The OnPause and OnContinue events mirror the OnStop and OnStart events.
Figure 1 - fwService Class.
Public Class fwService
Inherits System.ServiceProcess.ServiceBase
' Component Desiner Generate code omitted.
' Path for the file wathcer to watch. The D: drive is the FTP server drive
Private Path As String = "D:\"
' Path for the FileWatcher log of created files to be written
Private TxtFilePath As String = "D:\FileWatcherFiles\FileWatcher.Txt"
Protected Overrides Sub OnStart(ByVal args() As String)
' Add code here to start your service. This method should set things
' in motion so your service can do its work.
Try
Me.FileSystemWatcher1.Path = Path
Me.FileSystemWatcher1.IncludeSubdirectories = True
Me.FileSystemWatcher1.Filter = "*.*"
Me.FileSystemWatcher1.EnableRaisingEvents = True
Catch ex As System.Exception
StructuredErrorHandler(ex)
End Try
End Sub
Protected Overrides Sub OnStop()
' Add code here to perform any tear-down necessary to stop your service.
' start receiving file created events
Try
Me.FileSystemWatcher1.EnableRaisingEvents = False
Catch ex As System.Exception
StructuredErrorHandler(ex)
End Try
End Sub
Protected Overrides Sub OnPause()
Try
Me.FileSystemWatcher1.EnableRaisingEvents = False
Catch ex As System.Exception
StructuredErrorHandler(ex)
End Try
End Sub
Protected Overrides Sub OnContinue()
Try
Me.FileSystemWatcher1.Path = Path
Me.FileSystemWatcher1.IncludeSubdirectories = True
Me.FileSystemWatcher1.Filter = "*.*"
Me.FileSystemWatcher1.EnableRaisingEvents = True
Catch ex As System.Exception
StructuredErrorHandler(ex)
End Try
End Sub
|
In Figure 2, you will see the code for the FileSystemWatcher_Created event. I created this event by clicking on the FileSystemWatcher1 in the object drop down list of the class code window. Next, I clicked on the Created event in the event drop down list. This code gets or creates a timestamp for the newly created file and calls the LogFilesAndErrors helper method to write the log of created files.
Figure 2 - FileSystemWatcher Created Event.
Private Sub FileSystemWatcher1_Created(ByVal sender As Object, _
ByVal e As System.IO.FileSystemEventArgs) _
Handles FileSystemWatcher1.Created
' record the receipt of the file
' unless it is a temporary file created by Microsoft Word
' also ignore the creation of the file in which I am writing the
' log of files
Dim FileTime As String
Try
If e.FullPath.ToUpper.IndexOf("FILEWATCHERFILES") > -1 OrElse _
(e.FullPath.ToUpper.IndexOf("~WRD") > -1 And _
e.FullPath.ToUpper.IndexOf(".TMP") > -1) Then
Exit Sub
End If
Catch
Exit Sub
End Try
Try
FileTime = FileDateTime(e.FullPath).ToString
Catch
FileTime = Now.ToString
End Try
Try
LogFilesAndErrors("TM:" & vbTab & FileTime & vbTab & "FN: " & _
vbTab & e.FullPath)
Catch
' an error here is caused by the log method, and there is nothing to do
End Try
End Sub
|
In Figure 3, I show the helper method which does the actual recording of the newly created file. The service is creating or appending to the log file named FileWatcherText.txt file. The reason that it has to keep checking for availability of the file is that another complementing, application is running on a client computer. Every five minutes, that application is "grabbing" (by renaming) the FileWatcherText.txt file and recording its contents in a SQLServer database. That means that every five minutes, the file that the service is writing to, disappears and the service has to create a new one. The application that is renaming the file is called FileWatcherToDatabase. It contains the business logic for determining the files that really are of interest. If a file is of interest, it is recorded in the database, otherwise it is ignored by the client program. That program also has the logic in it for tracing through the FTP server drive, for recovery purposes, in case the server/service is down for some reason. That gives us the ability to find any files that may not have been recorded by the service application. I will cover that application in another article.
Figure 3 - Helper Method to Record Newly Created Files.
Private Sub LogFilesAndErrors(ByVal FullPath As String, _
Optional ByVal Time As String = "")
' this method will open the sql error file and append the sql to the file
Dim i As Integer
Dim start As Integer
Dim h As Integer
Dim sLine As String
If Time.Length = 0 Then Time = Now.ToString
sLine = FullPath
For i = 1 To 100
If System.IO.File.Exists(TxtFilePath) Then
' file renamed, create a new one.
Try
h = FreeFile()
FileOpen(h, TxtFilePath, OpenMode.Output, OpenAccess.Write, _
OpenShare.LockWrite)
PrintLine(h, sLine)
FileClose(h)
Exit Sub
Catch
End Try
Else
Try
h = FreeFile()
FileOpen(h, TxtFilePath, OpenMode.Append, OpenAccess.Write, _
OpenShare.LockWrite)
' we have the file, write the sql and close the file
PrintLine(h, sLine)
FileClose(h)
Exit Sub
Catch
End Try
End If
End If
start = Microsoft.VisualBasic.Timer
Do While Microsoft.VisualBasic.Timer - start < 1
DoEvents()
Loop
Next i
End Sub
|
Space will not allow me to go into the installation of the service, but you can find the needed information at MSDN.
Top Of Page |
|