Why does my program still show up in the Programs and Features folder after my uninstaller exits?

A customer reported that they were having problems with their program entry in the Programs and Features folder (formerly known as Add and Remove Programs, formerly known as Add/Remove Programs). When the user goes to the Programs and Features folder, selects their program, and clicks Uninstall, the uninstaller runs, but after the uninstaller exits, their entry remains in Programs and Features. They have to manually refresh the folder to get it to disappear. Why won't the item disappear?

The Programs and Features folder launches your uninstaller and waits for it to exit, at which point the Programs and Features folder looks to see if the uninstall entry for your program still exists in the registry. (There is no standard method for an uninstaller to report success or failure back to their caller, so this is the only technique available.) If the registry entry has been deleted, then the Programs and Features folder concludes that the program was successfully uninstalled and removes the item from view.

The trick is the "waits for it to exit" part. If your uninstaller in turn launches another program to do the real work of uninstalling, the Programs and Features folder doesn't know or care. It just waits for your uninstaller to exit. If your uninstaller exits before the uninstall is complete (because it handed off the work to some helper process), then when the uninstaller exits, the Programs and Features folder looks for the uninstall entry in the registry, finds that it's still there (because your helper is still running), and concludes that the uninstall was unsuccessful.

Sadly, as is not uncommon, the customer replied with additional information that indicated that they didn't understand the explanation.

Thanks. We logged all accesses to our uninstall key, and we found that the key is accessed by two processes: explorer.exe and msiexec.exe. The last access is from msiexec.exe. A log file has been attached for reference.

Yes, this is completely consistent with the uninstaller exiting before the helper (here: msiexec.exe) finishes its work. The Programs and Features folder (running inside explorer.exe) checks the key, finds that it's still there, and leaves the item in the view. And then msiexec.exe finishes its work and deletes the key. But by then it's too late; the Programs and Features folder already concluded that the uninstall was unsuccessful.

Bonus chatter: Why doesn't the Programs and Features folder wait until the uninstaller and all its child processes exit?

Because that doesn't work either. It is common for installers to launch child processes that it intends to outlive the installer. For example, it might end with a dialog box that says, "Congratulations, your install was successful. Do you want to run the program now?" Or it might launch some background task to create an annoying notification icon.

Anything an installer does, an uninstaller can do, because one of the options in the uninstaller might be Repair or Reinstall. If the Programs and Features folder waited for all child processes to exit, then it might end up concluding that the uninstaller never finished because some random background task is still running.

