How to integrate and debug custom actions

The following article uses options that are available starting
with the Enterprise edition and project
type.

Although Advanced Installer comes with a predefined list of custom
actions, in many cases you need to create your own custom action
to implement a scenario, to either complete the installation or prepare
the application for the first launch.

Tools required

In order to create a custom action in C# the WiX
Toolset is required to be installed on the developer machine.
Once downloaded and installed, the toolset will add all necessary
modules enabling you to create C# custom actions from Microsoft
Visual Studio.

By default, the new project will generate a simple custom
action that will write some text in the installer log. Let's
add a simple MessageBox which will be
displayed when the custom action will be executed. So, your custom
action code should look like this:

1.1 Generate the custom action file which will be used in
Advanced Installer.

From the Menu bar select the “Build > Build
Solution” option.

This will generate two DLL files:
CustomAction1.dll and
CustomAction1.CA.dll

The CustomAction1.CA.dll file is the
one that holds the C# custom action which will be used in
Advanced Installer.

2. Integrate the C# custom action in Advanced Installer

If Advanced Installer is not currently running, launch it by
double-clicking a desktop icon or selecting it from the “Start” menu.
When the application starts, you will see a dialog where you can
choose the type of the project you want to create.

2.1 Add custom action with sequence

Use the to add the custom action with
sequence. When prompted, select the CustomActionSample.CA.dll
file.

The custom action is placed in a default location,
appropriate for this type of custom action. Let's move this custom
action, using a drag and drop operation after the
SearchesStandard Action, as bellow:

Build and Run

Click on the [ Build ] toolbar button
and a “Build Project” dialog will appear showing
you the build evolution.

Once the build is complete,
click on the [ Run ] toolbar button.

The custom action will be executed right away the
installation package is launched.

2.2 Add custom action without sequence, using a published event as
trigger

Use the to add the custom action
without sequence. When prompted, select the
CustomActionSample.CA.dll file.

As you can see, the custom action is nowhere added, either
in the Install Execution Stage or Wizard Dialogs
Stage. If you will Run your installation package you
can see that the custom action will not be executed. Without any
event as trigger, the custom action will never be executed. In order
to execute this custom action, it needs to be added as a published control
event.

Let's supose we want to execute this custom action when the
[ Next ] control from the
FolderDlg.

Go to the Dialog Editor page. Select the button
that will trigger the execution of the custom action.

Argument = Select the name of the custom action that you
created earlier, in our case
CustomActionSample.CA.dll.

Condition = Leave this field unchanged if you don't want to
condition the execution of this control event.

If you will Run your installation package you
can see that the custom action will be executed when the
[ Next ] from the FolderDlg will be
pressed.

All the custom actions which are added as published
events are running as immediate custom actions.

3. Setting execution time for custom actions

After you added the custom action, you can set the execution
time from its properties.

3.1 Immediately custom action

The immediately - custom action will be
executed immediately upon encountering it in a action
sequence.

The characteristics of a immediate custom action are:

The immediate custom action should not modify the target
system because they cannot be rolled back.

It has access to the installation database.

The only changes that should be made are the ones that
influence the installation process, e.g. set and verify
properties.

A custom action set as immediate can only run in the context
of the user initiating the installation. For example, if your
custom action require administrator rights, it cannot be scheduled
as an immediate custom action.

The custom action without sequence can be only set as immediate
actions.

3.2 Deferred custom action

The deferred actions can run only during the
installation script execution. So, a custom action deferred is not
executed imediately upon encountering, instead are sheduled to run
later during the execution script.

The characteristics of a deferred custom action
are:

The deferred custom action can be only scheduled
between InstallInitialize and
InstallFinalizestandard actions.

These cannot have access the installer's public properties.
However, you can pass information process through the
CustomActionData property.

These custom action can run in:

Context of the user
initiating the installation

Elevated rights using the system context

The custom actions that should run with elevated rights must
be of deferred in system context. For this, you can enable the
Run under the LocalSystem account with full privileges
(no impersonation) option from the Exection
Options pane.

Best practice: Each deferred action should have a
rollback action so that the changes it makes can be undone if the
setup fails or is canceled.

3.3 Rollback custom action

These actions are performed during the installation
rollback and its purpose is to reverse a custom action that has made
changes to the system, e.g. a deferred custom action. As you
noticed, a rollback custom action must always precede the deferred
custom action it rolls back in the action sequence. A
rollback custom action should also handle the case where the
deferred custom action is interrupted in the middle of execution.
For example, if the user were to press the [ Cancel ]
button while the custom action was executing.

3.4 Commit custom action

The commit actions are the opposite of the
rollback actions. The commit script is executed after the
InstallFinalize standard action when everything ended
successfully. Its purpose is to delete the backup files created by
the rollback script. Commit custom actions are the first
actions to run in the rollback script. If a commit custom action
fails, the installer initiates rollback.

4. Retrieving and setting properties

Using DTF C# approach, getting and setting the value for a
property is very easy.

5. Pass installer properties in deferred custom action

Deferred custom actions can receive information about the
installation process, mostly only embedded in the
CustomActionData property.

Let's change the previos code of the custom action and try
to access a property during the installation process. Supposing that
we want to copy the installation log into the "C:\"
drive.

We need to check the Enable verbose logging
option from Install
Parameters page. By enabling this option, a log file will be
generated each time the install package runs. Windows Installer will
automatically set the MsiLogFileLocation property to the
path where the log file will be generated.

Once we have the log file location, you can move it to the
desired location. Since we want to copy the log file on
C:\ drive, we need adminstrator right. So, the custom
action needs to run as deferred and with no impersonation.
Add the Call function from attached .DLL predefined
custom action with sequence after the Add
Resources action group. Make sure this custom action is set
as deferred and the Run under the LocalSystem
account with full priviledges (no impersonation) option is
enabled, since we copy the log on a per-machine location we need full
administrator rights.

As told before, the deferred custom action do not have access
to installer properties. We send the log file location through action
data field.

A sample code which can handle the copy log file location is
the following:

5.1 Adding the custom action rollback functionality

Since it is a best practice that a deferred action have
its rollback action, we will add this functionality in our example
too. Our deferred custom action copy the log file on the C:\ drive.
Assuming the user cancel the installation, after the deferred action
is executed, we need a rollback action which reverse the changes to
the system. In our particular case, the log file needs to be
deteleted from the C:\ drive.

In the code samples you might see a lot of message boxes. These
are simply added for debugging purposes.

6. Creating a single DLL for both deferred and rollback
actions

There is no need to create each time a .DLL for each
function. You can easily have a single .DLL with multiple functions
which will be called accordingly. Considering the above
example you should be able to use the following code for a single .DLL
and have both functionality:

Using the above code, we simulate that the deferred action
fails to execute in order to start the rollback sequence so the
rollback action get executed. This is done by the return
ActionResult.UserExit; statement from the deferred action.
In this moment, the rollback sequence is triggered and the rollback
action should executed. Before the rollback action get executed, a
simple message box has been added so you can search on the C:\ drive
and make sure the log is there. Click on the [ OK ]
button and the rollback action will be executed so the log file will
be deleted.

7. Configuring the deferred and rollback function in Advanced Installer