Recently, Microsoft has announced the VBScript deprecation.
Although most Windows admins are just fine with this, as PowerShell is even a more powerful and capable tool, packagers who used VBScript type custom actions took a hit.
VBScript was a really capable language, especially when it comes to MSI installers due to its' Session object.
The Session object is really powerful, as it has lots of methods and properties that directly work with MSI components (e.g. actions, features, etc.).
Since its' deprecation, many customers have asked me if it's possible to achieve the same in any other language (such as PowerShell and .NET).
While PowerShell can do pretty much all VBScript can and more, in terms of Windows Administration, when it comes to its' Windows Installer support, PowerShell really lacks it.
Recently, we have added support for .NET Custom Actions (both Core and Framework). This will prove really useful as, after many tries to reproduce VBScript behavior in another language, I have finally managed to do so from a .NET Framework Custom Action.
Some more details about our .NET Custom Action can be found here: How to create a .NET Custom Action
Enough storytelling for today, let's get to today's scenario. Few days ago, I had yet another customer asking me how to replicate the VBScript behavior in a different type of Custom Action. While this wasn't possible in the past, I thought I'd give it another go with our current support for .NET Custom Actions.
This specific customer wanted to access the FeatureRequestState property of the Session object.
In VBScript, this is really easy because it has predefined support. For instance, accessing the FeatureRequestState property is as easy as:
Code: Select all
Session.FeatureRequestState("MyFeature")However, a workaround that I've found is making use of the GetFeatureState function, which returns two special objects, a "state" and an "action", where:
1. state represents whether the feature is installed or not on the machine - we can compare this with the FeatureCurrentState property of the Session object
2. action represents whether the feature will be installed or not on the machine - we can compare this with the FeatureRequestState property of the Session object
Now that we know how to achieve our goal, let's get to coding.
1. the first step would be creating the .NET Framework custom action as per the article I've linked at the start
2. under Project Solution, double click on the MsiSession.cs and add the following declaration:
Code: Select all
[DllImport("msi.dll", CharSet = CharSet.Unicode)]
internal static extern uint MsiGetFeatureState(int hInstall, string szFeature, out int iInstalled, out int iAction);3. in the same file, we have to declare the function as well:
Code: Select all
public void GetFeatureState(string szFeature, out int iInstalled, out int iAction)
{
NativeMethods.MsiGetFeatureState(MsiHandle.ToInt32(), szFeature, out iInstalled, out iAction);
}Note: This sohuld be done towards the end, where the other functions are declared.
4. now that all the "prerequisites" are met, here's the final code that calls the GetFeatureState function:
Code: Select all
using System;
using System.Windows.Forms;
using WindowsInstaller;
namespace CustomActionFRQNew
{
public class CustomActions
{
public static int CustomAction1(string aMsiHandle)
{
MsiSession session = new MsiSession(aMsiHandle);
int state = 0;
int action = 0;
session.GetFeatureState("featureSample", out state, out action);
MessageBox.Show(state.ToString());
MessageBox.Show(action.ToString());
return 0;
}
}
}Implementing this in Advanced Installer is quite easy and it is also showcased in the first article that gives more details about the .NET Custom Action.
Here's how I defined the custom action in a sample project:
1. add the DLL file as a temporary file in the "Files and Folders" page
2. Custom Actions page
3. CallNetMethod custom action
4. define it as it follows:
After building the project and running the MSI, the two message boxes will appear, giving us our state (Session.FeatureCurrentState) and action (Session.FeatureRequestState).
In our case, here's the results:
1. state = 2 (meaning that the feature is not installed on the machine - true, considering it's our first time installing the package)
2. action = 3 (meaning that the feature is to be installed locally)
For more details about the Feature state and action values, please refer to the following article: Edit Control Dialog
Hope this helps!
Best regards,
Catalin