Custom/External UI on Uninstall

Nov 25, 2015 at 9:38 AM
Is it possible to provide the same Custom/External UI on uninstall? (Uninstall triggered with Add/Remove Programs)

I've tried to change the uninstallstring which is created while Installation from the msi-Setup, but still with no luck. (see SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall[Product]\UninstallString)

I've also came across this post and it says that there is always the basic minimal UI while uninstalling by design... I've mentioned to call a custom Action while uninstalling which calls the real Setup but I think there must be a better way to do this.


Many thanks
Coordinator
Nov 26, 2015 at 3:17 AM
As far as I know you cannot change this behavior. A standard basic setup UI will always be displayed on uninstall. Even more, you may have your MSI packed with your custom embedded (not external) UI and it will also be ignored.

Canceling ARP uninstall and starting the the external setup.exe instead is what I also wanted to suggest. It's not an elegant solution at all but I see no other way.
Nov 26, 2015 at 4:04 AM
And what is the best way to achieve such behavior? I mean the cancellation of the ARP uninstall processes.
AFAIK, one should implement custom action for that, but what this action should do?

Thanks!
Nov 26, 2015 at 5:34 AM
Edited Nov 26, 2015 at 5:48 AM
Canceling ARP uninstall and starting the the external setup.exe instead is what I also wanted to suggest
Thanks Oleg, I think I'm gonna go this way... Although It seems to me to be a hack over the ARP behavior, but if there isn't any other way I think it should be fine..
one should implement custom action for that, but what this action should do?
In my understanding, this custom Action should only call the custom Setup.exe and kill itself after that.

I think you have to do the following:
  1. While installing, copy the Setup.exe with the CustomUI_into the TargetDir Directory (or any other Directory where you think this file should be copied to)
  2. On uninstall, call a custom Action which invokes the Setup.exe
  3. Make sure that the msi-Setup kills itself after calling the Setup.exe (note that It's not possible to uninstall applications paralell)
Sample Code to call the Setup.exe:
System.Diagnostics.Process.Start("[Path_To_Setup.exe]");
Nov 26, 2015 at 5:51 AM
TopplerHarley,
This is almost the solution I'm testing right now. The only difference with your idea is that I'm using InstalledFileAction to call installer with custom UI:
new InstalledFileAction("Uninstall.exe", "", blah-blah-blah)
But how can I finish the ARP setup from the installer script? Do you know if there is some proper way of doing it except explicit tskill?

Best.
Nov 26, 2015 at 8:26 AM
Edited Nov 26, 2015 at 8:28 AM
Hi vlad_ss,

I've managed to get it working. (Although it's a very hacky solution :-s)

To stop the ARP-session, I'm using a MangedAction:
new ManagedAction(
    nameof(Setup.CallPrettyUIWhileUninstall), 
    Return.check, 
    When.Before, 
    Step.InstallInitialize, 
    Condition.Installed)
Body of the action:
[CustomAction]
public static ActionResult CallPrettyUIWhileUninstall(Session session)
{
    // Call pretty setup... If it could not be located, the default 
    // uninstaller will continue to run
    // 
    // Note: Additionally the running processes are checked to determine 
    // if the current setup is already the pretty one..
    var setupPath = "[Path to your Setup.exe]"
    if (System.IO.File.Exists(setupPath) && 
        !Process.GetProcessesByName(
            Path.GetFileNameWithoutExtension(setupPath)).Any())
    {
        // --> Start pretty setup
        Process.Start(SetupParams.SetupPath);
        Environment.Exit(0);
    }

    // Either the setup could not be located or it's already running
    return ActionResult.Success;
}
Please let me know If you've found a better solution.

Best regards
Coordinator
Nov 27, 2015 at 3:12 AM
> Although It seems to me to be a hack over the ARP behavior...
Absolutely!!!
But if you have no other options and you assessed all your risks... why not?

As for the actual implementation you can also go with ManagedSetup as below. But ultimatelly it is the same as TopplerHarley suggestion.
project.Load += project_Load; 
...
static void project_Load(SetupEventArgs e)
{
    if (e.IsUninstalling && e.Session["PROPERTY_SET_BY_YOUR_UI_BUT_NOT_ARP"].IsEmpty())
    {
        Process.Start(System.IO.Path.Combine(e.InstallDir, "setup.exe");
        Environment.Exit(0);
    }
    ...
Coordinator
Nov 27, 2015 at 4:11 AM
I actually think it is a good idea to let user know that the MSI session was started as a ManagedUI or External UI. While the external UI is always provided by the user (thus Wix# has no control over it) the ManagedUI is always hosted by the WixSharp.ManagedUI class so it can always auto-inject some property to indicate it's presence.

Thus the very latest HotFix release v1.0.29.2 (available from NuGet as prerelease) has a new property SetupEventArgs.IsManagedUISession. It is nothing else but a simple MSI property evaluator:
public bool IsManagedUISession
{
    get { return Session.Property("WIXSHARP_MANAGED_UI").IsNotEmpty(); }
}
Thus the code from the previous post can be rewritten as follows:
project.Load += project_Load; 
...
static void project_Load(SetupEventArgs e)
{
    if (e.IsUninstalling && !e.IsManagedUISession)
    {
        Process.Start(System.IO.Path.Combine(e.InstallDir, "setup.exe");
        Environment.Exit(0);
    }
    ...