7

I need to allow a user to specify whether the installer should remove or retain a registry key during uninstallation. Here is what I do. I have a RemoveRegistryKey component with a Condition element that looks like this:

<Component
    Id="ID"
    Guid="GUID"
    KeyPath="yes" >

    <Condition></Condition>

    <RemoveRegistryKey
        Root="HKLM"
        Key="Software\PATH_TO_KEY" 
        Action="removeOnUninstall"/>
</Component>

This seems to work as expected. If I hard code the Condition element to 0, the registry key stays, if I set it to 1, the registry key gets removed. (There is a different component that creates this registry key, but I set its ForceDeleteOnUninstall attribute to no.)

Now, I need to control this condition via user input during uninstallation. I have a CA in C# that looks like this:

[CustomAction]
public static ActionResult AskUser(Session session)
{
    MessageResult result = session.Message
    (
        InstallMessage.User +
            (int)MessageBoxIcon.Information +
            (int)MessageBoxButtons.YesNo,
            new Record { FormatString = String.Format("Delete registry key?") }
    );

    if (result == MessageResult.Yes)
        session["DELETEREGKEY"] = "1";

    return ActionResult.Success;
}

I schedule CA execution using this code:

<CustomAction Id="AskUserCA" BinaryKey="CA_Dll" DllEntry="AskUser" Execute="immediate" />

<InstallExecuteSequence>
    <Custom Action="AskUserCA" Before="InstallValidate">(REMOVE="ALL") AND (NOT UPGRADINGPRODUCTCODE)</Custom>
</InstallExecuteSequence>

And I set the Condition element of the RemoveRegistryKey component as:

<Condition>DELETEREGKEY="1"</Condition>

I also tried DELETEREGKEY=1 and DELETEREGKEY, but even though I get the prompt from the CA (it appears after the uninstall confirmation dialog box) and I can see in the log file (when I use logging) that DELETEREGKEY is set to 1, regardless of response (Yes or No), the registry key is never deleted. I tried scheduling the CA before/after other events, but nothing seems to help.

Why does this condition seem to always evaluate to false? Is there a way to make it work?

Also, is there a better alternative? I was thinking about modifying the uninstall dialog to add a check box prompting user to delete the registry key, but I'm not sure how to do this. I know how to make changes -- modify existing dialogs or add new ones -- to the install sequence (I'm using a modified WixUI_InstallDir sequence), but I can't figure out how to do it on uninstall.

Any ideas?

