开发者

Renaming a directory locks renamed dir the second time I want to rename

开发者 https://www.devze.com 2023-02-16 19:22 出处:网络
I\'m having problems with renaming a directory multiple times, it seems to lock the file. // e comes from a objectListView item

I'm having problems with renaming a directory multiple times, it seems to lock the file.

// e comes from a objectListView item
DirectoryInfo di = (DirectoryInfo)e.RowObject;
DirectoryInfo parent = Directory.GetParent(di.FullName);
String newPath = Path.Combine(parent.FullName, e.NewValue.ToString());

// rename to some temp name, to help change lower and uppercast names
di.MoveTo(newPath + "__renameTemp__");
di.MoveTo(newPath);

// Trying to cleanup to prevent d开发者_JAVA百科irectory locking, doesn't work...
di = null;
parent = null;
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);

Any help is much appreciated, because the first rename works okay, but when trying to do a new rename on the renamed folder, it throws an exception :

The process cannot access the file because it is being used by another process. A first chance exception of type 'System.IO.IOException' occurred in mscorlib.dll

So first time rename that folder works, second time throws exception, I'm guessing the application holds a lock on the new folder, but how to work around it? I should be able to rename a folder twice right?


Introduction

To reproduce your problem, I created the following method:

private static string RenameFolder(string path, string newFolderName)
{
    DirectoryInfo di = new DirectoryInfo(path);
    DirectoryInfo parent = Directory.GetParent(di.FullName);
    String newPath = Path.Combine(parent.FullName, newFolderName);

    // rename to some temp name, to help change lower and uppercast names
    di.MoveTo(newPath + "__renameTemp__");
    di.MoveTo(newPath);

    return di.FullName;
}

When I call it like the following, it works:

var path = @"C:\Temp\test";
var newPath = RenameFolder(path, "TESt");
newPath = RenameFolder(path, "Test1");

When I call it like the following, it doesn't work:

var path = @"C:\Temp\test";
var newPath = RenameFolder(path, "TESt");
newPath = RenameFolder(newPath, "Test1");

The only difference between the two calls is, that in the first version I pass in the original name, i.e. everything in lower case. In the second case, I supply the new name, i.e. everything in uppercase except the last letter. Even sleeping for 20 seconds in between the two calls to RenameFolder doesn't change that. Odd!

Solution

If I implement RenameFolder like this, it works in both cases:

private static string RenameFolder(string path, string newFolderName)
{
    String newPath = Path.Combine(Path.GetDirectoryName(path), newFolderName);

    // rename to some temp name, to help change lower and uppercast names
    Directory.Move(path, newPath + "__renameTemp__");
    Directory.Move(newPath + "__renameTemp__", newPath);

    return newPath;
}

Somehow, DirectoryInfo seems to have a case sensitive lock on the path.

Explanation
I have none, maybe someone with a little bit more insight into the internal ways of DirectoryInfo can shed some light on this strange behavior.

Important point
Don't use GC.Collect if you don't know, what you are doing! Normally, you don't need to call this method.


Grab a copy of Process Monitor and see exactly what has locked that directory after your rename:

http://technet.microsoft.com/en-us/sysinternals/bb896645


My previous answers were wrong. As mentioned in the comments, the MoveTo() method updates the DirectoryInfo object to represent the new path, which isn't clearly documented.

As Daniel Hilgarth points out in his answer, the problem probably lies somewhere else. You might need to add logic which checks when the directory is accessible again.

0

精彩评论

暂无评论...
验证码 换一张
取 消