如何重命名当前由Windows资源管理器打开的c#中的文件夹

use*_*015 11 c# directory rename windows-explorer

在C#中重命名文件夹时,如果(Windows 7)资源管理器窗口当前打开了该文件夹或任何子文件夹,则System.IO.Directory.Move抛出System.IO.IOException("拒绝访问"消息).使用命令行也RENAME失败了.使用第二个浏览器窗口成功.

即使在折叠父文件夹(或其父文件夹)后,该错误仍然存​​在.实际上,需要关闭特定的资源管理器窗口.因此,探险家似乎只是为了显示文件夹结构而创建一些锁,即使实际文件夹不再显示也不会释放它们(这是纯粹的非文本IMO).

有没有办法重命名文件夹(在程序中,例如使用C#),目前由资源管理器窗口显示(或可见,见上文)?

更新

找到了我自己对这个问题的回答(见下文)所描述的方法SHFileOperation().但是,这种解决方案不太可行(另见下文).

huy*_*itw 5

我使用了Rohitab的API Monitor v2来监控Windows API调用.

当改变从目录名D:\test来D:\abc,此呼叫记录:

explorerframe.dll   ITransferSource::RenameItem ( 0x0000000015165738, "abc", TSF_COPY_CREATION_TIME | TSF_COPY_LOCALIZED_NAME | TSF_COPY_WRITE_TIME | TSF_DELETE_RECYCLE_IF_POSSIBLE, 0x00000000150f77d0 )
Run Code Online (Sandbox Code Playgroud)

进一步深入监视器的输出显示一些本机调用:

在此输入图像描述

正如你所看到的,他们没有使用MoveFile,而是使用NtOpenFile与FILE_OPEN_FOR_BACKUP_INTENT和别人开原来的目录,然后调用NtSetInformationFile新目录名称和标志FileRenameInformation被记录在这里.

不幸的是,这些都是内核调用.

您可以从用户模式获取C/C++中的目录句柄,如下所示:

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);
Run Code Online (Sandbox Code Playgroud)

但是,您仍然需要NtSetInformationFile-call 的用户模式替代方案.

一些选项(按复杂程度排序):

  • 看看你是否可以使用shell接口ITransferSource::RenameItem或找到一个现成的shell函数
  • 进一步深入了解用户模式解决方案并尝试寻找替代方案 NtSetInformationFile
  • 编写一个驱动程序,其中包含执行这些内核模式的IOCTL并DeviceIoControl从C#调用.

更新

似乎该SHFileOperation功能完成了OP发现的所有上述内容.

将在线留下这个答案,因为它可能会向其他人展示如何调试类似问题并获得有价值的指示.


use*_*015 5

所以我在进一步研究后回答我自己的问题..

可以使用SHFileOperation()如下所示重命名该文件夹: https: //learn.microsoft.com/en-us/windows/win32/shell/manage
(无论这是否使用 Wouter 提到的“魔法”。;-)

但是如果有 windows/.Net API,比如System.IO.Directory.Move,我还需要使用 Shell 吗?不谈性能...

不管怎样,使用SHFileOperation()C# 是一种痛苦,因为你需要声明所有这些 p-invoke 东西。在这种特殊情况下,您需要对 32 位和 64 位 Windows 使用不同的结构,因为打包不同(请参阅https://www.pinvoke.net/default.aspx/shell32.shfileoperation)。这非常麻烦,因为通常我会指定AnyCPU作为目标。此时,您要么需要在运行时进行分支(确实非常糟糕),具体取决于您是 64 位还是 32 位进程,要么您为两个不同的目标进行不同的构建,这对于解决愚蠢的资源管理器来说是一个相当大的影响。

问候