如何删除已打开句柄的文件?

4

问题历史:
现在我使用Windows Media Player SDK 9在我的桌面应用程序中播放AVI文件。在Windows XP上运行良好,但当我尝试在Windows 7上运行时,遇到了一个错误 - 播放结束后无法立即删除AVI文件。问题在于存在已打开的文件句柄。在Windows XP上,在播放文件期间我有2个打开的文件句柄,并且在关闭播放窗口后它们被关闭,但在Windows 7上,在播放文件期间我已经有4个打开的句柄,其中2个在关闭播放窗口后仍然存在。只有在关闭应用程序后它们才会变为空闲状态。

问题:
我该如何解决这个问题?如何删除已打开句柄的文件?是否存在类似“强制删除”的东西?

4个回答

3
问题在于,你不是唯一一个获取文件句柄的人。其他进程和服务也可以打开该文件。因此,在它们释放句柄之前,无法删除它。但是,在这些句柄打开的情况下,您可以将文件重命名或复制文件。不确定是否可以将文件移动到另一个容器中?
其他进程和服务,特别是包括杀毒软件、索引等。
以下是我编写的一个函数,可在Windows下实现“立即删除”:
bool DeleteFileNow(const wchar_t * filename)
{
    // don't do anything if the file doesn't exist!
    if (!PathFileExistsW(filename))
        return false;

    // determine the path in which to store the temp filename
    wchar_t path[MAX_PATH];
    wcscpy_s(path, filename);
    PathRemoveFileSpecW(path);

    // generate a guaranteed to be unique temporary filename to house the pending delete
    wchar_t tempname[MAX_PATH];
    if (!GetTempFileNameW(path, L".xX", 0, tempname))
        return false;

    // move the real file to the dummy filename
    if (!MoveFileExW(filename, tempname, MOVEFILE_REPLACE_EXISTING))
    {
        // clean up the temp file
        DeleteFileW(tempname);
        return false;
    }

    // queue the deletion (the OS will delete it when all handles (ours or other processes) close)
    return DeleteFileW(tempname) != FALSE;
}

但是,如果这些文件(视频文件!)太大且数量太多,使用此策略会导致缺少可用空间 - 临时文件会占用我的驱动器空间。我下载文件,播放它,然后多次删除。 - SKINDER
2
嗯 - 我认为你没有理解情况。上述技术并不会创建文件的副本 - 它只是将它们重命名,以便原始文件立即消失。重命名后的文件仍然会被尽可能快地删除 - 既不慢也不快。没有办法强制操作系统更快地删除它,一般来说,这只需要几秒钟的延迟(足够让您的防病毒软件或索引服务关闭其文件句柄并允许文件消失)。 - Mordachai

1

从技术上讲,您可以使用MoveFileEx并传递MOVEFILE_DELAY_UNTIL_REBOOT来删除已锁定的文件。当lpNewFileName参数为NULL时,移动操作变成了删除操作,并且可以删除已锁定的文件。但是,这仅适用于安装程序,而且需要管理员权限,同时还存在其他问题。


你能提供一个证明链接,证明MoveFileEx的工作方式是“移动变成删除并可以删除锁定文件”吗? - SKINDER
2
在MSDN的函数规范中,我帖子中的链接所述:如果dwFlags指定MOVEFILE_DELAY_UNTIL_REBOOT并且lpNewFileName为NULL,则MoveFileEx会在系统重新启动时注册要删除的lpExistingFileName文件。 如果lpExistingFileName引用目录,则仅当该目录为空时,系统才会在重新启动时删除该目录。 - Remus Rusanu

0
你是否检查过哪个应用程序仍在使用AVI文件? 你可以使用handle.exe来做这个。在关闭正在使用该文件的进程后,您可以尝试删除/移动该文件。
另一种解决方案是使用 unlocker 应用程序(免费的)。
上述两种方法之一应该可以解决你的问题。

我使用COM接口与Windows Media Player进行交互,并需要通过编程方式删除锁定的文件。 - SKINDER
在这种情况下,您将需要编写一个内核驱动程序,该驱动程序将遍历打开文件句柄列表,然后获取所有者进程的名称,然后可以在内核空间中对该进程执行任何操作 :) - Vikram.exe

0

你是否已经尝试过要求WMP释放句柄呢?(IWMPCore::close似乎可以做到这一点)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接