tags:

views:

279

answers:

6

Hi,

I need to accomplish the following task:

Attempt to move a file. If file is locked schedule for moving as soon as it becomes available.

I am using File.Move which is sufficient for my program. Now the problems are that:

1) I can't find a good way to check if the file I need to move is locked. I am catching System.IO.IOException but reading other posts around I discovered that the same exception may be thrown for different reasons as well.

2) Determining when the file gets unlocked. One way of doing this is probably using a timer/thread and checking the scheduled files lets say every 30 seconds and attempting to move them. But I hope there is a better way using FileSystemWatcher.

This is a .net 3.5 winforms application. Any comments/suggestions are appreciated. Thanks for attention.

A: 

Have a look at the FileSystemWatcher.

http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher(VS.90).aspx

Listens to the file system change notifications and raises events when a directory, or file in a directory, changes

Flo
I don't think `FileSystemWatcher` triggers an event if a file becomes available. Do you have a sample?
0xA3
Sorry, I thought the FileSystemWatcher would have events for locking/unlocking aswell, but it does not look like it does.
Flo
private void fileSystemWatcher1_Changed(object sender,System.IO.FileSystemEventArgs e){FileStream fs=null;try{fs=new FileStream(e.FullPath,FileMode.Open,FileAccess.Rea dWrite,FileShare.None,100);fs.Close();Console.WriteLine("closed, ready to process the file ");}catch{...}} this tries to open the file for writing and fails if the file is locked. But does not look like a nice solution to me.
Flo
+1  A: 

One possible alternative is by using MoveFileEx with a MOVEFILE_DELAY_UNTIL_REBOOT flag. If you don't have access to move the file right now, you can schedule it to be moved on the next reboot when it's guaranteed to be accessible (the moving happens very early in the boot sequence).

Depending on your specific application, you could inform the user a reboot is necessary and initiate the reboot yourself in addition to the moving scheduling.

Blindy
+3  A: 

You should really just try and catch an IOException. Use Marshal.GetHRForException to check for the cause of the exception. A notification would not be reliable. Another process might lock the file again before File.Move is executed.

Henrik
A: 

This is not specific to your problem, but generally you will always need to retain the 'try it and gracefully deal with a failure' mode of operation for this sort of action.

That's because however clever your 'detect that the file is available' mechanism is, there will always be some amount of time between you detecting that the file is available and moving it, and in that time someone else might mess with the file.

Will Dean
+1  A: 

It's simple:

        static void Main(string[] args)
        {
            //* Create Watcher object.
            FileSystemWatcher watcher = new FileSystemWatcher(@"C:\MyFolder\");

            //* Assign event handler. 
            watcher.Created += new FileSystemEventHandler(watcher_Created);

            //* Start watching. 
            watcher.EnableRaisingEvents = true;

            Console.ReadLine();
        }


        static void watcher_Created(object sender, FileSystemEventArgs e)
        {
            try
            {
                File.Move(e.FullPath, @"C:\MyMovedFolder\" + e.Name);
            }
            catch (Exception)
            {
                //* Something went wrong. You can do additional proceesing here, like fire-up new thread for retry move procedure.
            }
        }
Lukas Šalkauskas
I really wish it was simple as that ;)
m0s
The logic is simple, everything else depends on your imagination ;)
Lukas Šalkauskas
A: 

The scheduled retry on exception (probably increasing delays - up to a point) is probably the simplest way to achieve this (your (2) ). To do it properly you're going to have to drop to system level (with Kernel code) hooks to trap the file close event - which has its own idiosynchrases. It's a big job - several orders of magnitude more complex than the scheduled retry method. It's up to you and your application case to make that call, but I don't know of anything effective in between.

Phil Nash