Working with a Managed-Code Action in a Suite/Advanced UI Installation

InstallShield 2019

Project • This information applies to Suite/Advanced UI projects.

Edition • The Advanced UI project type is available in the Professional edition of InstallShield. The Suite/Advanced UI project type is available in the Premier edition of InstallShield. For information about the differences between these two project types, see Advanced UI Projects vs. Suite/Advanced UI Projects.

InstallShield lets you add to your Suite/Advanced UI project an action that calls a public method in a managed assembly that is written in managed code such as Visual Basic .NET or C# at run time.

Creating a Managed Assembly for a Managed-Code Action

The first step in adding a managed-code action to a Suite/Advanced UI project is to create the managed assembly. You can create the managed assembly with any recent version of .NET languages such as Visual Basic .NET or C#.

The Suite/Advanced UI engine requires that each managed-code action have one entry point. An entry point in this case is either a static method, or an instance method on a class that can be constructed without any parameters.

To specify the entry point, use the Class setting and the Method setting for the action in the Events view.

The Suite/Advanced UI installation calls the entry point when an action in the installation is scheduled to run. Your entry-point method should return the number zero (0) to indicate that the action finished successfully. If the action fails, it should return a non-zero value. The error values that are returned are the same as those defined for return in Windows Installer custom actions.

The interface that is passed to the action’s entry point implements the ISuiteExtension interface, which is passed as an object. The return type should be a 32-bit integer type.

To work with a Suite/Advanced UI extension interface, you can include code such as the following when you are writing C# code, for example, in Visual Studio:

[Guid("BAFAEAED-08C6-4679-B94E-487A4D89DE63")]

[TypeLibType(4288)]

public interface ISuiteExtension

    {

        [DispId(1)]

        string get_Attribute(string bstrName);

        [DispId(2)]

        void LogInfo(string bstr);

        [DispId(3)]

        string get_Property(string bstrName);

        [DispId(3)]

        void set_Property(string bstrName, string bstrValue);

        [DispId(4)]

        string FormatProperty(string bstrValue);

        [DispId(5)]

        string ResolveString(string bstrStringId);

    }

You can use the following methods in your managed code:

LogInfo—This method writes any information that is needed to the Suite/Advanced UI debug log, making it available for debugging or other informational purposes. The bstr parameter contains the string to be written to the log.
get_Property—This method retrieves the value of any property that is currently defined in the running Suite/Advanced UI installation. Properties that are not defined return an empty value. The bstrName parameter specifies the name of the property whose value is being obtained. The value for the property is returned in the bstrValue parameter.
set_Property—This method sets the value of a new property or changes the value of an existing property in the currently running Suite/Advanced UI installation. Passing an empty value effectively deletes the property. The bstrName parameter specifies the name of the property to set. The bstrValue parameter specifies the value to set for the specified property.
FormatProperty—This method resolves embedded formatted expressions in the string that is provided in the bstrValue parameter. The formatted value is returned in the bstrReturnValue parameter. To learn about the syntax that is available for formatted expressions, see Using Formatted Expressions that Advanced UI and Suite/Advanced UI Installations Resolve at Run Time.
ResolveString—This method resolves a Suite/Advanced UI string identifier into the corresponding string value for the currently running Suite/Advanced UI installation in the currently selected UI language. The bstrStringId parameter specifies the string identifier to resolve, and the resolved string is returned in bstrReturnValue. If no such string identifier exists, the returned string is empty.

The following sample C# code corresponds with a Class setting value of TestCLRAction.TestCLRClass and a Method setting value of TestCLRMethod:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Runtime.InteropServices;

using System.Security.Cryptography;

using System.Security.Cryptography.X509Certificates;

using Microsoft.WindowsAzure.Common;

using Microsoft.WindowsAzure.Management;

using Microsoft.WindowsAzure.Management.WebSites;

using Microsoft.WindowsAzure.Management.WebSites.Models;

using Microsoft.WindowsAzure;

using System.Windows.Forms;

 

namespace TestCLRAction

{

    [Guid("BAFAEAED-08C6-4679-B94E-487A4D89DE63")]

    [TypeLibType(4288)]

    public interface ISuiteExtension

    {

        [DispId(1)]

        string get_Attribute(string bstrName);

        [DispId(2)]

        void LogInfo(string bstr);

        [DispId(3)]

        string get_Property(string bstrName);

        [DispId(3)]

        void set_Property(string bstrName, string bstrValue);

        [DispId(4)]

        string FormatProperty(string bstrValue);

        [DispId(5)]

        string ResolveString(string bstrStringId);

    }

 

    public class TestCLRClass

    {

        const UInt32 ERROR_INSTALL_FAILURE = 1603;

        const UInt32 ERROR_SUCCESS = 0;

 

        ISuiteExtension GetExtensionFromDispatch(object pDispatch)

        {

            if (Marshal.IsComObject(pDispatch) == false)

                throw new System.ContextMarshalException("Invalid

                dispatch object passed to CLR method");

 

            return (ISuiteExtension)pDispatch;

        }

        public UInt32 TestCLRMethod(object pDispatch)

        {

            try

            {

                ISuiteExtension suiteExtension = GetExtensionFromDispatch(pDispatch);

                suiteExtension.set_Property("TESTPROP", "hello, world");

            }

            catch (System.ContextMarshalException)

            {

                return ERROR_INSTALL_FAILURE;

            }

 

            return ERROR_SUCCESS;

        }

    }

Note that although the Suite/Advanced UI installation allows any action to be performed, actions are run with the privileges that they are configured to have. Some actions may require administrator privileges (such as reading IIS 7.x configuration data). In such cases, in order for the action to access the required data successfully, the action would need to be configured to require administrator privileges; that is, Yes would need to be selected for the Requires Administrative Privileges setting for the action in the Events view. As an alternative, the Suite/Advanced UI installation’s Setup.exe file could be run with administrator privileges, or it would need to include an administrator manifest. However, privileges should be elevated for as short of a duration as possible.

Adding a Managed-Code Action

To add an action that calls a public method in a managed assembly during a Suite/Advanced UI installation:

1. In the View List under Behavior and Logic, click Events.
2. Right-click the Actions explorer and then click New Managed Code. InstallShield adds a managed-code action to the Actions explorer.
3. Enter a new name, or right-click it later and click Rename to assign it a new name. Use a name that helps you distinguish this action from other actions in your project.
4. Configure the action’s settings as needed.

Once you have added the action to your project, schedule it as needed. For more information, see Scheduling a Suite/Advanced UI Action.

Run-Time Requirements for a Managed-Code Action

You can use the Suite/Advanced UI property IS_CLR_VERSION to identify a semicolon-delimited list of .NET Framework versions that the action should attempt to load to run your managed code. To learn more about the IS_CLR_VERSION property, see Advanced UI and Suite/Advanced UI Property Reference.

If the managed-code action has any dependencies, add these to your project through the Support Files view. At run time, the Suite/Advanced UI engine specifies to the .NET Framework that the dependencies are in [SETUPSUPPORTDIR].

See Also