- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
function FileIsBusy(AFileName: string): Boolean;
var
F: Integer;
begin
F := FileOpen(AFileName, fmShareExclusive);
Result := F = -1;
FileClose(F);
end;
function WaitFile(AFileName: string; ASpeepDelay: integer): Boolean;
begin
while FileIsBusy(AFileName) do
Sleep(ASpeepDelay);
Result := True;
end;
пока юзверь ковыряется в Ворде, другой процесс мечтает овладеть файлом
"It is necessary to wait of end of editing Microsoft Office files.I use next conventional approach: file is editing While file is busy" (ингриш - питерского разлива)
это stackoverflow такими сниппетами переполнено
на десктопе? ояебу
а раз тут дельфи, значит, скорей всего, для редактирования он порождал новый процесс. Так что тут надо всего лишь дождаться завершения этого процесса
По-нормальному, это делается открытием файла на эксклюзивный доступ однажды - после получения события об изменении файла (точнее, после таймаута событий, потому что они могут идти тоннами, например от ворда) и забыванием про него в случае INVALID_HANDLE до следующего события.
А если программа открывала файл, но так ничего и не изменила?
Я считаю, что в общем случае на винде задача решается только так, так написал автор якобы говнокода.
Повторюсь, что в общем случае это не будет работать.
Можно представить себе приложение, которое после окончания записи будет делать flush, чтобы очистить буферы и вызвать событие изменения файла, потом выжидать полчаса (чтобы враг не догадался) и только потом отпускать файловый дексриптор. В реальной жизни таких программ нет, и сохранение производится двумя способами:
1. Открыл файл, записал, закрыл
2. Создал новый файл, записал в него, переименовал старый в темп, переименовал новый в старый
Алгоритм, который я описываю, покрывает оба этих случая.
Простой тест на "общий случай" - запись в файл, флаш, ожидание и закрытие файла. Вешаем FSW на систему и смотрим, что нам выведет.
[STAThread]
static void Main(string[] args)
{
FileSystemWatcher fsw = new FileSystemWatcher();
fsw.Path = "D:\\";
fsw.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.Size | NotifyFilters.FileName;
fsw.EnableRaisingEvents = true;
fsw.Filter = "*";
fsw.Changed += new FileSystemEventHandler(fsw_Changed);
Stream s = new FileStream("D:\\test1.txt", FileMode.Create, FileAccess.Write);
s.Write(new byte[500], 0, 500);
s.Flush();
Thread.Sleep(10000);
s.Close();
Console.ReadLine();
}
static void fsw_Changed(object sender, FileSystemEventArgs e)
{
Console.WriteLine("{0}: {1}", e.ChangeType, e.Name);
}
Выводит 2 события Changed. Первое при изменении, второе при закрытии.
P.S. Жаль, что на MSDN не документированы все тонкости.