What if, hypothetically, the system was suspended in the middle of script execution, and the resume function was designed to reload the script from disk?
It just feels like a different hack to me.
Also - trying 20 times and pausing 500 ms seems wasteful. What are the chances that it's going to succeed a subsequent try if it fails the first try? Why not catch the error message and only retry for errors that have a plausible chance of succeeding if you retry?
DllCanUnloadNow returns an indication that a DLL can be unloaded. A DLL cannot be unloaded if any threads are executing the code. But a DLL can only change to the unloadable state by executing some code, and that code has to return after it has set the indication. Only after it returns is the DLL is actually unloadable! So a delay is needed for that thread to vacate the DLL.
https://groups.google.com/g/microsoft.public.vc.atl/c/AQvHCW... [2001]
The binary .exe program which the script is trying to delete is the one which created the script and launched it. So that means the .exe is still running at that point and cannot yet be deleted. Lauching the script indicates "I'm about to die", not "I'm already dead". The script cannot delete the .exe until the .exe terminates. Without some event to indicate that, you poll.
The script knows it can delete itself, so it tries that only once.
If a handle could be attached to the process, then the script could do a WaitForSingleObject on it; that would be the prim and proper way.
It doesn't seem worth doing; the chances are low that the process cannot terminate within 20 seconds of launching the reaper script.
As a metaphor: you find the instructions to sweep your floor cumbersome so you reprogram your neighbor's Roomba to come clean your floor. Sure, it may well go back to their house and no harm done, but it's hacky, socially unacceptable, and no matter how hard your broom is to use it's not OK.
I think the retry is necessary because if you launch "wscript cleanup.js" from the process that wants to be cleaned up, you then need to wait for the spawning process to finish executing. I agree if it fails after 20 times, you should probably spawn an alert or something letting the user know that uninstall failed. There are also so many random processes that might take a reference on the file like antivirus in Windows so just spamming retry will help wait that stuff out (this problem does not exist on Linux since Linux generally just does garbage collection which has the downside of not keeping specific paths around, just file inodes).
It can do that because, I'm guessing, the file isn't open; the run-time isn't executing instructions from that file. The file was read, the content compiled into memory, and closed.
The script is deleting its source code, not itself. What actually deletes the script itself is the garbage collector in the run-time. Once the fso.Deletefile call and the for loop are executed, they are no longer reachable and so they are garbage. If there is a way for the "var fso" and "var path" variables to go out of scope, they become garbage also.
A binary executable is mapped into memory while the process is running it. In Windows, an open file cannot be deleted.
But, even on Windows, a prog.exe could delete the prog.c source code it was compiled from, right? Same thing, sort of.