-
Mar 2nd, 2012, 04:46 PM
#1
Thread Starter
Junior Member
VB.Net 2010 - FileSystemWatchers
Hello, I'm having issues trying to get file system watchers working properly, I'm not sure whats not right here, I want to use multiple, but I can't even get one of them to fire on an event...
simple form with a listbox for folders to watch and a listbox to list changes detected and a command button to launch watchers.
Code:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
lstFolders.Items.Add("C:\temp\1")
lstFolders.Items.Add("C:\temp\2")
lstFolders.Items.Add("C:\temp\3")
End Sub
Private Sub cmdWatch_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdWatch.Click
For i As Integer = 0 To lstFolders.Items.Count - 1
'MsgBox(Me.lstFolders.Items(i))
fnWatchFolder(lstFolders.Items(i), "*.txt")
Next
End Sub
Public Function fnWatchFolder(ByVal strFolderToWatch As String, ByVal strFileExtension As String) As Boolean
' Get the path to the directory we will watch.
' Make the FileSystemWatcher.
Dim FileWatcher = New FileSystemWatcher(strFolderToWatch, strFileExtension)
FileWatcher.NotifyFilter = NotifyFilters.FileName ' Or NotifyFilters.FileName
FileWatcher.EnableRaisingEvents = True
AddHandler FileWatcher.Changed, AddressOf OnChanged
fnWatchFolder = True
End Function
Public Sub OnChanged(ByVal source As Object, ByVal e As FileSystemEventArgs)
MsgBox("change occured")
lstChanges.Items.Add(e.FullPath & " : " & e.ChangeType.ToString("G"))
End Sub
-
Mar 2nd, 2012, 05:58 PM
#2
Re: VB.Net 2010 - FileSystemWatchers
You are creating a new FileSystemWatcher inside the method, once you leave the method, it is gone! .Net got rid of it as you have left no way to get back to it. Move the declaration out, if you need more than one, then create a (list of) them.
-
Mar 2nd, 2012, 06:02 PM
#3
Thread Starter
Junior Member
Re: VB.Net 2010 - FileSystemWatchers
thanks for the info, I understand what you're saying but I dont quite understand how best to structure what your saying... any chance you can provide me a little more guidance
-
Mar 2nd, 2012, 06:30 PM
#4
Re: VB.Net 2010 - FileSystemWatchers
Only if you invite me over to stay in NZ for a month!
For now, just move the declaration out of the method.
Code:
Private WithEvents TheFileWatcher As FileSystemWatcher
Public Function fnWatchFolder(ByVal strFolderToWatch As String, ByVal strFileExtension As String) As Boolean
' Get the path to the directory we will watch.
' Make the FileSystemWatcher.
TheFileWatcher = New FileSystemWatcher(strFolderToWatch, strFileExtension)
TheFileWatcher.NotifyFilter = NotifyFilters.FileName ' Or NotifyFilters.FileName
TheFileWatcher.EnableRaisingEvents = True
' AddHandler FileWatcher.Changed, AddressOf OnChanged You can use the WithEvents above to just xxx Handles TheFileWatcher.Changed event
Return True
End Function
-
Mar 2nd, 2012, 06:50 PM
#5
Thread Starter
Junior Member
Re: VB.Net 2010 - FileSystemWatchers
haha yes you'd like NZ, but I tell ya, we spent far less money on living expenses when we were living in London than what we do here, its become incredibly expensive place to live here.
I understand your changes and they all work well, but how do i instigate this withevents/onchanged method now... previosuly with the addhandler when and event was raised it woudl go to the private sub onchanged and then you could do what ever with the notifican event... how do i get to this same place? your comment xxx the ... has me lost!
-
Mar 3rd, 2012, 02:37 AM
#6
Re: VB.Net 2010 - FileSystemWatchers
I have toured around NZ, still fancy moving over!
Code:
Public Sub OnChanged(ByVal source As Object, ByVal e As FileSystemEventArgs) Handles TheFileWatcher.Changed
...
End Sub
-
Mar 3rd, 2012, 03:29 AM
#7
Thread Starter
Junior Member
Re: VB.Net 2010 - FileSystemWatchers
You should do it, plenty of work here for coders, we're trying to hire one at the moment. (www.seek.co.nz or www.trademe.co.nz for job listings in NZ)
Okay thanks for the above that all works well, except after one detection the filewatcher stops and so does the debugger! shouldnt it keep running until the enableraisingevents = false?
I want to continue monitoring until I choose to stop.
-
Mar 3rd, 2012, 03:09 PM
#8
Re: VB.Net 2010 - FileSystemWatchers
I already had visa to live, but could not sell the house or I would already be there!
Likely you had an exception of some sort, I would guess that the event is not being fired on the main thread, so you adding an entry to the listbox is causing a cross-thread exception. For now, take out that line, just use the messagbox to ensure it is working. If this is working OK, then lookup UI threading in the code bank.
-
Mar 12th, 2012, 06:17 PM
#9
Thread Starter
Junior Member
Re: VB.Net 2010 - FileSystemWatchers
Private WithEvents TheFileWatcher As FileSystemWatcher
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
lstFolders.Items.Add("C:\temp\1")
lstFolders.Items.Add("C:\temp\2")
Me.cmdStopWatch.Enabled = False
End Sub
Public Sub cmdWatch_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdWatch.Click
fnWatchFolders()
End Sub
Public Function fnWatchFolders() As Boolean
'Only seems to watch the last folder passed to the fnWatchFolder
For i As Integer = 0 To lstFolders.Items.Count - 1
TheFileWatcher = New FileSystemWatcher(lstFolders.Items(i), "*.txt")
TheFileWatcher.NotifyFilter = NotifyFilters.FileName
TheFileWatcher.EnableRaisingEvents = True
Next
cmdWatch.Enabled = False
cmdStopWatch.Enabled = True
cmdAddFolder.Enabled = False
cmdRemoveFolder.Enabled = False
cmdExit.Enabled = False
Return True
End Function
Public Sub OnChanged(ByVal source As Object, ByVal e As FileSystemEventArgs) Handles TheFileWatcher.Changed, TheFileWatcher.Created, TheFileWatcher.Renamed, TheFileWatcher.Deleted
MsgBox("Change detected: " & (e.FullPath & " : " & e.ChangeType.ToString("G")))
Debug.Print("change" & e.FullPath & " : " & e.ChangeType.ToString("G"))
Dim strChangeItem As String = ("change" & e.FullPath & " : " & e.ChangeType.ToString("G"))
'addChangedDataToChangedListboxInvoker(strChangeItem) ' doesn't work as expected yet.
End Sub
Now as i see it, each time a filesystem watcher is instigated via the loop that holds the folder locations, the filesystemwatcher is getting overidden to only monitor that last folder.
somehow does there need to be a collection of file system watchers that each are incremented so that there is FSW1, FSW2 etc so that it can handle this? and then are the onchanged events FSW.changed fsw.created need to be fsw(x).created etc or am i over complciating this...
I dont get how this needs to be structured, yet it seems so simple!!!
-
Mar 12th, 2012, 06:55 PM
#10
Re: VB.Net 2010 - FileSystemWatchers
Yes, a collection of system watchers. I gave you a hint earlier .
Code:
Private MyFSWList As New Generic.List(Of FileSystemWatcher)
Code:
'Inside a loop
Dim TheFileWatcher As New FileSystemWatcher(lstFolders.Items(i), "*.txt")
TheFileWatcher.NotifyFilter = NotifyFilters.FileName
TheFileWatcher.EnableRaisingEvents = True
AddHandler TheFileWatcher. xxxxx, AdressOf xxx 'You can not use withevents on items that are not declared individually
MyFSWList.Add(TheFileWatcher) 'Adding this to the collection keeps a reference to it, thus stopping it going out of scope
-
Mar 12th, 2012, 07:25 PM
#11
Thread Starter
Junior Member
Re: VB.Net 2010 - FileSystemWatchers
Okay, so theory was right, but implementation still unsure...
remembering, that i will have (X) number of folders to watch. and this will only be known at runtime, the code needs to read in these values and create a 'handled' watcher for each instance. so each instance that is identified at runtime let say 5, will need to be declared somehow in here with the xxx's ?
For i As Integer = 0 To lstFolders.Items.Count - 1
Dim TheFileWatcher As New FileSystemWatcher(lstFolders.Items(i), "*.txt")
TheFileWatcher.NotifyFilter = NotifyFilters.FileName
TheFileWatcher.EnableRaisingEvents = True
AddHandler TheFileWatcher. xxxxx, AdressOf xxx 'You can not use withevents on items that are not declared individually
MyFSWList.Add(TheFileWatcher) 'Adding this to the collection keeps a reference to it, thus stopping it going out of scope_
Next
It would seem that you are giving me an inch, when I really need a foot.
setting myself up for beer when you get down here again aren't I!
-
Mar 12th, 2012, 07:33 PM
#12
Re: VB.Net 2010 - FileSystemWatchers
If I gave you a foot, you would not know what to do with it next time .
Code:
Dim TheFileWatcher As New FileSystemWatcher(lstFolders.Items(i), "*.txt")
Notice the NEW keyword, it is creating a new copy. Because it is new, you have no reference to it, you have no handlers, and nothing setup to tell you about changes. So, the next couple of lines setup those parts
Code:
TheFileWatcher.NotifyFilter = NotifyFilters.FileName
TheFileWatcher.EnableRaisingEvents = True
Then you have to attach up the handles manually, which you know how to do, as you did it in the first post!
Code:
AddHandler TheFileWatcher.Changed, AddressOf OnChanged
I did not give you this directly, as you have actually changed the events you are watching since your first post to include others:
Code:
AddHandler TheFileWatcher.Changed, AddressOf OnChanged
AddHandler TheFileWatcher.Created, AddressOf OnChanged
Remember, this is inside a loop, and you are calling this on every NEW watcher, so you are adding in your example 5 handlers for .Changed, and another 5 for .Created etc etc.
-
Mar 12th, 2012, 08:17 PM
#13
Thread Starter
Junior Member
Re: VB.Net 2010 - FileSystemWatchers
Okay, brilliant, thanks for clarifying that...
so the below works well and makes sense, I guess the addhandler creates its own magical accessible instance of 'thefilewatcher' which is why it didnt makes sense to me. (surely it would overwrite each time, but it doesnt so good)
Code:
Public Function fnWatchFolders() As Boolean
For i As Integer = 0 To lstFolders.Items.Count - 1
Dim TheFileWatcher As New FileSystemWatcher(lstFolders.Items(i), "*.txt")
TheFileWatcher.NotifyFilter = NotifyFilters.FileName
TheFileWatcher.EnableRaisingEvents = True
AddHandler TheFileWatcher.Changed, AddressOf OnChanged
AddHandler TheFileWatcher.Created, AddressOf OnChanged
AddHandler TheFileWatcher.Renamed, AddressOf OnChanged
AddHandler TheFileWatcher.Deleted, AddressOf OnChanged
MyFSWList.Add(TheFileWatcher) 'Adding this to the collection keeps a reference to it, thus stopping it going out of scope_
Next
cmdWatch.Enabled = False
cmdStopWatch.Enabled = True
cmdAddFolder.Enabled = False
cmdRemoveFolder.Enabled = False
cmdExit.Enabled = False
Return True
End Function
Now moving back to an earlier query, which is providing visual notification of the changes, so lstchanges.items.add(strchangeItem) This fails to work and the program just halts as we talked about earlier, so i tried RTFM and invoked the following, but this just doesnt not seem to work, no doubt have got this wrong somewhere! (commented in magenta)
Code:
Public Sub OnChanged(ByVal source As Object, ByVal e As FileSystemEventArgs) Handles TheFileWatcher.Changed, TheFileWatcher.Created, TheFileWatcher.Renamed, TheFileWatcher.Deleted
Dim strChangeItem As String = ("Change Detected: " & e.FullPath & " : was " & e.ChangeType.ToString("G"))
MsgBox(strChangeItem)
Debug.Print(strChangeItem)
'lstChanges.Items.Add(strChangeItem) 'addChangedDataToChangedListboxInvoker(strChangeItem) ' doesn't work as expected yet. End Sub
Private Delegate Sub addChangedDataToChangedListboxInvoker(ByVal strChangeItem As String)
Private Sub addChangedDataToChangedListbox(strChangeItem As String)
If Me.lstChanges.InvokeRequired Then
Me.lstChanges.Invoke(New addChangedDataToChangedListboxInvoker(AddressOf addChangedDataToChangedListbox))
Else
Me.lstChanges.Items.Add(strChangeItem)
End If
End Sub
Also, I'm guessing we need to use that collection created above, when we want to stop the filewatcher from running,
Obviously here, its not going to be an instance anymore so will fail, as we want to use the collection of TheFileWatcher(s) and set .enableraisingevents to false for each of the items in the collection somehow ?
Code:
Private Sub cmdStopWatch_Click(sender As System.Object, e As System.EventArgs) Handles cmdStopWatch.Click
TheFileWatcher.EnableRaisingEvents = False
cmdWatch.Enabled = True
cmdStopWatch.Enabled = False
cmdAddFolder.Enabled = True
cmdRemoveFolder.Enabled = True
cmdExit.Enabled = True
End Sub
-
Mar 12th, 2012, 08:55 PM
#14
Thread Starter
Junior Member
Re: VB.Net 2010 - FileSystemWatchers
Hmnn seems the closing the watchers was easier than I expected...
Code:
For Each fsw In MyFSWList
fsw.EnableRaisingEvents = False
Next
works a treat...
the updating of controls is not so easy!
-
Mar 13th, 2012, 02:04 AM
#15
Re: VB.Net 2010 - FileSystemWatchers
Originally Posted by n10ct
I guess the addhandler creates its own magical accessible instance of 'thefilewatcher' which is why it didnt makes sense to me. (surely it would overwrite each time, but it doesnt so good)
There is no magic involved, it was as I explained earlier, you create a NEW filewatcher object inside the loop first, it is this NEW object that you add the handler for.
-
Mar 13th, 2012, 02:20 AM
#16
Re: VB.Net 2010 - FileSystemWatchers
In answer to your other question, there is an example here of how to access the control from off the UI thread exactly as you need.
Code:
Private Delegate Sub SetTextBoxText(ByVal text As String)
Private Sub SetTextBoxText(ByVal text As String)
If Me.TextBox1.InvokeRequired Then
Me.TextBox1.Invoke(New SetTextBoxTextInvoker(AddressOf SetTextBoxText), _
text)
Else
Me.TextBox1.Text = text
End If
End Sub
You seem to have used this, but I notice a crucuial parameter missing from this line?
Code:
Me.lstChanges.Invoke(New addChangedDataToChangedListboxInvoker(AddressOf addChangedDataToChangedListbox))
-
Mar 13th, 2012, 02:51 PM
#17
Thread Starter
Junior Member
Re: VB.Net 2010 - FileSystemWatchers
doh! works like a charm, must have cut off that damn parameter!!!
thank you for your direction!! kinda glad I forced myself to do this in vb.net, and not just do it in vb6 (which would have been way faster!) next step is to see if i can manipulate services like i could with vb6 and provide this as a windows service that has some notifyicon and form capacity as well. ( yeah i know this breaks some rules but works faultlessly in vb6 on a few hundred thousand desktops I know of. haha.
I imagine .net service control/creation maybe harder to manipulate!
-
Mar 13th, 2012, 04:06 PM
#18
Re: VB.Net 2010 - FileSystemWatchers
Actually it is far far easier than in VB6 .
-
Apr 13th, 2012, 05:30 AM
#19
Thread Starter
Junior Member
Re: VB.Net 2010 - FileSystemWatchers
Hmnn, beg to differ on the far easier in VB6,
you are so limited in what you can "make happen" with all the new rules etc, (but its easier from the point of view you dont need a whole structure template if you dont already have one) but in anycase I have managed to get a windows service running and all the SQL using LINQ (woooooo!) working and populating a SQL database beautifully, currently it runs at around 1000 event rows per day, which is great.
I have one issue that doing my head in, and the only way I have been able to successfuly debug the service, to get the exact line of code that the errors is occuring is do eventlog reporting on a per line of code basis!
The issue with this fault is that it happens every 600 - 800 events ( or every 8 - 12 hours) so debugging manually is not possible.
So for part of my filesystemwatcher OnChanged event:
Code:
Dim intFileSize As Integer
Try
LogInfo("debug run 15")
Dim info As New FileInfo(strChangeFullFilePath)
LogInfo("debug run 16")
intFileSize = info.Length
LogInfo("debug run 17")
Catch ex As Exception
LogInfo("debug run 18")
Throw ex
LogInfo("debug run 19")
End Try
LogInfo("debug run 20")
If intFileSize = Nothing Then intFileSize = 0
LogInfo("debug run 21")
Now all this does obviously is grabs the filesize for the file that the filesystemwatcher has discovered, in my case its a .TMP file that is renamed to .XXX when it has finished the copy routine.
So every 600 - 800 events (or 8 - 12 hrs), I'm getting a:
Application: OnlineReportingEngine.exe Framework Version: v4.0.30319 Description: The process was terminated due to an unhandled exception. Exception Info: System.OverflowException Stack: at OnlineReportingEngine.OnlineReportingEngineService.OnChanged(System.Object, System.IO.FileSystemEventArgs) at System.IO.FileSystemWatcher.CompletionStatusChanged(UInt32, UInt32, System.Threading.NativeOverlapped*) at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)
In my event log reporting i am getting "Debug Run 15", "Debug Run 16","Debug Run 18" which means the offending line of code is definately:
Code:
intFileSize = info.Length
now for what ever reason, it might be a 200GB file or a 200MB file, so this could just be a timing thing, but regardless, I want to do this right..
I could just use a thread sleep for say 5000, but i'd be happy enough for the overflow error to be handled exception out and just present 0 as filesize, rather than crash the service, but id prefer to get the filesize.
What would be the best way to handle this kind of situation ?
and why is my try catch not handling it? what have I done wrong here?
all my others are working as expected, just this one is odd.
-
Apr 13th, 2012, 07:48 AM
#20
Re: VB.Net 2010 - FileSystemWatchers
The answer to your issue is pretty simple, look at the documentation for the .Length property and you will see that it is in fact a Long, not an Integer. You are finding a file that is longer than the size of the integer. You should actually get this as an error if you have Option Strict/Explicit turned On (should do anyway).
Your Try/Catch is handling the exception, however you are just throwing it again, which will stop the process as nothing else higher up the stack is available to catch it.
Last edited by Grimfort; Apr 13th, 2012 at 08:00 AM.
-
Apr 13th, 2012, 02:07 PM
#21
Thread Starter
Junior Member
Re: VB.Net 2010 - FileSystemWatchers
Oh my god!! I can't believe I missed that!
Thank you yet again! Geez gonna be more like a crate of beers when you get here!
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|