Alek Davis
  • 10,628
  • 2
  • 41
  • 53
  • Hi, can you tell me what kind of information you are storing at hklm, please. I like to understand why this computer wide information should stay. – coding Bott Oct 08 '13 at 07:40
  • Say, you have an encrypted database connection string. Or, encryption key. Or some privileged user credentials. or some other sensitive data. – Alek Davis Oct 08 '13 at 16:59
  • Some thing like a connection to a local network? It doesn't sound for me that is a custom user setting. When you are talking about many computers you should think about sharing the settings to all computers by using active directory and group policies. This setting, will it enter in setup process? – coding Bott Oct 09 '13 at 08:05
  • No, not "like a connection to a local network" (not even sure what it means). It's not a custom user setting. It's an application setting (think of enterprise app). I'm not talking about many computers on network; just specific app servers that run some sort of enterprise service. No, this setting is not part of setup. It's a configuration step, that can be invoked at any time (e.g. maybe an application needs to point to a disaster recovery database, or use a different encryption key, or use different user credentials to call an external web service). – Alek Davis Oct 09 '13 at 17:03
  • When you have a global setting, which is not part of the setup, why should it handled by uninstall? i think that should not part of the setup at all. That software which creates stuff is responsible for removing it. I know, is a little bit difficult, because app isn't run while/before removing. When you are now say, but there will be garbage left on the pc - you are right. – coding Bott Oct 14 '13 at 07:49
  • Because if uninstall does not handle it, then who will? Let's assume the app itself can clean up the settings, but do you think users will remember to do this before uninstalling the app? No, they won't. And it's not just garbage, it's garbage with sensitive data. You do not want to keep it around unless the data are used. – Alek Davis Oct 14 '13 at 16:41
  • Btw, this is a common uninstall pattern. I just uninstalled Chrome from a test system, and it asked me if I wanted to remove all data (like temp file, cookies, etc) and if I wanted change default browser to IE. Neither of these are installed by setup, but Chrome is responsible enough for cleaning after itself. As any app should be. – Alek Davis Oct 15 '13 at 01:54
  • I'm still thinking about your problem. My current idea is to use a custom UI in a chainer. that is showing the question and contains that code for the settings. but doing this needs to suppress the msi uninstall with arp_ properties and creating an uninstall entry which links to the chainer. – coding Bott Oct 28 '13 at 09:59
  • Right, this seems like a cleaner alternative (i.e. turn the ARPSYSTEMCOMPONENT on and manually populate ARP with the uninstall shortcut that would launch MSI on uninstall in full UI mode). But this would pose a few more challenges, like having to fix the WiX UI sequence that does not really handle uninstalls well, then all issues related to patching, etc. So it's a good workaround, but it poses a few challenges of its own. – Alek Davis Oct 28 '13 at 16:45
  • I checked some uninstall strings, created by msi files. setups which have a special uninstall ui, call msiexec /i{guid} which "installs" the product. that msiexec /x{guid} looks like a silent uninstall. But i still prefer a chainer, which contains a module for your special settings and their handling. – coding Bott Oct 29 '13 at 10:33
  • The deal is that MSI would ignore the uninstall strings that appear under the ARP registry key, unless you set ARPSYSTEMCOMPONENT to true (in which case, you'll be in charge of all ARP entries). As I said, it's an option, and I suspect this is what other apps (like Chrome) do to launch uninstaller in the UI mode. Not a terribly bad option, if you understand the caveats. I'm not sure I understand what you mean by a chainer containing a module for my specific settings and handling. – Alek Davis Oct 29 '13 at 18:35
  • Chainer: Take a look at the new MS Office installer. They starting a own UI made with c#/c++. This UI installs lots of single MSI's containing different components. When i'm talking about your app, i think you have two Modules. Modules one is the product itself (msi). The second Modules is your custom code (must not be a msi) which is for handling your settings and their UI. The chainer simply calls/installs/uninstalls the modules in a row. Of curse that chainer must be found in those uninstall registry keys. Yes, you are right, there are lot's of caveats, but you get single responsible's. – coding Bott Oct 30 '13 at 11:16
  • I see, but this sounds a bit complex for a simple task of conditional deletion of a registry key (or whatever app settings we may want to clean up on uninstall). – Alek Davis Oct 30 '13 at 16:21

3 Answers3

5

Normally you schedule dialog's in the UI-Sequence and not in Execute Sequence. When you are not doing this, you can't have a silent (un)-install.

I think your CustomAction (CA) is run to late and the script which will executed is already created. DELETEREGKEY in this case is unset and evaluates to false - result Key stays.

Try to move your CA to UI-Sequence, please.

coding Bott
  • 4,287
  • 1
  • 27
  • 44
  • I have tried scheduling the CA in the UI sequence (tried a few events), but it did not seem to have helped. I'll give it another try. Thank you for the silent uninstall tip. – Alek Davis Oct 01 '13 at 15:30
  • Hmmm, tried scheduling it before and after CostInitialize and ExecuteAction in the ExecuteUISequence and I don't see the pop-up at all. Probably doing something wrong. Will keep digging. – Alek Davis Oct 02 '13 at 05:47
  • If you have problems with the CA, try to implement the dialog in WIX. Simple add a other wizard page. Best practice is always to avoid CA's. – coding Bott Oct 02 '13 at 09:22
  • I don't really have a problem with CA, per se, just with scheduling CA. I kind of made it work by adding code to CA to delete the key. I can check the mode and suppress it for silent execution (I think), but I still don't like this approach. Would rather have it done via a dialog, as you suggested. I will post another question because I can't figure out how to add or update a dialog during the uninstall sequence. – Alek Davis Oct 02 '13 at 19:44
  • According to this answer uninstall runs in silent mode, so UI sequence is bypassed, which explains why my CA is not invoked from the UI sequence: http://stackoverflow.com/a/19146375/52545 – Alek Davis Oct 03 '13 at 03:03
  • Yes, but this is by design - silent = really no ui = no ui sequence required – coding Bott Oct 04 '13 at 07:56
  • Right, but then the suggestion to move CA execution to the UI sequence would not make much sense, since there is no way to control how the user would initiate uninstallation. I suspect majority of users don't even realize that uninstall from ARP runs in silent mode (many would not even realize that there is such thing as silent mode). So it looks like there is no good solution for this problem. – Alek Davis Oct 04 '13 at 18:43
  • but you still should keep that design - never open a ui when no ui should opened. think in domain environment, where software is installed/uninstalled via gpo. you are going to break that function. – coding Bott Oct 07 '13 at 13:13
  • Right, if there is higher chance of the software deployment via GPO, totally agree. But otherwise, I'm not so sure. And what I mean here is that few users understand how this works. I have been working with installers/wix/msi for a long time (not my primary job, though), and the behavior of ARP was a complete revelation for me. So for majority, the intended behavior may seem like the problem of software (installer) more than the original design of Windows Installer. – Alek Davis Oct 07 '13 at 16:47
  • Another thing that puzzles me is that even though the uninstaller runs in silent mode, user still sees UI. First, there is is an install confirmation prompt. It's not part of product MSI, but from user's perspective, it's part of the uninstall process. Then, if uninstaller modifies system settings, there is a UAC prompt. There may be completion dialog. So, when we say that when uninstaller runs from ARP in silent mode, it's not really 100% silent. Just another Windows Installer idiosyncrasy. – Alek Davis Oct 08 '13 at 17:06
1

For items such as user data and other settings, I have handled it in the past by leaving the data on the machine during uninstall. During installation, you can check for such data and if it exists, prompt the user to remove\overwrite that data.

BryanJ
  • 8,485
  • 1
  • 42
  • 61
  • This would work in case user plans to reinstall software, but it's not a good option when software is removed for good, and especially when settings contain some sensitive data that under normal circumstances you would not want to keep around (e.g. if it's a server app that contains encrypted connection strings, password, or something else, that you would not want to retain). – Alek Davis Oct 03 '13 at 18:02
  • In that case, if you were just doing an uninstall, couldn't you remove it forever? However if you detect that you are doing an upgrade, then you can keep it or prompt the user on what to do? – BryanJ Oct 03 '13 at 18:23
  • Because, I don't know if the user is uninstalling for good (in which case clean up would be appropriate) or temporarily (say, user wants to run a clean install, or maybe install a previous version) and wants to keep configuration settings for future use. I don't mean major upgrade (this would be easy), but there are cases, when you need to do complete uninstall, and then install from scratch (e.g. to install a previous version). – Alek Davis Oct 03 '13 at 19:47
0

I'll summarize my own findings here.

It looks like setting a property in the Execute Sequence is too late for it to take effect when evaluating conditions. But moving the CA to the UI Sequence is not a good option either because by default uninstalls run in silent mode bypassing UI. There is a way to tweak custom uninstall shortcut and the Add/Remove Programs (ARP) entry to run uninstaller in the full UI mode, but it poses its own hassles, the least of which is having to manually populate ARP registry entries.

The approach I took was to simply delete the registry key programmatically in the same CA invoked during Execute Sequence (so I do not need the RemoveRegistryKey component). To allow silent uninstalls, I also added command-line options to specify whether the registry key should be deleted and whether to show prompt (if the delete key switch is not provided). And by default I keep the registry key. Not very elegant, but seems to do the job.

With respect to suggestions on modifying uninstall dialogs, see WiX 3.7: How to add or update a dialog during uninstall?

Community
  • 1
  • 1
Alek Davis
  • 10,628
  • 2
  • 41
  • 53