I was just doing some browsing today, and I ran across an article in the 1996 Microsoft Systems Journal Archives, basically the question asked was:
In order for us to get the "Designed for Windows® 95" logo, we must supply an application that uninstalls our software from the user's machine. We have developed an application called UNSETUP.EXE. But how can we make UNSETUP.EXE delete itself?
Which is a fair enough question back then (remember, there was no such thing as Windows Installer!) The problem is the answer that was given is just horrendous! Basically, the author went through various attempts at trying to delete the “UNSETUP.EXE” program while it was still running.
I won’t go through all of them, but at one point, he was calling FreeLibrary on the executable’s HINSTANCE handle in an endless loop, to see if he could force it to close. The reason is pure brilliance: you see, calling FreeLibrary on the executable’s HINSTANCE actually worked in Windows 95 (he tried it already) – it cause the module to be unloaded, but as soon as that happened, the program crashed. Well, he figured out that he could just inject the code from the module directly into the process’s address-space and then unload it. But it didn’t work on Windows NT because Windows NT didn’t let you call FreeLibrary on the main executable (or it just kept returning TRUE). So he figured maybe Windows NT just sets the reference count really high, and by calling FreeLibrary in a loop, it might cause the reference count to go down to zero eventually.
Luckily it didn’t work and he had to come up with a different method.
He eventually came up with the idea of spawning off a batch file which simply deleted the UNSETUP.EXE and the deleted itself (batch files can do that). This worked, but it only worked because of one of the most annoying features in ever - that is, if you try to delete a locked file, Windows will wait a couple of seconds and try again. So that’s why if you try to delete a file in explorer that’s locked, it takes a couple of seconds for the error message to come up. It’s only a couple of seconds, but by god it’s the most annoying couple of seconds in my day!
And the reason that “feature” is there is exactly because of this kind of hack! People would try to delete files from a scripting language, and they never bother to include retry logic. So the behaviour they see is that “I try to delete it from a batch file and it doesn’t work, but if I delete it from explorer once the batch file exits, then it works – batch files are broken!”
So the behaviour was made into what we see today. Of course, what should have happened is that explorer should have given an error straight away, and the batch files should have tried again – different interface, different behaviour. I have Vista installed, but I can’t be bothered trying to figure out if it’s been “fixed”... I hope so :)
Anyway, to Raymond, I just want to say – I feel your pain! I can’t imagine how hard it must be trying to improve Windows in the face of this kind of “advice.” Mind you, I also think Microsoft would be doing the software-development world a big, big favour if they took these crappy article off the web.
By the way, how would I have done it? Well, I would have gone with his original idea of using MoveFileEx. But I guess nowadays having a few files around waiting to be deleted on the next reboot isn’t as big a problem as it was back when hard drives were only 50MB big. (Also, I would have changed the behaviour slightly: I would copy the UNSETUP.EXE to the user’s temporary folder first – that way the UNSETUP.EXE in the temp folder can delete the whole hierarchy, and if the user cleaned up the temp folder before the reboot anyway, then so much the better).
Now the problem with hindsight is that it’s 20-20 – today the “proper” solution is almost obvious. Back then it might not have been. And I’m sure if the original author were to come back to that article today, he’d be just as embarrassed as I would be to read it.