[wix-users] Custom bootstrapper access to engine variables

robert_yang at agilent.com robert_yang at agilent.com
Fri Aug 19 16:39:57 PDT 2016

After taking a week off and being sidetracked on other issues, I decided to try the custom BA approach to the "Uninstalling a simple patch results in repair of the whole bundle" thing.

I took the standard Wix bootstrapper application C++ source, cloned it, made some modifications so that it is now a custom bootstrapper (also commented out the calls to LoadBootstrapperBAFunctions / ParseBootrapperApplicationDataFromXml), and added some code to the OnPlanRelatedBundle to inhibit repair if uninstalling the patch.  This BA would be used solely for patch installation.  The added handler code looks like this :

              // Check requested action.
              LONGLONG llAction;
              BalGetNumericVariable(L"WixBundleAction", &llAction);

              if (llAction == BOOTSTRAPPER_ACTION_UNINSTALL)
                     * TODO: This does not work : it returns null, why ??
                     // Check for bundle we are not supposed to repair
                     LPWSTR wzBundleIdToCheck = NULL;
                     BalGetStringVariable(L"BundleNoRepair", &wzBundleIdToCheck);

                     if ((wzBundleId != NULL) && (*wzBundleId != 0) &&
                           (_wcsicmp(wzBundleId, L"{0f2b9c55-d7bc-4a60-83b2-6dcf2cb8f7f5}") == 0))
                           BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "OnPlanRelatedBundle: bundle %ls: requested state=%d", wzBundleId, *pRequestedState);

                           // If bundle requested state is repair, then inhibit the repair.
                           if (*pRequestedState == BOOTSTRAPPER_REQUEST_STATE_REPAIR)
                                  *pRequestedState = BOOTSTRAPPER_REQUEST_STATE_NONE;
                                  BalLog(BOOTSTRAPPER_LOG_LEVEL_STANDARD, "OnPlanRelatedBundle: bundle %ls: setting requested state to %d", wzBundleId, *pRequestedState);

                           }      // IF bundle requested to be repaired
                     }      // IF bundle ID matches
              }      // IF action is Uninstall

I resorted to hardcoding the package ID just for testing, to check that the concept works (which it seems to).

Note the commented out part and the TODO: I wanted to be able to set a bundle ID variable in the bundle .wxs, but this doesn't seem to work.  The corresponding bundle WXS looks like this :
(sorry, this is super crude and I just wanted to get a quick proof of concept)

    <!-- Custom bootstrapper looks for this bundle ID and inhibits its repair on uninstall -->
    <WixVariable Id="BundleNoRepair" Overridable="yes" Value="{0f2b9c55-d7bc-4a60-83b2-6dcf2cb8f7f5}" />

    <BootstrapperApplication Id='CustomBootstrapperApplication' SourceFile="SourceDir\install\patch\customba.dll">
      <Payload Name='thm.xml' Compressed='yes' SourceFile='SourceDir\install\Wix\B.08.00_Patch\Resource\HyperlinkTheme.xml' />
      <Payload Name='thm.wxl' Compressed='yes' SourceFile='SourceDir\install\Wix\B.08.00_Patch\Resource\HyperlinkTheme.wxl' />
      <Payload Name='logo.png' Compressed='yes' SourceFile='SourceDir\install\Wix\B.08.00_Patch\Resource\agt_logo.bmp' />

What is the proper way to pass such arguments to a custom bootstrapper written in C++ ? (Or did I do something dumb in retrieving the variable ?)

Thanks for any insights !

More information about the wix-users mailing list