Moving the file while it's still being created

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 Boolean

While Success = False

Try

Success = True

File.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

Else

Success = False

End If

Catch ex As Exception

' TODO: Write log and trace entries

End Try

End While

It 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.



Answer this question

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

    While testing, I just copied large mpg files to folder that is being monitored. I don't know how the files will be created in production environment, but I need to make sure service can handle any type of situation.
  • 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

    No, same thing. File.Exists returns true while file is still being created.
  • 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

    Hi guys
    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

  • 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;

    }

    else

    i = 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

    This doesn't relate to your actual question, but this line of code brought up some huge alarm bells for me:

    If ex.Message <> "The process cannot access the file because it is being used by another process." Then

    Exception messages are not constant - they can change depending on the *user's* current language. They often change between releases .NET - the last thing you want is your code to break because the exception message was slightly changed!

    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&amp;#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.



  • Moving the file while it's still being created