Filewatcher code won't allow delete?

jmurdock

Member
Joined
Jul 6, 2005
Messages
7
Programming Experience
5-10
I am working on an application which will allow users to ftp xml files onto our web-server. A windows service using filewatcher will 'see' the file, bring it in, process it, then delete it.

I have used the following code:
<code>

strFileName = e.FullPath.ToString

EventLog.WriteEntry(Me.ServiceName, Me.ServiceName & " File found = " & strFileName, EventLogEntryType.Information)

e = Nothing

Try
File.Delete(strFileName)
Catch ex As Exception
EventLog.WriteEntry(Me.ServiceName, Me.ServiceName & " fsWatcher_Created Delete File " & ex.ToString, EventLogEntryType.Error)
End Try
</code>

The log indicates that the file is found, it writes to the event viewer the proper filename and path, then it logs that the delete attempt failed, reason given: the file is in use by another process.

I am assuming that it is the filewatcher itself that has the file? If so how do I make it 'let go'?
 

jmcilhinney

VB.NET Forum Moderator
Staff member
Joined
Aug 17, 2004
Messages
14,579
Location
Sydney, Australia
Programming Experience
10+
What exactly does "bring it in, process it" mean? Also, if this is an event handler then you shouldn't really be setting "e" to Nothing. It is passed by value so it doesn't make a difference outside the procedure, but why do you need to do it anyway? Setting a reference to Nothing has no effect on the referenced object itself.
 

jmurdock

Member
Joined
Jul 6, 2005
Messages
7
Programming Experience
5-10
jmcilhinney said:
What exactly does "bring it in, process it" mean? Also, if this is an event handler then you shouldn't really be setting "e" to Nothing. It is passed by value so it doesn't make a difference outside the procedure, but why do you need to do it anyway? Setting a reference to Nothing has no effect on the referenced object itself.

I need to read the xml file. Parse it (using an XMLReader) then store the information in a database.

Once that is done I need to delete the file.

I have tried to read the file, delete the file, rename the file... anything I could think of to get control of the file so that I can do SOMETHING that will ultimately allow me to read the file.

It all fails and says the file is in use.

I tried setting e to nothing thinking that 'e' was the piece of code locking the file. If it ceased to exist then perhaps I could read the file since it would not be in use. I was wrong. What ever is locking the file, setting e to nothing (You cannot dispose of it) does not release it.
 

jmcilhinney

VB.NET Forum Moderator
Staff member
Joined
Aug 17, 2004
Messages
14,579
Location
Sydney, Australia
Programming Experience
10+
Show us the code that opens and parses the XML file. It is almost certainly that section that is locking the file and not releasing it.

Note that setting any reference-type variable (read: class) to Nothing does not affect the object itself in any way. The object still exists in memory, but you do not have a refence to it any longer. If that object can be, but was not, disposed then that is a bad thing because you cannot then dispose it. Voila, memory leak!
 

jmurdock

Member
Joined
Jul 6, 2005
Messages
7
Programming Experience
5-10
Have a look at the code I posted (first posting). It has the exact same problem and it is much simpler. If I can figure out how to release the file for deletion (the code posted) then I can use the same logic to release the file to read it.

Thanks.

