Pass arguments to C# DLL Custom Action in MSI

In the last post, we had a look on how to create a C# (CSharp) DLL for MSI Custom Actions, but what if you want to create something more dynamic? What if we want to pass some MSI properties to our DLL, and in our DLL we use those arguments in our code to set things up?

 

C# Code

In our DLL, we are going to use the session object and the CustomActionData property. If you had a look over the previous post, our DLL is quite simple and writes only some registry keys. For this project, I want to write in the registry the INSTALLLOCATION of my MSI. The only thing I modified in my code is this line:

 

 key.SetValue("yourkey", session.CustomActionData["INSTALLLOCATION"]);

 

At the end, the script looks like this:

The whole code is:

 

using Microsoft.Deployment.WindowsInstaller;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Win32;

namespace TestCustomAction
{
public class CustomActions
{
[CustomAction]

public static ActionResult MyMethod(Session session)
{
RegistryKey key = Registry.LocalMachine.OpenSubKey("Software", true);

key.CreateSubKey("AppName");
key = key.OpenSubKey("AppName", true);


key.CreateSubKey("AppVersion");
key = key.OpenSubKey("AppVersion", true);

key.SetValue("yourkey", session.CustomActionData["INSTALLLOCATION"]);

return ActionResult.Success;
}

}
}

 

After we added our changes in the code, build the DLL from Build > Build Solution.

MSI Setup

We are going to edit the MSI with Advanced Installer. In our project, navigate to the Custom Actions Page and add a Call function from attached native DLL custom action and configure it like in the screenshot bellow:

Ok, now that we have our DLL added as a custom action, we need to pass the MSI install location to it. In our case the APPDIR internal MSI property is the one which tells the MSI which is the install directory. To do this, in the Custom Actions Page, we need to add a Set Installer Property custom action, and configure it like in the screenshot bellow:

In the Property field of the Set Installer Property custom action you must write the name of the custom action of your DLL (that we previously created) and in our case it’s TestCustomAction.CA.DLL.

In the Value field of the Set Installer Property custom action you must write the key/pair set of value. For example, in our DLL we are searching if an argument for INSTALLLOCATION is passed, and if it is, the DLL will take it’s value. So in our case, we are going to set the value as a key/pair of INSTALLLOCATION=[APPDIR].

 

Test it

Now that we have our MSI build, when we install it and the custom actions are executed, it will write the following key in the registry:

And that is a success from our part.

 

Alternative way of passing arguments

If you don’t want to pass arguments as a key/pair value (INSTALLLOCATION=[APPDIR]), we can change the C# code to get all the arguments that are passed in the session.

With this in mind, we can create a variable like this:

string data= session["CustomActionData"];

Then, we use our data variable to write in the registry:

key.SetValue("yourkey", data);

Now all the arguments we pass in the MSI will be gathered by the DLL. One additional change we must perform in our MSI is in the Set Installer Property custom action. Instead of setting the value to INSTALLLOCATION=[APPDIR], we are only going to use [APPDIR]:

When you build and install the MSI, the result will be the same:

Passing multiple arguments

But what if you have more than one argument that you want to pass? It’s also simple. We need to set a delimiter for the arguments, and in this case i’m going to use “;”.

First, let’s go into our MSI and modify our Set Installer Property custom action like this: [APPDIR];[ProductName]. This will pass two arguments to the DLL as a single string, delimited by the “;” character.

Now, in our C# code, we need to split the string by the “;” delimiter. To do this, the following code was added:

 string data= session["CustomActionData"];
string[] tokens = data.Split(';');

Because I know only two arguments are passed, I am going to use the following code:

key.SetValue("yourkey", tokens[0]);
key.SetValue("yourkey2", tokens[1]);

The position 0 will be for the [APPDIR] and position 1 will be for [ProductName].

In the end, when we build and install our MSI, two registry keys will now be created with the MSI Properties that we passed to our C# Custom Action:

Sharing is caring!

Leave a comment

Your email address will not be published. Required fields are marked *

12 − five =