【问题标题】:How to remove the file which has opened handles?如何删除已打开句柄的文件?
【发布时间】:2016-09-24 04:17:10
【问题描述】:

问题历史:
现在我使用 Windows Media Player SDK 9 在我的桌面应用程序中播放 AVI 文件。它在 Windows XP 上运行良好,但是当我尝试在 Windows 7 上运行它时我发现了一个错误 - 我无法在播放后立即删除 AVI 文件。问题是存在打开的文件句柄。在 Windows XP 上,我在播放文件期间打开了 2 个文件句柄,它们在关闭播放窗口后关闭,但在 Windows 7 上,我在播放文件期间已经打开了 4 个句柄,其中 2 个在播放窗口关闭后保留。它们只有在关闭应用程序后才能免费。

问题:
我怎么解决这个问题? 如何删除已打开句柄的文件?可能存在“强制删除”之类的东西?

【问题讨论】:

    标签: c++ qt file-io windows-7 windows-media-player


    【解决方案1】:

    问题在于,您并不是唯一获得文件句柄的人。其他进程和服务也可以打开该文件。因此,在他们释放句柄之前,无法删除它。您可以在这些句柄打开时重命名文件。您可以在这些句柄打开时复制文件。但是,不确定您是否可以将文件移动到另一个容器?

    其他流程和服务,尤其是。包括防病毒、索引等。

    这是我编写的一个函数,用于在 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;
    }
    

    【讨论】:

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

    从技术上讲,您可以使用MoveFileEx 并传入MOVEFILE_DELAY_UNTIL_REBOOT 来删除锁定的文件。当lpNewFileName参数为NULL时,Move变成delete,可以删除锁定的文件。但是,这适用于安装人员,除其他问题外,还需要管理员权限。

    【讨论】:

    • 您能否提供一个证明链接,证明 MoveFileEx 以这种方式工作,即“Move 变为删除并可以删除锁定的文件”?
    • 在MSDN上的函数规范中,我帖子中的链接:'如果dwFlags指定MOVEFILE_DELAY_UNTIL_REBOOT并且lpNewFileName为NULL,则MoveFileEx注册lpExistingFileName文件在系统重启时被删除。如果 lpExistingFileName 引用了一个目录,则系统仅在目录为空时才会在重新启动时删除该目录。'
    【解决方案3】:

    您是否检查过哪个应用程序仍在使用 avi 文件? 您可以使用handle.exe 来做到这一点。您可以在关闭正在使用该文件的进程后尝试删除/移动该文件。

    替代解决方案是使用unlocker 应用程序(免费)。

    以上两种方法之一应该可以解决您的问题。

    【讨论】:

    • 我使用 COM 接口与 Windows Media Player 交互,我需要以编程方式删除锁定的文件。
    • 在这种情况下,您将不得不编写一个内核驱动程序,该驱动程序将遍历打开的文件句柄列表,然后获取所有者进程的名称,然后对该进程执行任何您想要的操作(来自内核空间):)
    【解决方案4】:

    您是否已经尝试让 WMP 释放句柄? (IWMPCore::close 似乎是这样做的)

    【讨论】:

      猜你喜欢
      • 2018-05-21
      • 1970-01-01
      • 2011-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多