问题 当用户不使用“安全删除硬件”时,如何确保文件永久保存在USB上?


当我在delphi应用程序中的USB上保存文件时,如果没有执行“安全删除硬件”(特别是忘记使用),如何确保文件真正(永久)保存在USB上?
告诉我们的客户使用Windows功能“安全删除硬件”不起作用。
是否有一个Windows API命令来刷新缓冲区,以便所有数据永久写入USB驱动器?


9494
2017-10-28 08:54


起源

对于投票结束为“不编程相关”的人,请重新阅读该问题。 - Lasse Vågsæther Karlsen
和这里一样。这个问题与编程有关。
我从来没有数据丢失,我可以归因于删除USB存储设备而不执行“安全删除硬件”。我确保文件复制操作完成(“复制文件”对话框消失)。我非常幸运吗? - Les
莱斯:是的。我已经失去了很多次数据...... - Jörgen Sigvardsson


答案:


这是我用于在以编程方式弹出数据之前将数据刷新到USB驱动器的功能。这克隆了功能 Mark Russinovich的“同步”实用程序。我对这段代码没有任何问题,并且已经在很多系统上运行了几年。

此代码中最相关的部分是调用 FlushFileBuffers

function FlushToDisk(sDriveLetter: string): boolean;
var
  hDrive: THandle;
  S:      string;
  OSFlushed: boolean;
  bResult: boolean;
begin
  bResult := False;
  S := '\\.\' + sDriveLetter + ':';

  //NOTE: this may only work for the SYSTEM user  
  hDrive    := CreateFile(PAnsiChar(S), GENERIC_READ or
    GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil,
    OPEN_EXISTING, 0, 0);
  OSFlushed := FlushFileBuffers(hDrive);

  CloseHandle(hDrive);

  if OSFlushed then
  begin
    bResult := True;
  end;

  Result := bResult;
end;

3
2017-10-28 13:44



这是为了刷新卷上的所有打开文件。如果Max只关心他的程序正在编写的文件,而不是用户可能通过其他方式写入驱动器的任何其他文件,那么他可能只是将句柄刷新到他的文件而不是刷新整个卷,并且因此,他不需要行政特权。 - Rob Kennedy
几乎不可能保证不存在腐败。闪存盘可以随时拔出。我认为MSalters的回答更为正确。我同意Rob的意见,它是磁盘范围的。 - Matt
为什么这个代码使用3个变量(OSFlushed,bResult和Result)时只有一个似乎可以完成这项工作? - EMBarbosa
@EMBarbosa,好点。我添加这个主要是为了清晰,而不是作为最简洁的方法的一个例子。 - Mick


打开文件时,请指定“直写”(FILE_FLAG_WRITE_THROUGH标志为CreateFile())。这将迫使操作系统直接写出文件。它可能仍然在OS缓存中以加速后续读取,但这对您来说不是问题。

如果你确实想要刷新文件缓冲区,那当然总是如此 FlushFileBuffers()


11
2017-10-28 10:13



当我使用FlushFileBuffers()时,我能确定文件是否物理存储在USB驱动器上?因此,在“不受控制”的拔出后,它并没有消失? - markus_ja
@max:是的,只要在调用FlushFileBuffers()和删除物理写入之间有足够的时间。 IOW,如果您尝试将2GB文件写入USB磁盘,请调用FlushFileBuffers(),然后+立即+删除驱动器,它仍然无法完全写入 - 只是没有足够的时间来完成实际的写操作。您需要教育您的用户如何安全地删除驱动器,或至少等到您的应用告诉他们可以删除它;你的应用程序可以确定它需要等待多长时间才能让它们正常。 - Ken White
肯,你让它听起来像FlushFileBuffers将在实际完成刷新文件缓冲区之前返回。那是对的吗?如果是的话,那么 怎么样 程序应该知道需要等待多长时间? - Rob Kennedy


无论发生什么,你都可以自己拔掉设备,我的意思是以编程方式。那么你将完全确定他们已正确删除了设备。

看看这个问题的答案: 使用-Win32的API安全去除的-USB驱动器,。特别 这个链接到msdn kb文章 在答案中给出。


2
2017-10-28 09:13



但是,如果用户不想删除USB驱动器怎么办? - simon
用户已经卸下了USB驱动器,我认为他不再需要它了。更严重的是,如果他等待更长时间使用驱动器,文件将最终写入磁盘(该文件永远不会保留在缓存中)。 (我每天都在与这类客户打交道,对他们来说越简单,对每个人来说都越好。告诉他们他们不能使用驱动器,这很简单;告诉他们必须去“安全地移除硬件”,这太过分了。我敢打赌我们的OP已经有一些代码可以自动检测USB驱动器插入并将所需文件复制到预定路径 - Adrien Plisson
Adrien,我们只知道用户正在移除驱动器 有时。我们不知道那个用户 总是 保存后删除驱动器。我们也不知道驱动器是否用于此程序以外的其他设备。 - Rob Kennedy
@rob:你是对的,我只是根据自己的亲身经历做出假设......我的坏。 - Adrien Plisson