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

柔情痞子 提交于 2019-12-12 19:52:10

问题


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 directory 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?


回答1:


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.




回答2:


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




回答3:


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.



来源:https://stackoverflow.com/questions/5313799/renaming-a-directory-locks-renamed-dir-the-second-time-i-want-to-rename

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!