Dim f As FileStream = New FileStream(e.FullPath, FileMode.Open, _
FileAccess.Read, FileShare.Read, 8192)
f = New FileStream(e.FullPath, FileMode.Open, FileAccess.Read, _
FileShare.Read, 8192)
md5.ComputeHash(f)
Edit
Notice anything odd? You are opening a filestream on the file, then immediately opening another filestream on the same file using the same variable without closing the first. Thats one reason it reports the file open in VS. Delete the f = New FileStream...
line.
You will have ANOTHER problem here when the event fires due to a File Delete.
Then:
Dim ObjFSO As Object = CreateObject("Scripting.FileSystemObject")
Dim objFile = ObjFSO.GetFile(e.FullPath)
These last 2 dont appear to do anything. The objects are created but not used. But since objFile
is built from the file in question, it could be preventing you from deleting or working with the file.
Dim hash As Byte() = md5.Hash
Dim buff As StringBuilder = New StringBuilder
Dim hashByte As Byte
For Each hashByte In hash
buff.Append(String.Format("{0:X1}", hashByte))
Next
md5code = buff.ToString()
Since you now have the MD5 code, you should close the filestream (f
) so you can do other things. You cannot delete or move the file while it is open.
If md5code = "D41D8CD98F0B24E980998ECF8427E" Then
' Dim frm2 As New Form2
' frm2.Show()
TestForm.Show()
f.Close()
Else
f.Close()
End If
As with your previous code, if TestForm is form class, you must create an instance of it:
Dim frm As New TestForm
frm.Show ' or frm.ShowDialog
Forms are just classes. You must instance them before using them.
Edit continued
Finally, the freeze is a result of doing too much in a log event (log change AND compute MD5 AND show a new form). You have probably noticed that your app does not slow down while monitoring many files in many folders. Thats because the filewatcher runs on a different thread. When you create an instance of a new form or show it from that event, the form apparently runs on that thread.
You need to rework your code to remove the stuff that does not relate to actual logging. In that event, instead of all that stuff you might add the changed file to a List(of String) which represents a todo list. Do the MD5 and form stuff elsewhere on that list so it takes place on your app's thread.
FINAL edit
If all you are worried about is the form freezing, add this:
watchfolder = New System.IO.FileSystemWatcher()
watchfolder.SynchronizingObject = Me
It will only delay more major issues, but you seem to think it is important. Next, I have told you this 3 times now, but you MUST exit the log routines if the file operation was a delete because you cannot open a deleted file:
Case IO.WatcherChangeTypes.Deleted
Exit Sub ' after the log
The next problem you will get is when 2+ files have changed. You need a way to queue files/tasks. Your approach to calling other subs for some stuff DOES break things down to discrete tasks, but those called sub are called from the FW thread so you just moved the problem around. For a queue I was thinking a List(of String) but a new class (as suggested in your last post) with its own BackgroundWorker might be better.
Public Class FileMgr
Friend thisFile As String
Friend thisHash As String = ""
Dim frm2 As Form2
Private WithEvents bw As BackgroundWorker
Public Sub New(ByVal f As String)
thisFile = f
bw = New BackgroundWorker
AddHandler bw.DoWork, AddressOf ProcessFile
' Explorer might not be done creating it yet,
' especially if you drop 3-4 files, so wait
Threading.Thread.Sleep(250)
' start the BW with the name of the file
bw.RunWorkerAsync(thisFile)
End Sub
ProcessFile is just your (fixed) MD5 sub with a new declaration:
Private Sub ProcessFile(ByVal sender As Object, _
ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bw.DoWork
Dim sFile As String = e.Argument
AGAIN, CLOSE THE FILE ONCE YOU HAVE THE HASH:
md5.ComputeHash(f)
f.Close()
DONT OPEN ANY FORMS. JUST GET THE HASH.
For Each hashByte In hash
buff.Append(String.Format("{0:X1}", hashByte))
Next
thisHash = buff.ToString() ' last line!!!
When the BackgroundWorker is done, it raises an event:
Private Sub bw_RunWorkerCompleted(ByVal sender As Object, _
ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) _
Handles bw.RunWorkerCompleted
' I dont know why each file has to have its own form rather
' that a report item in a listbox but I also dont know why you
' are computing a hash for a 0 byte new file
If thisHash = "D41D8CD98F0B24E980998ECF8427E" Then
frm2 = New Form2
frm2.Label1.Text = thisFile
frm2.Show()
End If
End Sub
End Class
To use it, takes one line of code in the log events:
Dim fMgr As New FileMgr(e.FullPath)
EACH file operation Windows reports will create a new file helper which will run its own BackgroundWorker. Since you arent doing too much there wont be too many alive at one time until you are processing files larger than 0 bytes. You also need a Try/Catch in MD5Sub/ProcessFile for times when the file is open and in use.
I dropped 6 files in the watch folder, got 6 copies of Form2, no errors and no freezes (and not even an upvote for all this).