When renaming a folder in C#, System.IO.Directory.Move
throws System.IO.IOException
(message \"access denied\") if that folder or any subfolder is curr
I've used API Monitor v2 by Rohitab to monitor Windows API calls.
When changing the directory name from D:\test
to D:\abc
, this call was logged:
explorerframe.dll ITransferSource::RenameItem ( 0x0000000015165738, "abc", TSF_COPY_CREATION_TIME | TSF_COPY_LOCALIZED_NAME | TSF_COPY_WRITE_TIME | TSF_DELETE_RECYCLE_IF_POSSIBLE, 0x00000000150f77d0 )
Digging further into the output of the monitor shows some native calls:
As you can see, they're not using MoveFile
, instead, they use NtOpenFile
with FILE_OPEN_FOR_BACKUP_INTENT
and others to open the original directory, then call NtSetInformationFile
with the new directory name and the flag FileRenameInformation
which is documented here.
Unfortunately, these are all kernel calls.
You can get a handle to a directory in C/C++ from user-mode like this:
HANDLE h = ::CreateFileA("D:\\test",
DELETE | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
But then, you still need a user-mode alternative for the NtSetInformationFile
-call.
Some options to proceed (ordered by complexity):
NtSetInformationFile
DeviceIoControl
from C#.Update
Seems like the SHFileOperation function does all of the above as found by the OP.
Will leave this answer online, because it might show others how to debug similar problems and get valuable pointers.