Archive: How to determine when a file has been written to disk?


How to determine when a file has been written to disk?
We are using NSIS to be the installer for a large number of individual installers, which will work with our system. We don't want to support changes to base script for individual components, as was the past method, because we want to be able to chang that base script. So each of the components we are building also has a "Hooks.nsh" file. This file is specific to each component, and may or may not exist.

The idea with the hooks file is to enable specific customization of each of the component installers, using the function callbacks.
PreInstallation - Before the installer writes anything to disk.
PostInstallation - After the installer has completed in the "Install" section.

We also have these as well for the uninstaller, obiviously named correctly.
These all work just fine.

However we also wanted to make a callback for each file being installed. Pre and Post installation for each file, so the following:

Function PreFileFilter
FunctionEnd

Function PostFileFilter
FunctionEnd


The idea is instead of doing a chunk of work at the end of the installation to copy around files, (which are sometimes huge,) we could instead modify the path of installer to out these files. So in a PreFileFilter the function could merely check for the file name, and change the location and/or name of the file. This too works perfectly.

In order to support this functionality, the code which generates the file list now instead of just generating a single file entry per file, generates the following:

;File .\state.xml
push "$OUTDIR"
StrCpy $CURRENTFILEPATH "$OUTDIR"
StrCpy $CURRENTFILENAME "state.xml"
Call PreFileFilter
StrCmp $ALLOWCURRENTFILE "0" lbl_skip_1
SetOutPath "$CURRENTFILEPATH"
File "/oname=$CURRENTFILENAME" ".\state.xml"
Call PostFileFilter
lbl_skip_1:
pop $OUTDIR


It generates the above, on a perfile basis. lbl_skip_1 increments per file of course. The globals $CURRENTFILENAME and $CURRENTFILEPATH are used to communicate with the filter functions.

So the issue I am having, is with the PostFileFilter, the PostFileFilter needs to be able to modify files, the above case, I need to be able to adjust "state.xml" however, when the PostFileFilter is called, the state.xml file, is not always there!!!!

So what I need is a way to ensure that the file has been written, before I call the PostFileFilter. How would I do this? I've tried ReserveFile for the files which I know will need to be modified in this manner, but to no avail. Also I've checked, and yes the file has not yet been written to disk at the point the PostFileFilter has been called, if I put a messagebox in the PostFileFilter, it stops there, and then I go check the directory.

Anyone have an idea of how to solve this? This would be incredibly useful for the system we are writing.

IfFileExists isn't enough? Also, there's a function in the wiki call to get file size, in case that you want if the file actually has bytes.


No IfFileExists is not enough, because what I need to know, is *WHEN* does the file get written to disk, and so that I can ensure that the file gets written to disk, *before* I need to modify it.


Wow! You want to know when the file get written? :\
I think you can only know if the file was written.
As I told you, you can know if a file has bytes with fileSize...Or..subclass the explorer to catch the written event.

For me, that's out of nsis league.


Yeah it is very important to know when, or to be able to force at a particular time, the file to be written.

So does anyone have an answer?


See NSIS documentation 4.8.2.7 SetDateSave and 4.9.3.7 GetFileTime