(By the way... isn't it the middle of the night in Australia???)
 

jmcilhinney

VB.NET Forum Moderator
Staff member
Joined
Aug 17, 2004
Messages
14,579
Location
Sydney, Australia
Programming Experience
10+
I used the following code:
VB.NET:
	Private Sub FileSystemWatcher1_Created(ByVal sender As Object, ByVal e As System.IO.FileSystemEventArgs) Handles FileSystemWatcher1.Created
		Debug.WriteLine("Found file: " & e.Name)

		Try
			IO.File.Delete(e.FullPath)
			Debug.WriteLine("File deleted.")
		Catch ex As Exception
			Debug.WriteLine("Delete failed.")
		End Try
	End Sub
with no issue. I created a new text file and moved it to the folder being watched and it was found and deleted without a problem. Obviously your file is being locked elsewhere, as I suspected.
 

jmurdock

Member
Joined
Jul 6, 2005
Messages
7
Programming Experience
5-10
I really appreciate you taking the time to try that. I used you code (cut an pasted it. I added code to write errors to the event log since this is a service and there is no interface. I get this:


Event Type: Error
Event Source: SpendTrackImportSvc
Event Category: None
Event ID: 0
Date: 7/7/2005
Time: 8:49:48 PM
User: N/A
Computer: SMART1
Description:
SpendTrackImportSvc System.IO.IOException: The process cannot access the file "e:\WebSitesEtc\Inetpub\ftproot\SpendTrackFiles\40cb80e5-1cf5-43d8-828e-3c7b95177c9e.txt" because it is being used by another process.
at System.IO.__Error.WinIOError(Int32 errorCode, String str)
at System.IO.File.Delete(String path)
at SpendTrackImportSvc.SpendTrackImportSvc.fsWatcher_Created(Object sender, FileSystemEventArgs e)
For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.


My code now looks like this:

Private Sub fsWatcher_Created(ByVal sender As System.Object, ByVal e As System.IO.FileSystemEventArgs) Handles fsWatcher.Created

Dim strFileName As String

Debug.WriteLine("Found file: " & e.Name)

Try

IO.File.Delete(e.FullPath)

Debug.WriteLine("File deleted.")

Catch ex As Exception

Debug.WriteLine("Delete failed.")

EventLog.WriteEntry(Me.ServiceName, Me.ServiceName & " " & ex.ToString, EventLogEntryType.Error)

End Try



End Sub

 

jmcilhinney

VB.NET Forum Moderator
Staff member
Joined
Aug 17, 2004
Messages
14,579
Location
Sydney, Australia
Programming Experience
10+
Like I said, when I tested my code I created the file in a different folder and moved it into the folder being watched. At this point it was not being accessed by any other process. How is your file being created? If it is your program that is creating it then perhaps the FSW event is being raised before your program has closed the file. I've never written a service before, so I'm not sure if debugging them is the same as debugging a WinForms app. If you can debug as normal, I'd say you need to put a breakpoint on the line that closes the file and another on the line that deletes it and see which one gets executed first. If its being a service is an issue, create a WinForms test app that does the same thing and iron out the kinks in it first.
 

jmurdock

Member
Joined
Jul 6, 2005
Messages
7
Programming Experience
5-10
[Resolved]

You got it! AHA!

I was using the copy command (command line) to move a number of files into the 'watched' directory. You suggested maybe the weren't done copying.

I added a simple loop, I count to 10 million THEN try to delete. Works like a charm.

I will be looking for some way to tell if the file is done being written (put it in a loop and check) then when it is, i can pass the file name to the function that reads the xml and does the work.

I figure there has to be a proper way to see if a file is locked. I now just have to find it!

Thanks!
 

jmcilhinney

VB.NET Forum Moderator
Staff member
Joined
Aug 17, 2004
Messages
14,579
Location
Sydney, Australia
Programming Experience
10+
It's generally better to avoid throwing an exception if possible, but you could use something like this:
VB.NET:
	Private Sub FileSystemWatcher1_Created(ByVal sender As Object, ByVal e As System.IO.FileSystemEventArgs) Handles FileSystemWatcher1.Created
		For i As Integer = 1 To 10
			Try
				IO.File.Delete(e.FullPath)
				Exit Sub
			Catch ex As Exception
				'Wait 1 second before trying again.
				Threading.Thread.Sleep(1000)
			End Try
		Next

		MessageBox.Show("File could not be deleted.")
	End Sub
If it seems that it is always failing the first time, you could move the call to Sleep to before the Try block. That way it will wait 1 second before trying the first time.
 

jmcilhinney

VB.NET Forum Moderator
Staff member
Joined
Aug 17, 2004
Messages
14,579
Location
Sydney, Australia
Programming Experience
10+
You might also try putting the two operations in SyncLock blocks. I'm not sure what the threading situation is with a FSWs events, but if you put the Copy and Delete calls inside SyncLock blocks that take the same expression, then I think that should prevent the call to Delete being made until the call to Copy has completed. I'd suggest you give it a try. Read the help topic on the SyncLock Statement for further details.
 

jmurdock

Member
Joined
Jul 6, 2005
Messages
7
Programming Experience
5-10
[Resolved]

I used a hybrid, your code and the line of thought I was on before I saw your code (I went with a half second because I just hate to wait ;) ):

Try

strFileName = e.FullPath

Do While IO.File.GetAttributes(strFileName) = FileAttributes.Offline
'Wait 1/2 second before trying again.
Threading.Thread.Sleep(500)
Loop
Threading.Thread.Sleep(500)
IO.File.Delete(e.FullPath)
EventLog.WriteEntry(Me.ServiceName, Me.ServiceName & " " & strFileName, EventLogEntryType.SuccessAudit)

Catch ex As Exception
EventLog.WriteEntry(Me.ServiceName, Me.ServiceName & " " & ex.ToString, EventLogEntryType.Error)
End Try

It works like a charm. I dropped 20 files in 3 times and it worked every time.

Thank you very much for your help! (And now it's off to bed! Thanks again!)
 
Top Bottom