Comments (41)
  1. Mordachai says:

    I have seen many uninstallers annoyingly open a web browser on a survey "whine, whine, why did you stop loving us?!"

    Waiting for that to finish could easily be "never" since it would be the main browser process, which itself (for me) generally stays open for eternity (or something close).

  2. Jon says:

    While the add/remove programs dialog is open it could have a registry change notification set on the key that hold all the uninstallation entries.

  3. Joshua says:

    Especially because of the self-delete problem this does not seem to be well-thought-out.

    I ended up spawning my uninstaller via rundll32 so that FreeLibrary could be used. (If you think about it hard enough you'll see why this can work).

  4. Joshua Ganes says:

    Clearly this situation isn't ideal. I wonder if there were any attempts to improve the uninstall process. If so, what ideas were proposed, and why were they rejected? I would think that adding a simple way for the uninstaller to notify Windows of success would go a long way to improving this feature for the future.

  5. Mordachai says:

    I have often wondered / wished for Windows to provide comprehensive installer / uninstaller functionality.

    Some relatively simple way to leave things to the OS so that myriad companies are not rolling their own. Must be something like 95% of all software could be handled w/o the need for extra code to be written (and for those that need it, seems like a few hooks could be added to make them work as well).

    I know that install/uninstall are deceptively complex, but having "rolled my own" a few times, and worked with various vendors installer packages, it still seems to be the sort of thing that would be better handled by the OS than by 3rd parties (especially since Windows keeps changing).

    I know that Windows takes the attitude that it already provides all of the tools necessary – and on some level it does. But give me 10 programmers tasked to make an installer, and I'll give you back 10 solutions – all of them with shortcomings.

    [Then why don't those 9% of all software use MSI? That's been around as part of Windows for well over a decade, with redistributables all the way down to Windows 95! -Raymond]
  6. SimonRev says:

    @Joshua & Steve

    Windows 8 provides full installation/uninstallation services for Metro apps.  As far as for the desktop, I am sure Raymond's standard answer of "We'd need a time machine" applies.

  7. I know that there's MSI and any app is free to use it.  We use WiX, and that's addressed many of the issues that Steve mentioned.  A short, simple XML file describing what needs to be installed gets the job done.  That's not so much the issue.  (I wish Nullsoft would output MSI files… advantage of MSI is that you can easily deploy it via Active Directory, you get repair/maintenance for free, etc.)

    My big gripe is that there isn't a standard method for pushing updates to the client.  Sure, there's Microsoft/Windows Update – but that's only for MS products.  So every 3rd-party app developer is rolling their own solution.  And now my system has 10 different auto-updaters running in the background sucking up memory, instead of just 1.  Gross.

    I know they have announced that there will be a solution for Metro-style apps on Windows 8 sold in the Windows store, but there needs to be more.  The desktop itself badly needs a solution for existing apps.  Not every app will be usable with a "tablet-style" interface, but they'll still need an automatic update mechanism.

    And MSI is far from perfect.  What if your app depends on other packages?  Look at Visual Studio setup for exhibit A of a big mess.  I end up with seemingly 30 different MSI packages in my Programs and Features list after installing the Visual Studio product – they were chained together with a big fat non-MSI bootstrapper.  The MSI team badly needs to address the serviceability problems with merge modules so people can start using them again… or support nesting MSI files… or something…  Chaining together a bundle of unrelated MSI files in a proprietary, custom bootstrapper EXE and calling that a setup program isn't really a good solution in my book.

  8. Joshua says:

    [Then why don't those 9% of all software use MSI? That's been around as part of Windows for well over a decade, with redistributables all the way down to Windows 95! -Raymond]

    Because you cannot spawn an exe-wrapped MSI from inside a MSI. Fix that and backport it as far as XP (we are obligated to support our software running on XP for years to come for contractual reasons) or I'm staying away from MSI.

  9. Klimax says:


    I saw many insanities done from msi, so I suspect that your scenario can be done too.

  10. Joshua says:

    @Klimax: Let's just say that unlocking a system-wide mutex and spawning another copy of the program that created it doesn't sound like a sustainable idea.

  11. Unix programmer says:

    This is one the many reasons an exec()-like API would be useful.

  12. Klimax says:


    What the hell then are you doing exactly? (Your previous post isn't too clear and is missing some things)


    Don't know about being broken or what fundamental use case is missing. Not that I saw "desperater hoops" or something. You might want to be more specific (links welcome) and being less hostile would be nice too so your point isn't lost in low sound/noise ratio.

  13. I believe Add/Remove Programs waited for child processes in XP.

  14. Joshua says:

    @Klimax: A product I work on has this thing where it conditionally downloads installs SQL Express depending on some options chosen during install, but only if it doesn't find a database using the target instance on the machine. Window installer takes a global mutex to prevent two installs from running at the same time. You can figure out the rest from there.

  15. MSI says:

    @Joshua Isn't that the whole point of MSI Merge Module? msdn.microsoft.com/…/aa369820%28v=vs.85%29.aspx If you had taken the time to study the problem and realize what the real solution was you wouldn't have ended up with something so hacky as attempting to evade a global mutex.

    I did some research for you, and found that the Merge Modules are not produced anymore for SQL Server Express, specifically because you are required to register SQL Server Express (they want your info to sell you product I'd assume) to quote from their blog "If you distribute SQL Server Express without registering you violate the End User License Agreement."

    I would wager than conditionally downloading SQL Express as you are violates their EULA, especially if you are automating the registration portion.

  16. James says:

    Is there even a way to wait on child processes using supporting APIs if Programs and Features wanted to?  I don't know of any good way to do that other than by using Job objects, but Jobs can't be nested in shipping versions of Windows.

  17. Joshua says:

    @MSI: Wasn't true when I pulled down SQL Express.

  18. Dave says:


    I ended up spawning my uninstaller via rundll32 so that FreeLibrary could be used

    Oh, so it your app that Raymond was talking about in articles like this one blogs.msdn.com/…/10237911.aspx.

  19. Mordachai says:

    @SimonRev – I'm hopeful for Windows 8 giving a much more user-friendly interface for Metro Apps.  That world looks like it's designed better – to hold the developer's hand and help them make an app that really integrates with the OS, and other Apps, including installation and operation, far superior to anything MS has done in the past.

    However – this Metro ecology is really not appropriate for many types of desktop software, and does not help the current situation.  In fact, I'm worried (along with many others) that it will make my desktop conform to a universe that isn't of my desire for a desktop PC.  I'm all for that for a tablet PC or a phone.  But a PC?  I have my doubts…

    @Raymond – at the risk of exposing my own incompetence, my take on MSI has always been that it is horrendously complex.  It is awful, in my experience, to work with.

    Compare that to Nullsoft's installer: that is a charm to work with.

    For my 2c, I prefer the Nullsoft approach (or the NeXTStep / OS X approach) – where you simply create a manifest of a sort, fill in a few blanks, and boom, most software is installed and registered (and can be uninstalled & deregistered) by the OS with *very little* understanding on the part of the software developer (and hence very little chance they'll get it wrong).

  20. cheong00 says:

    I think this could have been fixed if the msiexec process calls something to notify installation status change at the end of each package. That'd somehow fix those 90%of the cases. (While updating the whole list can be slow, I think updating base of specific package ID should be fast)

    For those who write installer programs themselves, just make such API call available to them when finish. (Whether they're calling it or not is not important, at worse if they don't call it, the situation would have been just the same)

  21. grumpy says:

    Probably because MSI is so utterly broken. Just a thought.

    An installer engine  which fails to support the most fundamental use cases, and is ridiculously slow to boot? Yeah, I wonder why not everyone uses it. Heck, just looking at the desperate hoops various Microsoft products jump through to *try* and package working installers for their software should say it all.

  22. Ivan K says:

    Couldn't an MSI that wants to wait for an exe to exit call a function or do some custom action that process creates whatever.exe from the installed/temp files path and then waits on the process handle (with a timeout, if desired) before going on to the next operation? This would only work ok if the exe required no user input, or the install was interactive and the user was told the exe launch was a 'step' of the install wizard. [I'm obviously no expert on MSI]

  23. Joshua says:

    @Ivan K: It is my understanding that they shimmed the call to msiexec /u.

  24. Yuhong Bao says:

    @MSI: The biggest reason I think is that MSDE service packs required the application vendor to patch the original MSI package that the MSM was linked with, which was a big problem when SQL Slammer hit in 2003. Thus it was depreciated and in the next SQL Server release removed.

  25. alegr1 says:

    [Then why don't those 9% of all software use MSI? That's been around as part of Windows for well over a decade, with redistributables all the way down to Windows 95! -Raymond]

    Maybe because Microsoft decided that MSI doesn't need any authoring tools. Nope. Everybody can populate a poorly documented database, no fancy GUI tools necessary. OK, a third company has written their widely used authoring tool, so widely used that MS was forced to emulate their 16-bit installer module for x64. Or maybe because MSIEXEC is so poorly programmed that it takes the whole processor busy (busy loop waiting?) while extracting files with lightning fast speed of about 1 MB/s.

    Or maybe because sometimes *the whole MSI subsystem* decides to break so badly that it won't install or uninstall anything. Like it happened on my Win7 laptop on work.

    [The original complaint was "Why doesn't Microsoft have a unified installer?" The answer is "A unified installer for Windows has existed for over a decade." Whether that unified installer sucks is a separate issue. -Raymond]
  26. Alpha releases of Windows 8 supported AppX packages even for desktop apps.

    Raymond, why was that feature removed? MSI is without doubt one of the worst products Microsoft has ever released.

  27. InOut says:

    Use tools. Quite a few of them listed on InstallSite. I am partial to Advanced Installer myself.

  28. ender says:

    MSI is a good idea, but the execution is horrible – it's slow and fragile (though recent versions seem to break a bit less) – I ended up with MSI-based programs that couldn't be removed/repaired/reinstalled way too many times (I wasn't alone – <i>somebody</i> wrote this msizap tool that somehow fixed the problem). And then there's the (non-)progress indicator – why even bother with it, when with each install it fills up a random number of times (I remember a certain Office service pack where I counted the progress bar filling 30 times, then there was a mandatory reboot, after which the progress bar filled a further 10 times – and I'm not exaggerating).

  29. Burak KALAYCI says:

    Why wouldn't the Programs and Features folder poll the registry (assuming it is local) and refresh auto-magically?

  30. JohnL says:

    @Burak Maybe because if the uninstall really did fail then it could be doing that forever.

    MSI has many good points – but simplicity isn't one of them, and there's a lot of things it just can't do.  In many ways it's got the worst of both worlds – all the complexity but none of the power.  Maybe Chocolatey (http://chocolatey.org) will take off…

  31. Burak KALAYCI says:

    @johnL Forever is only as long as the folder is open. AFAIK explorer queries the registry all the time for various things (on XP at least). I don't see why polling at a 500ms interval would have any unwanted consequences.

    [Polling kills. -Raymond]
  32. Mordachai says:

    Isn't there a wait for object (registry key change) API already, just as there is for the file-system?  I've never needed that functionality, but I'd be surprised if it didn't already exist.

    Even if it doesn't exist, it's reasonable to implement using polling and an extra thread and a bit of storage to be able to tell when something changed…

  33. Phil W says:

    There is MSI functionality to wrap multiple MSI packages into one virtual product in Programs & Features. See MsiBeginTransaction, MsiEmbeddedUI etc. I hope nobody's asking for a feature that already exists. Also, the vast majority of the issues with installs are caused by the custom code (custom actions) that people write to get called from the install. A typical development story is to throw a bunch of configuration requirements at the people writing the install, and the result is an unreliable install and more complaints about why installs are so error prone. Configuration belongs in the app, not in the install, and it looks like Microsoft are going to enforce this with AppX.

  34. xpclient says:

    Wow look at the hatred here for MSI. I think MSI rocks. It's the most full-featured and well designed installer system.

  35. ender says:

    Oh, one more MSI gripe: the Windows Installer service removes privileges for creating symlinks from itself – this was recently a problem for CoApp, since it's pretty much designed around symlinks and Windows Installer. They ended up writing their own service which handles creating symlinks (Windows Installer has no problems spawning a service which then isn't subject to those limitations).

    @xpclient: MSI well-designed? Don't make me laugh.

  36. Phil W says:

    Well I think ender just supported my point. There's a complaint that MSI sucks because I can't run my app configuration code from the install. Roll on AppX in the hope that nobody can run their code from an install ;=)

  37. 640k says:

    If that's not a good strategy, then why does Visual Studio Pre/Post compilation steps wait for all "random background tasks" to finsih? Now you have to register a task scheduler event to contiue to compile. A little consistency please!

  38. ender says:

    @Phil W: huh? Windows Installer runs elevated, and lets you define custom actions. Making symlinks is limited to elevated users, which is why they have to be made at install time – except that for some weird reason Windows Installer service removes that privilege from itself, requiring you to do extra work (and potentially introduce a security hole to the system) to get the same effect.

  39. Killed says:

    [Polling kills. -Raymond]

    If someone could hop into his time machine and tell that to guys that wrote Autostart, Network Connection UI, WMI and Bluetooth… :(

  40. Remove the burden of msi says:

    MSI proven technology? Yeah, proven to NOT be useful. By MS!

    1. Now, when msi has existed for over a decade, most of MS' own install packages are still exes.

    2. Windows itself isn't compatible with MSI (uninstall). Case closed.

  41. Paramanand says:

    On Windows XP, I sometimes find that after the uninstall the entry for the program remains. And then I again click on the "Remove" button and a dialogs pops up saying "The program might be uninstalled, do you want to remove its entry from the installed program's list". After this I click on "Yes" button and the entry is deleted. Given the nature of the list updation (wait for the uninstaller to exit and check registry key) I think the above solution is pretty simple and not too annoying. However not all uninstall operations proceed like this and so this is not the preferred solution by many uninstallers.

Comments are closed.

Skip to main content