Как сделать так, чтобы файл был постоянно сохранен на USB, если пользователь не использует Safely Remove Hardware?

Когда я сохраняю файл на USB в моем приложении delphi, как я могу убедиться, что файл действительно (постоянно) сохранен на USB, когда «Безопасное извлечение оборудования» не выполняется (особенно забыто использовать)?
Сообщая наш клиент, использующий функцию Windows «Безопасное извлечение оборудования», не работает.
Есть ли команда Windows API для очистки буфера, чтобы все данные постоянно записывались на USB-накопитель?


person markus_ja    schedule 28.10.2009    source источник
comment
Тем, кто проголосовал за закрытие как не имеющий отношения к программированию, пожалуйста, перечитайте вопрос.   -  person Lasse V. Karlsen    schedule 28.10.2009
comment
Тут то же самое. Вопрос во многом связан с программированием.   -  person    schedule 28.10.2009
comment
У меня никогда не было потери данных, которую я могу отнести к удалению USB-накопителя без выполнения безопасного удаления оборудования. Я удостоверяюсь, что операции копирования файлов завершены (диалог «копирование файлов» исчезает). Мне очень повезло?   -  person Les    schedule 28.10.2009
comment
Лес: Да. Я много раз терял данные ...   -  person Jörgen Sigvardsson    schedule 30.05.2011


Ответы (3)


Вот функция, которую я использовал для сброса данных на USB-накопитель перед их программным извлечением. Это клонирует функциональные возможности утилиты Марка Руссиновича "Sync". У меня не было проблем с этим кодом, и он уже пару лет работает на многих системах.

Самая важная часть этого кода - это вызов 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;
person Mick    schedule 28.10.2009
comment
Это для очистки всех открытых файлов на томе. Если Макс заботится только о файлах, которые пишет его программа, а не о каких-либо других файлах, которые пользователь может записывать на диск другими способами, то он, вероятно, может просто сбросить дескрипторы своих файлов вместо того, чтобы сбрасывать весь том, и поэтому ему не потребуются административные привилегии. - person Rob Kennedy; 28.10.2009
comment
Гарантировать отсутствие коррупции практически невозможно. Флеш-диск можно вытащить в любой момент. Думаю, ответ MSalters более правильный. Я согласен с Робом, он занимает весь диск. - person hookenz; 01.03.2012
comment
Почему в этом коде используются 3 переменных (OSFlasted, bResult и Result), когда кажется, что только один выполняет работу? - person EMBarbosa; 01.06.2012
comment
@EMBarbosa, хорошее замечание. Я добавил это в основном для ясности, а не как пример наиболее лаконичного способа сделать это. - person Mick; 01.06.2012

Когда вы открываете файл, укажите «сквозную запись» (флаг FILE_FLAG_WRITE_THROUGH для CreateFile ()). Это заставит ОС записать файл напрямую. Он может все еще находиться в кеше ОС для ускорения последующих чтений, но для вас это не проблема.

Если вы действительно хотите очистить файловые буферы, конечно, всегда есть FlushFileBuffers ()

person MSalters    schedule 28.10.2009
comment
Когда я использую FlushFileBuffers (), могу ли я быть уверен, что файл физически хранится на USB-накопителе? Значит, он не пропадает после неконтролируемого отключения от сети? - person markus_ja; 28.10.2009
comment
@max: Да, если между вызовом FlushFileBuffers () и удалением достаточно времени для выполнения физической записи. IOW, если вы попытаетесь записать файл размером 2 ГБ на USB-диск, вызовите FlushFileBuffers (), а затем + немедленно + удалите диск, он все равно может не быть полностью записан - просто не хватит времени для завершения фактической операции записи. Вам необходимо обучить пользователей тому, как безопасно удалить диск, или, по крайней мере, подождать, пока ваше приложение не сообщит им, что они могут его удалить; ваше приложение может вычислить, сколько времени нужно ждать, прежде чем дать им это согласие. - person Ken White; 28.10.2009
comment
Кен, вы говорите так, будто FlushFileBuffers вернется до того, как фактически закончит очистку файловых буферов. Это правильно? Если да, то как программа должна вычислить, сколько времени ей нужно ждать? - person Rob Kennedy; 28.10.2009

что бы ни случилось, вы можете отключить устройство самостоятельно, я имею в виду программно. тогда вы будете полностью уверены, что они сняли устройство правильно.

посмотрите ответы на этот вопрос: safe-remove-usb-drive- using-win32-api. особенно эту ссылку на статью msdn kb, указанную в ответ.

person Adrien Plisson    schedule 28.10.2009
comment
Но что, если пользователь не хочет извлекать USB-накопитель? - person simon; 28.10.2009
comment
пользователь уже извлекает USB-накопитель, я не думаю, что он ему больше нужен. более серьезно, если бы он дольше ждал, чтобы использовать диск, файл в конечном итоге был бы записан на диск (файл не хранится в кеше вечно). (Я каждый день имею дело с такими клиентами, чем проще для них, тем лучше для всех. Скажите им, что они не могут использовать диск, это просто; скажите им, что они должны пойти и безопасно удалить оборудование, это тоже много. Могу поспорить, что у нашего OP уже есть код для автоматического обнаружения вставки USB-накопителя и копирования необходимого файла по заранее определенному пути) - person Adrien Plisson; 28.10.2009
comment
Адриан, мы знаем только, что пользователь извлекает диск иногда. Мы не знаем, что пользователь всегда удаляет диск после сохранения. Мы также не знаем, используется ли диск для других целей, кроме этой программы. - person Rob Kennedy; 28.10.2009
comment
@rob: ты прав, я просто делал предположения, основываясь на собственном личном опыте ... у меня плохо. - person Adrien Plisson; 28.10.2009