问题
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