C++ 将文件写入U盘会导致意外删除时文件损坏/锁定

C++ 将文件写入U盘会导致意外删除时文件损坏/锁定,c++,winapi,usb,writefile,C++,Winapi,Usb,Writefile,我正在编写一个后台应用程序,使用“优化以快速删除”策略集将循环中的文件复制到U盘。但是,如果在这个过程的一段时间内(特别是在下面的WriteFile()调用中,它返回错误FILE NOT FOUND)移除了棍子,那么应用程序将挂起,然后,任何其他应用程序都无法永久访问该驱动器,并且无法关闭/注销/重新启动电脑等。所有正在运行的Windows资源管理器实例也因此挂起 我已经追踪到了这个问题,它是在移除棍子并发生上述错误后进行的CloseHandle()调用。就好像CloseHandle()在驱动程

我正在编写一个后台应用程序,使用“优化以快速删除”策略集将循环中的文件复制到U盘。但是,如果在这个过程的一段时间内(特别是在下面的WriteFile()调用中,它返回错误FILE NOT FOUND)移除了棍子,那么应用程序将挂起,然后,任何其他应用程序都无法永久访问该驱动器,并且无法关闭/注销/重新启动电脑等。所有正在运行的Windows资源管理器实例也因此挂起

我已经追踪到了这个问题,它是在移除棍子并发生上述错误后进行的CloseHandle()调用。就好像CloseHandle()在驱动程序的某个地方无限期阻塞,因为斗杆已经不在了?无论如何,如果WriteFile()返回未找到错误文件,我只需跳过CloseHandle()调用,就可以解决这个问题。但是,这会导致另一个问题,即文件经常会出现无法恢复的损坏,唯一的修复方法是使用chkdsk,或者重新格式化棍子

请注意,这只发生在XP(SP2和SP3)上,Vista似乎没有遇到这个问题。下面是一段代码:

HANDLE hFile = CreateFile(szFile, 
                          GENERIC_WRITE, 
                          FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
                          NULL,
                          CREATE_ALWAYS,
                          FILE_FLAG_WRITE_THROUGH,
                          NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
    if (!WriteFile(hFile, pBuffer, dwBufferSize, &dwWritten))
    {
        int nLastError = GetLastError();
    }

    // If usb stick is removed during WriteFile(), ERROR_FILE_NOT_FOUND usually      results.
    // If handle is closed at this point then drive is inaccessible.
    // If CloseHandle() is skipped, then file corruption occurs instead
    if (nLastError != ERROR_FILE_NOT_FOUND)
    {
        CloseHandle(hFile);
    }
}
我尝试了CreateFile()的几乎所有标志组合,但都没有效果。以前有没有人见过这一点,或者有什么好主意如何避免出现这两个问题中的任何一个。我看到的是一个在vista下被默默修复的驱动程序问题吗


感谢您的帮助。

关于挂起问题:您可以生成一个单独的写入线程,从主线程监督写入过程,如果花费的时间可疑,则中止写入线程。换句话说:异步实现写入并查找超时

这似乎是驾驶员的问题

必须释放驱动程序的所有句柄,使其自行清理,并释放windows以卸载它。当你不这样做时,驱动程序认为它仍然要对设备负责,即使它发生了变化

在用户模式下无法避免此问题

放弃句柄只会将问题转移到以后的阶段(例如退出程序,以便windows尝试关闭所有放弃的打开句柄)

几乎就好像CloseHandle()在驱动程序的某个地方无限期地阻塞,因为 棍子不在了

听起来很合理。CloseHandle()最终将发出一个文件系统IRP,而您没有使用非阻塞I/O,因此IRP将是同步的,但看起来实际的文件系统从文件系统驱动程序下面突然消失了,IRP永远不会完成。这意味着您已被填满-导致文件系统IRP被发出的用户模式函数调用将永远不会返回

尝试使用非阻塞I/O——这将很好地解决这个问题,至少从不挂起的角度来看是这样的。您仍然会经历资源丢失之类的情况,因为IRP仍然会被传递下去,几乎可以肯定的是,它仍然不会恢复,但至少您不会阻塞它

顺便说一句,“为快速删除而优化”是我想说的设计,旨在减少正在进行的缓存量,并可能影响文件系统的写入顺序,以减少损坏的机会;我非常怀疑它是为了在写入过程中文件系统离开时保留文件系统


这会导致文件系统死机,您不必感到惊讶。

这可能是文件系统驱动程序而不是硬件驱动程序的问题吗?您可能会发现,如果使用NTFS,问题就会消失。

谢谢您的回复。这确实可以解决我的应用程序挂起的问题,但是文件系统上挂载的驱动器也已经损坏了。任何其他应用程序仍然无法访问它,PC将挂起关闭/注销等。永远不要中止线程。在任何用例中,这都可能有所帮助。您只会面临“状态损坏”等风险。如果线程挂起,您还能做什么?我并不是说这是一个完美的解决方案,但中止线程并冒着状态崩溃的风险,这肯定会使整个应用程序挂起。@AdrianGrigore:您可以让线程等待驱动程序操作完成。