Custom Actions in PrimalScript 2018’s MSI Builder

Starting with PrimalScript 2018, version 7.4.111 you can define custom actions for your Windows Installers. A custom action is anything that can be executed from a command line. Most commonly you will probably use executable files or a PowerShell Script.

Overview: Custom Actions for Windows Installers

If you are not familiar with custom actions for Windows installers, here is a brief overview:

When installing or updating a product, Windows Installer’s main job is to copy the files of a product to the proper place. Likewise, when uninstalling, it uses information created while installing to remove files that have been previously copied to your hard drive. Any files or documents created by the user or created during normal operation of a product are not removed. While Windows Installer has some functionality for creating registry entries—chaining other Windows installers (e.g., for dependencies), or opening ports in your firewall—it has very little functionality to support PowerShell or its modules. This is where custom actions come into play. With custom actions you can install modules you need from the PowerShell Gallery or any other repository. You can create actions which will then remove these modules again during uninstall. Likewise, you can create registry entries and remove them again as needed. All the powerful functionality of Windows PowerShell is now at your disposal during installer operations.

Custom Actions Example

We will use a simple WMI Explorer generated application to illustrate these custom actions.

In addition to the application, we add two PowerShell scripts (setvalue.ps1 and removevalue.ps1) and a readme.txt:

image

 

On the installer setting dialog, we have a new page “Custom Actions.” As you may have guessed, here is where you define them. Each custom action must have a unique name. The dialog will not allow you to use the same name for more than one action.

PowerShell scripts as custom actions are executed with the following command line:

”C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe” -NoLogo -NonInteractive -InputFormat None -NoProfile –File “<yourcustomactionscript>.ps1”

That means for PowerShell scripts you only need to specify the script file itself, nothing else.
For any other type of script you will need to specify the entire command, including what script engine you want to use (e.g., WScript.exe or JScript.exe for Windows Script Host.)
If you package your custom action scripts as executable files, you need to add the .exe file and reference that rather than the script.

 

image

 

The Properties options are defined as follows:

File Place the name of the file to be executed. This file must either be installed by the MSI you are creating or pre-exist on all target machines (e.g., Notepad.exe.)
Folder Defines the current directory for the custom action. In most cases, this will be the INSTALLDIR folder, which is where your application will be installed. The drop-down combo box has a few other common Windows folder shortcuts.
Arguments Specify any command line parameters you need to pass to your custom actions. The example below illustrates how the readme.txt file included in the sample installer is passed to Notepad.exe. Please note that there is absolutely no checking on the values you enter here, as we do not know what will exist on the target machine. That is for you to check and verify in your specific environment.

 

image

 

The Execution Time options may be a little bit confusing in their terminology unless you are very familiar with Windows Installer:

Immediately Indicates that the custom action will run during normal processing time with user privileges.
When the system is being modified (deferred) Indicates that the custom action runs in-script (possibly with elevated privileges). This is the default.
During installation rollback Indicates that a custom action will run in the rollback sequence when a failure occurs during installation, usually to undo changes made by a deferred custom action.
After the system has been successfully modified (commit) Indicates that the custom action will run after successful completion of the installation script (at the end of the installation).

 

The Execution Options are defined as follows:

Run under the system account (no impersonation) Typically the installer process will make changes to the system impersonating the installing user. Check this option to make sure your custom action runs under the system account rather than the installing user.
Wait for custom action to finish Indicates that the custom action will run synchronously and the return code will not be checked.
Check return code Indicates that the custom action will run synchronously and the return code will be checked for success.

 

For any Windows Installer custom action a non-zero return value is interpreted as an error and the installation stops. If neither ‘Wait’ nor ‘Check’ is specified, the custom action will run asynchronously and execution may continue after the installer terminates.

image

 

In our sample the Setvalue.ps1 script creates a registry path ‘HKCU:\Software\SAPIEN\ShowServices\Settings” and sets a value “Version” to 17324. This script is set to be executed during install and maintenance modes. So deleting that registry entry and running the MSI in maintenance mode will restore it:

image

 

The ‘Remove Registry’ custom action will delete the entire ‘ShowServices’ node on uninstall:

image

 

When you run this installer for installing or uninstalling you will notice the flashing consoles when the custom actions involving PowerShell are active. You might ask why we did not hide these flashing consoles or make them permanent so you can see what happened. Since this is just a sample to get you familiar with the new custom actions option, we kept the actions simple. They are more or less simple one-liners. In a real-world application, these scripts will become much more involved. Since we don’t know what you will do, we left everything as basic as possible. When using PowerShell scripts, you may want to display a progress bar in the console for any lengthy processes or only stop to show results in case of an error. Likewise, you may choose to not bother the user with any errors during uninstall and just leave things in place if they cannot be removed.

Some may prefer custom actions to be silent and invisible, in which case you can use a script during development to see what happens and, as the last step, convert these scripts to an executable file with any of the silent engine options for Windows PowerShell within PrimalScript or PowerShell Studio. You should also note that using PowerShell script files will make these files subject to the PowerShell execution policy on the target computer, so do not forget to sign your script files if so required.

Keep in mind that the choice is yours what to do when, and how to handle errors and user notifications.

You can download the sample files for this post here: https://sapien.s3.amazonaws.com/Blog_Post_Files/ShowServicesSampleApplication.zip

Feedback

If you have any questions, concerns or feedback you are, as always, more than welcome to visit our support forum and post a message in the appropriate section.