[DUG] How to replace a file currently in use (Windows)
Paul Heinz
paul at accredo.co.nz
Wed Jan 19 12:23:15 NZDT 2011
Kyley wrote:
> I do it almost the same way..
>
> App.exe renames itself to App_old.exe while its running. then
> it downloads app.exe each time app.exe starts it deletes any
> app_old.exe that exist. This way you never need to run a
> different file.. effectively its the same thing.
>
> by doing it this way users on a network share always get the
> latest copy, even if people are still running in memory the
> old copy. The Old copy will be deleted as soon as all running
> instances are stopped and someone runs the new version.
Yes, it's a neat trick. Not many people seem to know that unlike Unix,
whilst you can't delete an open file in Windows (including .exe and
.dll), you can _rename_ them.
To do the self-update trick, I have seen developers still using .bat (or
.cmd) files to launch their app since you can delete the running
.bat/.cmd file since the command interpreter loads the whole file into
memory and then closes it before execution begins by design. This
behaviour dates to the era of .bat files on floppies which got removed
from the drive.
I can suggest a few nuances for robustness. We check the timestamp on
startup and download the updated copy to a .new file before doing the
rename process.
If the download attempt fails, we just skip the update attempt (for now)
and proceed as normal. The update code needs to trap all exceptions
otherwise a bad update can prevent use of the application. Not good.
If you don't take this precauation, an interrupted download attempt by
one client leaves an unrunnable partial .exe for everyone else and a
spate of support calls. Also not good :-)
We then delete .old and then rename the running .exe to .old before
renaming .new to .exe. You can use numbered extensions for .old to deal
with the fact that you can't delete the current one since someone is
still running it. This is quite common on TS servers which support lots
of clients.
I then execute the newly downloaded and renamed .exe which has code to
silently attempt to delete .old files on startup. I also pass a command
line switch to indicate that this is a downloaded respawn.
I do this to handle the case where for some reason, the timestamps are
misbehaving such that there always seems to be an update available.
Windows networking combined with Samba versions and phase of the moon.
You don't want to livelock downloading and restarting endlessly. Also
not good.
Finally, often, the .old file(s) are not deletable on the first run
since the new process commonly starts executing and hit the delete
attempt before the old process has shutdown. They're essentially racing
with each other and on dual core machines, the .new process starts
immediately. But there is no harm in attempting to delete the .old
file(s) everytime.
This is probably more detail on self-updating than anyone wanted to
know, but there you go :-)
Any logical holes that people can spot in the above approach I'd be very
glad to hear about. Many smart eyeballs makes even nasty bugs shallow!
Cheers,
Paul.
More information about the Delphi
mailing list