How to detect when a folder change is completed?

400 views Asked by At

I'm using Delphi and ReadDirectoryChangesW (in a TThread) to detect when a particular folder has changes. This is working quite nicely. I need to know when the changes are done so I can then safely do something with the file.

Here's the scenario: I've mapped a printer to a specific file name and folder (FILE: local port c:\MonitorMe\prinfil.dat). The only file in the folder will be that printer file. The print job can be single page, or hundreds of pages - and I have to wait until the "print to file" is complete before triggering further action. I'm monitoring FILE_NOTIFY_CHANGE_SIZE and FILE_NOTIFY_CHANGE_LAST_WRITE - so I will get periodic notices that the file is still "being printed to".

I'm looking for a safe way to actually detect when the "print" is complete. I thought I might set a timer up in the form, and call Synchronize(StillPrinting) in the thread. StillPrinting would stop and restart the timer such that only after some 300 ms of NO folder changes would the timer execute - triggering an OnAfterPrintComplete event. That just seems dangerous.

Is there anything I can look for to determine if the file save has been completed?

1

There are 1 answers

1
AmigoJack On

"File has been completed" is subjective - just think about it for 5 minutes and you'll come to the conclusion you're asking for something that rarely makes sense:

  • Speed of writing can vary: you might expect a file to be written in 2 seconds on one system while it takes 5 minutes on another.
  • Drawing the line: at which point do you consider a "write" to be completed and at which point are other writes appending to the existing file? Thing about logs where it can take i.e. 2 years until another write to that file occurs. Likewise your printer job/program can idle for 10 minutes for whatever reason but still access the file.
  • Modifications: what about a file that has been written from byte 1 to 52000 but afterwards bytes 10 to 19 are overwritten? When is that considered "completed"?
  • Even SetEndOfFile() only "cuts" (or extends) a file at a given point, but nobody knows if additional writes at any position will occur.

No. But there are various approaches to achieve the same:

  • Setting file attributes, i.e. R could signal that no more writes will occur. Because you as a consumer only want read access anyway. Of course, the "printer" has to set it.
  • Inspecting the file content for a valid footer, or if any of its format seems to be incomplete. This both requires you to know the print file format and the print file to have a format at all (instead of just being a binary stream).
  • Trying to open the file without any sharing permission (not even FILE_SHARE_READ) - this should fail as long as another process accesses the file. You can expect the printer job to not open/close the file multiple times (although that's a possibility, too).
  • Abusing files as "writing complete" markers: if the file has been written, create another (empty) file whose existence alone signals that the other file is complete. As per your print job/program you could add another short/simple print task and judge that as soon as 2 files exist the one of interest must be completed (while the other is irrelevant to you).