Extending Your Installation with COM Objects

InstallShield 2015

Important: Do not confuse COM objects with InstallShield objects. They are two separate features.

Instead of using DLLs or other executable files, you can extend your installation with COM objects. COM objects can be integrated into your installation fairly easily. Use the following procedure to assign COM objects in your script.

To assign a COM object:

1. Declare an object variable. For example:

OBJECT oMyCOMObject

2. Get a reference to your COM object and assign it to the variable by using the set keyword. For example:

set oMyCOMObject = CreateObject ( szMyProgID );

The value of szMyProgID is a valid program ID for your COM object. If you leave the set keyword out, the script engine attempts to set the default property of oMyCOMObject to szProgID. Because there is no default property, since oMyCOMObject does not contain a reference to your COM object yet, the script will fail.

Important: By default, once a COM object is loaded by the installation using CoCreateObject, CoCreateObjectDotNet, CoGetObject, or DotNetCoCreateObject, it remains loaded until the installation is finished. The COM object remains loaded regardless of whether the COM object variable goes out of scope or is set to NOTHING.

Consequently, the library referenced by the COM object is also not released until the installation is finished. However, it is possible to unload the library referenced by the COM object by calling the Windows API CoFreeLibrary. CoFreeLibrary unloads the library regardless of whether any object variables still reference it. Therefore, you should only call CoFreeLibrary after all objects that reference the library have gone out of scope or are set to NOTHING. See the following example code:

prototype void ole32.CoFreeLibrary( byval int );

int hModule;

 

program

 

    // Free the library.

    hModule = GetModuleHandle( "CSharpClassLibrary.dll" );

 

    if( !hModule ) then

       MessageBox( "Failed to get module handle", INFORMATION );

 

    else

 

       CoFreeLibrary( hModule ); // Release the library

 

    endif;

 

endprogram

CoFreeUnusedLibraries can also be used to unload the library. However, by default, the system waits 10 minutes before unloading the library, and in most cases, the installation requires the library to be unloaded immediately. If your installation will run on Windows XP and later only, you can call CoFreeUnusedLibrariesEx, which includes the option of unloading the library immediately.

Below is an example COM object that validates a serial number. It has one method, Validate, and one property, IsEval.

function OnFirstUIBefore()

    OBJECT oObj;

    STRING szProgID, szMsg, szTitle, svName, svCompany, svSerial;

    BOOL bValidSerialNumber, bEval, bValidate;

    NUMBER nResult;

begin

    szProgID = "MySerialValidation";

    set oObj = CreateObject( szProgID );

    if ( !IsObject( oObj ) ) then

        MessageBox( "Object " + szProgID + " is invalid!", SEVERE );

        return ISERR_GEN_FAILURE;

    endif;

 

    bValidSerialNumber = FALSE;

    while (!bValidSerialNumber)

        szMsg = "Please enter your name, company name, and product serial number.";

        szTitle = "Enter info";

        nResult = SdRegisterUserEx( szTitle, szMsg, svName, svCompany, svSerial );

        if ( nResult < 0 ) then

            MessageBox( "Failed to display dialog box.", INFORMATION );

            return ISERR_GEN_FAILURE;

        endif;

 

        /* Check the value of the object's IsEval property. */

        bEval = oObj.IsEval;

        /* Execute the object's Validate method and

        get the return value from the method. */

        bValidate = oObj.Validate( svSerial );

        if ( bEval || bValidate ) then

            bValidSerialNumber = TRUE;

        else

            MessageBox( "Invalid serial number; please re-enter.", INFORMATION );

        endif;

    endwhile;

 

    return ISERR_SUCCESS;

end;

Note: You can pass a data structure to your COM object as long as it has the members that your COM object expects. The following is an example of passing a data structure:

#define PERSON_NAME_SIZE 1024

 

typedef PERSON

    begin

        STRING Name[PERSON_NAME_SIZE];

        NUMBER Age;

    end;

 

function OnBegin()

    PERSON pPerson;

    NUMBER nPhoneNumber;

    OBJECT oMyCOMObject;

    STRING szMyProgID;

begin

    /* Assign a value to szMyProgID in this line. */

    set oMyCOMObject = CreateObject ( szMyProgID );

    if ( !IsObject( oMyCOMObject ) ) then

        MessageBox( "Object " + szMyProgID + " is invalid!", SEVERE );

        return ISERR_GEN_FAILURE;

    endif;

    nPhoneNumber = oMyCOMObject.GetPhoneNumber( pPerson );

 

    return ISERR_SUCCESS;

end;

Note: The standard COM return value HRESULT is not visible to an automation client such as InstallScript. To return a value from your COM object method, you should have an [out,retval] parameter in your method’s parameter list, as illustrated in the following code samples.

IDL:

interface IMyInterface : IDispatch

{

    [id(1)] HRESULT DoSomeWork([in] long nInputValue, [out,retval] long *pReturnValue);

}

C++:

STDMETHODIMP MyInterfaceImpl::DoSomeWork(long nInputValue, long *pReturnValue)

{

    // your implementation code

    *pReturnValue = 1; //return a value to client

    return S_OK;

}

InstallScript:

function OnBegin()

    NUMBER nObjReturn;

begin

    set oMyCOMObject = CreateObject("MyProgID");

    if (IsObject(oMyCOMObject) then

        nObjReturn = oMyCOMObject.DoSomething(10);

        /*nObjReturn will contain the value 1, returned from your implementation*/

    endif;

end;

See Also