J
jimmyfishbean
Hi,
I have a VB.Net Windows Service that monitors a varying number of
directories (that are read from an INI file). I set up a
FileSystemWatcher object to monitor each directory that is read from
the INI file and add each object to a collection.
The purpose of my service is to monitor the directories for any XML
files that are dropped into them. When a file is dropped, it is
firstly renamed by appending the extension '.lock' to the name of the
XML file. Secondly, the file is then processed by sending the contents
to a Web Service. Once the file has been completely processed and a
return value is received from the Web Service, the file is moved from
the directory to a 'Processed Files' folder (that is not monitored by a
FileSystemWatcher object).
I call a sub to process each directory, which loops through all files
in the directory (at one moment in time) and calls the web service for
each file.
When the service starts, any XML files in the 'monitored' are picked up
and processed without any erros/trouble. The problem starts if any
'new' XML files are dropped into the monitored directories when the
service is currently busy processing. I call the same sub that loops
through all files in a directory. Of course, there will be files
present in both calls to the sub, causing errors.
How can I tackle this? Is it reasonable to use a timer (I do not
currently use one). I did add a timer, but the number of handles and
memory kept increasing all the time (even when there was nothing to
process).
I am not concerned about the deletion of files or modification or
access. Simply addition/creation.
Any advice/guidance is greatly appreciated. Thanks.
Jimmy
Code snippet:
Private Sub setup()
...
While l <= UBound(aInputDirs)
Dim fsw As New FileSystemWatcher
fsw.Path = aInputDirs(l)
fsw.Filter = "*.xml"
fsw.IncludeSubdirectories = False
fsw.NotifyFilter = System.IO.NotifyFilters.LastWrite
AddHandler fsw.Changed, AddressOf OnChanged
fsw.EnableRaisingEvents = True
watcherCollection.Add(fsw)
l = l + 1
End While
l = 0
While l < UBound(aInputDirs)
ProcessDir(l)
l = l + 1
End While
...
End Sub
Private Shared Sub OnChanged(ByVal source As Object, ByVal e As
System.IO.FileSystemEventArgs)
'Dim strDir As String = e.Name
'1. work out the directory that has been changed (using the
full path/filename : e.Name)
Dim intLastSlash As Integer = e.FullPath.LastIndexOf("\")
Dim strDir As String = Left(e.FullPath, intLastSlash)
If Not bBusyProcessing Then
If Not e.Name = "XMLtoSOAP.ini" Then
If (File.GetAttributes(e.FullPath) And
FileAttributes.Directory) = FileAttributes.Directory Then
'Directory changed, created, or deleted.
Else
'File changed, created, or deleted.
Dim i As Integer = 0
Do While i < UBound(aInputDirs)
If aInputDirs(i) = strDir Then
ProcessDir(i)
Exit Do
End If
i = i + 1
Loop
End If
Else
'setup()
End If
End If
End Sub
Public Sub ProcessDir(ByRef lElement As Integer)
' Find all files in this directory and try to process them.
Dim fso As New Scripting.FileSystemObject
Dim oFile As Scripting.File
Dim strOrigFile As String
Dim stream As Scripting.TextStream
Dim bFileAlreadyOpen As Boolean
Dim cProcessedFiles As New Collection
Dim bMoreToProcess, bProcessedOne As Boolean
bMoreToProcess = True
While bMoreToProcess = True
bProcessedOne = False
For Each oFile In fso.GetFolder(aInputDirs(lElement)).Files
bBusyProcessing = True
'Make sure this file hasn't already been tried - if the
item is not in the collection an error is returned
On Error Resume Next
If cProcessedFiles.Count() <> 0 And
cProcessedFiles.Item(oFile.Name) <> oFile.Name Then
On Error GoTo 0
bFileAlreadyOpen = False
strOrigFile = oFile.Name
'Rename the file to see if it is still locked by
any process
On Error GoTo FileStillOpen
'create a copy of the original file to revert back
to if in changerootnode mode
If bChangeRootNode Then
If Not fso.FolderExists(aInputDirs(lElement) &
"\Temp") Then
fso.CreateFolder(aInputDirs(lElement) &
"\Temp")
End If
fso.CopyFile(oFile.Path, aInputDirs(lElement) &
"\Temp\" & oFile.Name)
sCurrFile = aInputDirs(lElement) & "\Temp\" &
oFile.Name
End If
fso.MoveFile(oFile.Path, oFile.Path & ".lock")
On Error GoTo 0
If Not bFileAlreadyOpen Then
ProcessFile(lElement, strOrigFile)
End If
'Store the file in a collection for exclusion in
the lower loop
cProcessedFiles.Add(strOrigFile, strOrigFile)
bProcessedOne = True
End If
bBusyProcessing = False
Next oFile
bMoreToProcess = bProcessedOne
End While
fso = Nothing
Exit Sub
FileStillOpen:
bFileAlreadyOpen = True
Resume Next
End Sub
'NOTE: Sub ProcessFile calls the web service
I have a VB.Net Windows Service that monitors a varying number of
directories (that are read from an INI file). I set up a
FileSystemWatcher object to monitor each directory that is read from
the INI file and add each object to a collection.
The purpose of my service is to monitor the directories for any XML
files that are dropped into them. When a file is dropped, it is
firstly renamed by appending the extension '.lock' to the name of the
XML file. Secondly, the file is then processed by sending the contents
to a Web Service. Once the file has been completely processed and a
return value is received from the Web Service, the file is moved from
the directory to a 'Processed Files' folder (that is not monitored by a
FileSystemWatcher object).
I call a sub to process each directory, which loops through all files
in the directory (at one moment in time) and calls the web service for
each file.
When the service starts, any XML files in the 'monitored' are picked up
and processed without any erros/trouble. The problem starts if any
'new' XML files are dropped into the monitored directories when the
service is currently busy processing. I call the same sub that loops
through all files in a directory. Of course, there will be files
present in both calls to the sub, causing errors.
How can I tackle this? Is it reasonable to use a timer (I do not
currently use one). I did add a timer, but the number of handles and
memory kept increasing all the time (even when there was nothing to
process).
I am not concerned about the deletion of files or modification or
access. Simply addition/creation.
Any advice/guidance is greatly appreciated. Thanks.
Jimmy
Code snippet:
Private Sub setup()
...
While l <= UBound(aInputDirs)
Dim fsw As New FileSystemWatcher
fsw.Path = aInputDirs(l)
fsw.Filter = "*.xml"
fsw.IncludeSubdirectories = False
fsw.NotifyFilter = System.IO.NotifyFilters.LastWrite
AddHandler fsw.Changed, AddressOf OnChanged
fsw.EnableRaisingEvents = True
watcherCollection.Add(fsw)
l = l + 1
End While
l = 0
While l < UBound(aInputDirs)
ProcessDir(l)
l = l + 1
End While
...
End Sub
Private Shared Sub OnChanged(ByVal source As Object, ByVal e As
System.IO.FileSystemEventArgs)
'Dim strDir As String = e.Name
'1. work out the directory that has been changed (using the
full path/filename : e.Name)
Dim intLastSlash As Integer = e.FullPath.LastIndexOf("\")
Dim strDir As String = Left(e.FullPath, intLastSlash)
If Not bBusyProcessing Then
If Not e.Name = "XMLtoSOAP.ini" Then
If (File.GetAttributes(e.FullPath) And
FileAttributes.Directory) = FileAttributes.Directory Then
'Directory changed, created, or deleted.
Else
'File changed, created, or deleted.
Dim i As Integer = 0
Do While i < UBound(aInputDirs)
If aInputDirs(i) = strDir Then
ProcessDir(i)
Exit Do
End If
i = i + 1
Loop
End If
Else
'setup()
End If
End If
End Sub
Public Sub ProcessDir(ByRef lElement As Integer)
' Find all files in this directory and try to process them.
Dim fso As New Scripting.FileSystemObject
Dim oFile As Scripting.File
Dim strOrigFile As String
Dim stream As Scripting.TextStream
Dim bFileAlreadyOpen As Boolean
Dim cProcessedFiles As New Collection
Dim bMoreToProcess, bProcessedOne As Boolean
bMoreToProcess = True
While bMoreToProcess = True
bProcessedOne = False
For Each oFile In fso.GetFolder(aInputDirs(lElement)).Files
bBusyProcessing = True
'Make sure this file hasn't already been tried - if the
item is not in the collection an error is returned
On Error Resume Next
If cProcessedFiles.Count() <> 0 And
cProcessedFiles.Item(oFile.Name) <> oFile.Name Then
On Error GoTo 0
bFileAlreadyOpen = False
strOrigFile = oFile.Name
'Rename the file to see if it is still locked by
any process
On Error GoTo FileStillOpen
'create a copy of the original file to revert back
to if in changerootnode mode
If bChangeRootNode Then
If Not fso.FolderExists(aInputDirs(lElement) &
"\Temp") Then
fso.CreateFolder(aInputDirs(lElement) &
"\Temp")
End If
fso.CopyFile(oFile.Path, aInputDirs(lElement) &
"\Temp\" & oFile.Name)
sCurrFile = aInputDirs(lElement) & "\Temp\" &
oFile.Name
End If
fso.MoveFile(oFile.Path, oFile.Path & ".lock")
On Error GoTo 0
If Not bFileAlreadyOpen Then
ProcessFile(lElement, strOrigFile)
End If
'Store the file in a collection for exclusion in
the lower loop
cProcessedFiles.Add(strOrigFile, strOrigFile)
bProcessedOne = True
End If
bBusyProcessing = False
Next oFile
bMoreToProcess = bProcessedOne
End While
fso = Nothing
Exit Sub
FileStillOpen:
bFileAlreadyOpen = True
Resume Next
End Sub
'NOTE: Sub ProcessFile calls the web service