4

I have a custom action that adds/removes a certificate from the Trusted Root Certificates via the Windows Installer. I achieve this by using a CustomAction

It's possible that the user may not have permissions to add the certificate to TrustedRoots, or they may select "Cancel", how do I roll back the previous actions, and tell the installer that I've cancelled the process?

As it stands now the Windows Installer is always reporting a success response even if it fails.

makerofthings7
  • 60,103
  • 53
  • 215
  • 448
  • I'm interested in seeing how to Add/Remove a Certificate in the Installer, if you don't mind. –  Aug 30 '11 at 18:37
  • 1
    @jp2code I will publish to http://xbapcertsetup.codeplex.com as soon as the system permits me to log in (Is codeplex having issues today?) – makerofthings7 Aug 30 '11 at 18:59

3 Answers3

6

You should set up your custom action to the a function with return type of ActionResult that way you can return the failure type if the cancel happens or another exception.

using Microsoft.Deployment.WindowsInstaller;
namespace CustomAction1
{
    public class CustomActions
    {
        [CustomAction]
        public static ActionResult ActionName(Session session)
        {
            try
            {
                session.Log("Custom Action beginning");

                // Do Stuff...
                if (cancel)
                {
                    session.Log("Custom Action cancelled");
                    return ActionResult.Failure;
                }

                session.Log("Custom Action completed successfully");
                return ActionResult.Success;
            }
            catch (SecurityException ex)
            {
                session.Log("Custom Action failed with following exception: " + ex.Message);
                return ActionResult.Failure;
            }
         }
    }
}

NOTE: This is a WIX compatible custom action. I find WIX to allow for more control over the MSI creation.

makerofthings7
  • 60,103
  • 53
  • 215
  • 448
Scott Boettger
  • 3,657
  • 2
  • 33
  • 44
  • -1 .. I don't think this applies to a Windows Setup project that produces MSIs. I am not using MVC, nor am I using any technology related to the web. Am I misunderstanding? – makerofthings7 Aug 30 '11 at 19:00
  • @makerofthings7: We use this for our Wix created MSI installers. It is not limited to MVC or web related technology. It does however, require wix to be installed: http://www.advancedinstaller.com/user-guide/qa-c-sharp-ca.html – Jason Down Aug 30 '11 at 19:16
  • 3
    @makerofthings7: This is a wix compatible custom action. Didn't see a specific mention in your question for a Windows Setup project. – Scott Boettger Aug 30 '11 at 19:21
  • Thanks, I tagged the question as Windows Installer but didn't specify in the text. I removed the -1 :) – makerofthings7 Aug 31 '11 at 14:27
3

Try to throw an InstallException. In this case installer will detect thomething wrong with the installation and rollback actions.

   public override void Commit(IDictionary savedState)
   {
      base.Commit(savedState);
      Console.WriteLine("Commit ...");
      // Throw an error if a particular file doesn't exist.
      if(!File.Exists("FileDoesNotExist.txt"))
         throw new InstallException();
      // Perform the final installation if the file exists.
   }
makerofthings7
  • 60,103
  • 53
  • 215
  • 448
Samich
  • 29,157
  • 6
  • 68
  • 77
  • Where should I throw this exception? (in which override?) Should I call the `Base.SomeAction()` before or after my custom code? – makerofthings7 Aug 30 '11 at 18:14
  • I'm not sure in your code, but probably where you validating the permissions (if you have such part in your custom code) or where you catching exception after failig of adding the certificate. As described [here](http://msdn.microsoft.com/en-us/library/system.configuration.install.installexception.aspx) this exception can be thrown on any overriden event. – Samich Aug 30 '11 at 18:31
  • That is perfect. Can you tell me what is called when a InstallException is thrown? Is the application "uninstalled" or must I have a cleanup function? – makerofthings7 Aug 30 '11 at 18:34
  • Throwing this exception will intitialize the rollback action. If you need to clean up something - override Rollback event and do the staf :) – Samich Aug 30 '11 at 18:57
  • An exception will be handled as a failure. It does trigger a rollback, but the user will think a fatal error has occured. – Cosmin Aug 30 '11 at 19:06
  • @Cosmin or Sanmich Where do I place my recovery code? What override? – makerofthings7 Aug 30 '11 at 19:09
  • You can put custom recovery code to the rollback action. It runs in case of InstallException (just checked). There are 2 thing: first you will have error notification dialog (you can describe the error in your exception message), second you need to add your custom action not only under **Install** node but also under **Rollback** node if you want to handle rollback action. – Samich Aug 30 '11 at 19:53
2

This can be done only from win32 DLL or VBScript custom actions by returning 1602. If you are using an EXE or an installer class action, any non-zero return value will be treated as a failure.

Cosmin
  • 21,216
  • 5
  • 45
  • 60
  • I'm looking everywhere for sample code. What do I override to run my custom code? Within the override, do I call `BaseObject.OverrideAction()` before or after my code? – makerofthings7 Aug 30 '11 at 18:16
  • Overrides are used by installer class actions. You need a win32 DLL or VBScript custom action. You can find a C++ DLL custom action tutorial here: http://www.codeproject.com/KB/install/msicustomaction.aspx – Cosmin Aug 30 '11 at 18:19
  • 1
    I'm a .NET developer following the scattered MSFT documentation for my breed of developer. I find it hard to believe that win32 or VB script is the *only* way... I'm interested in the C# way – makerofthings7 Aug 30 '11 at 18:29