The idiomatic way write an uninstaller 1. Clean up whatever you can in the uninstaller. If you're a decent human being this includes the registry, appdata, temp, and a toggle to delete wherever your app spews its config. The only thing left should be the uninstaller .exe and the directories leading up to it, since Windows doesn't allow you to unlink a exe/dll that's loaded in memory. Your uninstaller should be static…
That is pretty much the suggested solution at the end of the article. There, the author also removes the temporary script. The solution really isn't that hard, it might just feel a bit "dirty" (using a scripting language to do some work). But all that "stack smashing butt clenching fuckery" surely is much worse and less stable, so I'm not sure why one would even go that way...
Any sufficiently advanced uninstaller is indistinguishable from malware
201–210 of 556 posts
Re: Any sufficiently advanced uninstaller is indistinguishable from malware
#202Earlier quoted context omitted.
I don't think any major desktop OS handles this well. I suspect the final form for software installation is probably where iOS and Android are going in the EU, where there's a single means of installing software to the device so that everything can be sandboxed properly, but the acquisition/update process can be pointed to a URL/Store that the user has pre-approved. macOS comes pretty close to what I'd ideally want i…
> macOS comes pretty close to what I'd ideally want in an OS with regards to installation - independent packages that are certified/notarised, but I'd like to see the OS allow for user-specified authorities beyond just Apple. It's easy to run unsigned binaries/app packages on macOS: right click on the .app, hold down Option, then click Open and confirm the warning.
Re: Any sufficiently advanced uninstaller is indistinguishable from malware
#203Earlier quoted context omitted.
> You don't? Those are either free space, or held by handle by a running process, so you just leave them be and assume they will be released sooner or later. Well that's what I was getting at, it would suck to not be able to move around file blocks just because a process is using the file. That "sooner or later" might well be "until the next reboot". The current strategy makes it possible to live-shrink and live-defr…
I'm yet to want to defrag my computer and worrying about still open deleted files. I face builds failing because I have a terminal open in a build output directory or a textfile in an editor open is far more often, and annoys me more. (or being unable to replace a running service binary of a service being developed/tested, needing to stop the service, replace it, and start again. Or failing log rotations because a lo…
> Also see my link for a solution on unix, where you can indeed fix this problem
Looping through every FD of every process just to find ones that reside in your volume of interest is... a hack. From the user's perspective, sure, it might work when you don't have something better. From the vendor's perspective, it's not the kind of solution you design for & tell people to use.
In fact, I think that "solution" is buggy. Every time you open a an object that doesn't belong to you, you extend its lifetime. I think that can break stuff. Like imagine you open a socket in some server, then the server closes it. Then that server (or another one) starts up again and tries to bind to the same port. But you're still holding it open, so now it can't do that, and it errors out.
> or simply kill the process holding the file.
That process might be a long-running process you want to keep running, or a system process. At that point you might as well not support live volume shrinking or defrags, and just tell people to reboot.
> Also the original post is about Windows installers... don't get me started on the topic (or windows services), please.
This seems pretty irrelevant to the point? It's not like they would design the kernel to say "we'll let you do this if you promise you're an installer".
> I face builds failing because I have a terminal open in a build output directory or a textfile in an editor open is far more often [...]
Yes, I agree it's frustrating. But have you considered the UX issues here? The user has C:\blah\foo.txt open, and you delete C:\blah\. The user saves foo.txt happily, then reopens it and... their data is gone? You: "Yeah, because I deleted it." User: "Wait but I was still using it??!"
Re: Any sufficiently advanced uninstaller is indistinguishable from malware
#204And today I learned that Windows supports running Javascript as shell script. huh
My concern is more than Raymond Chen suggest that using it is still the recommended way. So much malware came through WScript.
Re: Any sufficiently advanced uninstaller is indistinguishable from malware
#205Earlier quoted context omitted.
> Any open file Any file that was opened without specifying FILE_SHARE_DELETE in the call to CreateFile[1] (the Win32 equivalent of open(2)). Unfortunately, most language runtimes that wrap CreateFile tend not to pass that flag. [1] https://learn.microsoft.com/en-us/windows/win32/api/fileapi/...
Can a running executable start with this flag, so that its file can be removed?
Re: Any sufficiently advanced uninstaller is indistinguishable from malware
#206Installing / uninstalling / updating software should be a service provided by the OS. Letting vendors do it themselves just gives them an opportunity to mess it up, and they frequently do.
This makes me think of the recent changes to pip on Arch Linux that recommend installing modules with pacman. Pacman is ok, but I recently destroyed the Ruby installation on a computer while trying to use Vagrant and other Ruby packages. I still haven't figured out how to fix it. Lesson learned, stick to AUR and pacman repo.
For per-project dependencies, Poetry is pretty good, although there are other options too.
For Ruby, I think Bundler is the venv/Poetry counterpart. Not sure what you could use for installing global tools though.
Re: Any sufficiently advanced uninstaller is indistinguishable from malware
#207Earlier quoted context omitted.
> You can put the batch script in %TEMP% and hope something will clean it up, or if you're feeling extra nice you can set up an action to get it cleaned up at next boot. If you can set an action to get something deleted at next boot why not use that to delete your uninstaller itself, rather than adding an extra layer of indirection?
As far as I remember the thing you use to delete the file on next boot does not run arbitrary code, but is a special "rename-like" action that you can't use to recursively delete the folder of your program. edit: https://learn.microsoft.com/en-us/windows/win32/api/winbase/... It's the MOVEFILE_DELAY_UNTIL_REBOOT flag. Honestly maybe you can call MoveFileA on the entire directory tree you want to delete starting from…
Re: Any sufficiently advanced uninstaller is indistinguishable from malware
#208Earlier quoted context omitted.
That’s kinda like asking “why does Linux rely on `curl | sudo bash`” It doesn’t rely on it. It’s just something that’s possible.
So there's a way to have Windows uninstall a program that doesn't offer an uninstaller? Where do I look in the OS for the manifest of all installed files from an installer? Thanks, I'm mostly a Linux user and I've sorely missed a `dpkg -L` on MS Windows for ages.
Re: Any sufficiently advanced uninstaller is indistinguishable from malware
#209I mean can you write a simulation of an uninstaller to create havoc on target's system and still remain "the good guy, the OS is at fault" type of situation when you write a malware?
Re: Any sufficiently advanced uninstaller is indistinguishable from malware
#210The idiomatic way write an uninstaller 1. Clean up whatever you can in the uninstaller. If you're a decent human being this includes the registry, appdata, temp, and a toggle to delete wherever your app spews its config. The only thing left should be the uninstaller .exe and the directories leading up to it, since Windows doesn't allow you to unlink a exe/dll that's loaded in memory. Your uninstaller should be static…
> You can put the batch script in %TEMP% and hope something will clean it up, or if you're feeling extra nice you can set up an action to get it cleaned up at next boot. If you can set an action to get something deleted at next boot why not use that to delete your uninstaller itself, rather than adding an extra layer of indirection?