tags:

views:

759

answers:

7

I am writing a simple application that will rename JPEGs with the date/time they were taken before the current filename. This is so that I can combine all the photos that I took with those of my partner (different camera makes and filenames).

The following piece of code is where the failure occurs:

private void RenameFile(String oldFilename, String newFilename)
{
    if (File.Exists(oldFilename)
    {
        File.Move(oldFilename, newFilename);
    }
}

Example values: oldFilename = "E:\001.jpg" | newFilename = "E:\2009-08-07 06h05 -- 001.jpg"

The exception I am getting is:

System.IO.IOException was unhandled
  Message=The process cannot access the file because it is being used by another process.
  Source=mscorlib
  StackTrace:
       at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
       at System.IO.__Error.WinIOError()
       at System.IO.File.Move(String sourceFileName, String destFileName)
       at RenamePhotos.Form1.btnRenamePhotos_Click(Object sender, EventArgs e) in C:\Users\Neil Deadman\Desktop\RenamePhotos\RenamePhotos\Form1.cs:line 107
       at System.Windows.Forms.Control.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
       at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ButtonBase.WndProc(Message& m)
       at System.Windows.Forms.Button.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(Form mainForm)
       at RenamePhotos.Program.Main() in C:\Users\Neil Deadman\Desktop\RenamePhotos\RenamePhotos\Program.cs:line 18
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()

If I use File.Copy instead then it works, but I have two files and can't delete the original and using File.Delete I get the same (or similar) exception.

During some tests, if I rename it to E:\a001.jpg then it seems to work?? The filename is valid as I can rename it using Windows Explorer. :S

Any ideas? The fact that some renames work seems to say it isn't a locking issue?

Cheers Neil

A: 

There is another process, or maybe your own process currently using the file. This will prevent the file from being removed, but it will not prevent it from being copied. Most likely, your program opened the file but forgot to close it.

monksy
+2  A: 

The fact that some renames work seems to say that it is not an external locking issue, but maybe in your program. If you put a breakpoint on File.Move(oldFilename, newFilename); can you still rename it from explorer?

klausbyskov
Tried that and I couldn't. Says its in use by vshost.exe. Interesting though that it it fails with the name I want but works if I force it to start with "a".
neildeadman
A: 

Two possibilities:

  1. The source file really is being held open by another app. In my experience, lots of Windows applications leave files open for longer than they should. Windows Explorer is probably the worst offender in this regard. I recommend you look at the Process Explorer and Process Monitor utilities from Microsoft SysInternals.

  2. The destination file already exists. You should check for that in your method as well as checking the source file.

Christian Hayter
I'd agree, but it works for a different filename... I'll look deeper into it with Process Explorer.
neildeadman
A: 

The exception indicates that the file is in use - this could be by the application itself, i.e. are you creating/opening the file elsewhere and not closing it?

Another option is that the file is open for editing in another program and hasn't been closed.

You can use FileMon to check who owns the lock on the file.

Oded
+4  A: 

See File.Move on MSDN.

Specifically You cannot use the Move method to overwrite an existing file.

James
See Common I/O Tasks on MSDN (http://msdn.microsoft.com/en-us/library/ms404278.aspx).Specifically: Rename or move a file.
neildeadman
@neil, this is if you are moving a file to a new location AND renaming it. Not trying to rename the same file in the same location...
James
A: 

File is probably still in use by some process on your system, most likely your program. You can use Process Explorer to check which process is using the file, and go further from there.

dbkk
A: 

Thanks to everyone who posted. I managed to get it working with the following method

private void RenameFile(String oldFilename, String newFilename)
{
    FileInfo file = new FileInfo(oldFilename);

    if (file.Exists)
    {
        File.Move(oldFilename, newFilename);
    }
}

Strangely, my original didn't work but the above did.

The real issue was that I was debugging the code which still causes the IOException to be thrown. If I run the built application, it works fine!

Thanks Again! I just couldn't believe it when it would let me rename to certain names... must have been seeing things!

Neil

neildeadman
You can access that method without instanciation as it is static. Try `if (System.IO.File.Exists(oldFilename))` instead.
Sonny Boy