Hi everyone,
I have the following problem. I use FileSystemWatcher.Created event to call a procedure that needs to move that file. Well, Created event should be called Creating, because it raises when file creation begins, and while it is being created. So, my problem is that I can not move the file until process that is creating the file ends. This is my solution:
Dim
Success As BooleanWhile Success = False
TrySuccess =
TrueFile.Move(sourcePath, destPath)
Catch ex As IOException If ex.Message <> "The process cannot access the file because it is being used by another process." Then ' TODO: Write log and trace entries ElseSuccess =
False End If Catch ex As Exception ' TODO: Write log and trace entries End Try End WhileIt works, but I don't like it. First of all, is there some better way to separate this type of error from all other IOException type of errors (such as FileNotFound...), and is there some way to find out if file is free to move, without throwing exceptions.

Moving the file while it's still being created
Gianni Patrono
hi
Please could you send me the open source library
thanx alot
Dermot French
WindRiverPublishing
One way to handle this is for the process that is creating the file to create it with a temporary name, close it, then rename it.
The receiving process will only see it when it is renamed, by which time it will no longer be locked.
liat
balcanuc
This problem is quite complex to solve.
I am currently developping a complete FilesystemWatcher Framework to watch any kind of file and then to apply any kind of actions to those watched files. This solution is working in production and works fine for all kind of files that are sent through the network by Macintoshes and PCs
There are two basic ideas to make a robust file system watcher:
First you must wait that the file is stable for a certain amount of time. A stable file is a file for which the last_created and the last_accessed and the last_write dates do not change for a fixed period of time. The recommended wait time is around 3 seconds. Below 3 seconds, keep in mind that you are fighting againt the OS, which might lead to a very bad situation if the CPU is overloaded.
The second idea is that the only way to check if a file is locked or not is to try to write to it. If you can write to it, then you may make any action on this file ( like moving it).
You cannot rely on the content of the exception message since it depends of the language of the installed Framework. For example in english you may search for the pattern "used by another process" , but in french the pattern will be "utilise par un autre process".
You can use the following method to check if the file is still locked or not after being created:
'''<summary>Check if the file is locked by another process.
'''<returns>Returns True if the file is locked by another process</returns>
'''<remarks></remarks>
'''</summary>
Public Function FileIsBusy(ByVal FilePath As String) As Boolean
Try
' clear previous errors
If Not ClearLastErrors() Then
' do something in next release
End If
If FilePath Is Nothing Then
Dim sErr As String = "File path is nothing"
Throw New System.ApplicationException(sErr)
End If
If FilePath.Length = 0 Then
Dim sErr As String = "File path is empty"
Throw New System.ApplicationException(sErr)
End If
Try
' Check if the file exists
If Not System.IO.File.Exists(FilePath) Then
Return False
End If
' Check if the file is Read Only
Dim mySetReadOnlyAttribute As Boolean = False
If FileIsReadOnly(FilePath) Then
' try to remove the Read-Only attribute
' A file can be ReadOnly and locked by another process ( for example a PDF file opened by Acrobat)
If RemoveFileAttributeReadOnly(FilePath) Then
mySetReadOnlyAttribute = True
End If
End If
Try
Dim myFileStream As System.IO.FileStream = New System.IO.FileStream(FilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.Read, 1024)
' we work with the FileStream object in a try...catch...Finally block
' in order to be sure to close the FileStream whatever happens
Try
If Not myFileStream.CanRead Then
Return True
End If
If Not myFileStream.CanWrite Then
Return True
End If
Catch ex As System.IO.IOException
Return True
Catch ex As Exception
Throw ex
Finally
If myFileStream IsNot Nothing Then
myFileStream.Close()
myFileStream.Dispose()
End If
End Try
Catch ex As System.IO.IOException
Return True
Catch ex As Exception
Throw ex
Finally
If mySetReadOnlyAttribute Then
If Not SetFileAttributeReadOnly(FilePath) Then
' do something in next release
End If
End If
End Try
Return False
Catch ex As Exception
RealTimeTrace(ex, FilePath)
Return False
End Try
Catch ex As Exception
RealTimeTrace(ex)
Return False
End Try
End Function
As you see, this is not a simple job ! But this the only way I found to work in all kind of situation.
You should call this method through a System timer ( Not a Windows form timer). Again the waiting time between each call must be at least 1 second ( do not forget, you are fighting against the OS).
I am ready to publish the full source code library (VB.NET 2.0, Visual Studio 2005, about 50 000 lines of source code) as an open source library that you will be able to include in your code.
If you are interrested, please let me know.
Henri d'Orgeval
MCAD.NET /MCT
Deep Dreams
I use Created event & set filter to FileName. When i suspend the thread for 100ms (Thread.Sleep(100)) it doesn't break down anymore.
May be a dirty solution but it's not dirtier than what FileSystemWatcher does!
Henri-Pierre
Then probably you should use FileSystemWatcher.Changed event and trap on the ChangeTYpe Property = WatcherChangerType.Created.
http://msdn.microsoft.com/library/default.asp url=/library/en-us/cpref/html/frlrfsystemiofilesystemwatcherclasschangedtopic.asp
http://msdn.microsoft.com/library/default.asp url=/library/en-us/cpref/html/frlrfsystemiowatcherchangetypesclasstopic.asp
soccerjoe5
ahmedilyas,
I know I can not move the file while it's being created. I need to know how can I check if the file is available to be moved (there are no locks), or how can I catch exception that is thrown when file is locked, without relying on ex.Message property, because that property can change in different localized versions of .Net Framework.
WTHUGHES
I tried using the below code
if
(File.Exists("CREATING.txt")){
File.Delete("CREATING.txt");}
TextWriter tw = new StreamWriter("CREATING.txt",false);tw.WriteLine(
"Hello"); int i; if (File.Exists("CREATING.txt")){
i = 0;
}
elsei = 1;
tw.Close();
and i never reached the condition i =0; which means that the file did not exist until i did tw.Close();
How do you create your file
Greg Bowie
If ex.Message <> "The process cannot access the file because it is being used by another process." Then
It's safe to do a catch (IOException) in this case. File.Delete throws an IOException for only "file in use" and for no other reason.
Dafrapster
Henry,
Thanks a lot. Your code works. And sure, I'm interested in any open source library...
I hope that in some future versions of .Net Framework, Microsoft will include simple function to check if file is available for access, or at least to cover this type of exception with it's own exception class... Well, maybe they will read this...
Thanks to everyone who tried to help.
S&#233;bastien
Hello Henri,
Just wondering if you have published your Open source File System Watcher library. If so, can you please let us all know where we can download it
Thank you.
egeorge
There maybe a way but in my experience I dont think you can move a file WHILST its still being created as its locked by the OS file handler
either create the file in the path you want BEFORE writing/creating it or AFTER. This is probably the only way, in my experience but there maybe a solution for your problem
From what I know and understand, when you create a file you CANNOT move it as the OS is doing stuff to the file as requested, therefore its locked at the OS level until the file has been closed/operation completed.
JenniferL
try this(Code is in C#)
while(!File.Exists(sourceFile))
{
Thread.Sleep(1000);
}
File.Move(sourcePath, destPath)
Let me know if this does not work.