InstallShield Tips and Techniques

January 17, 2012

How to update an InstallShield v6.x CAB file

Filed under: Reference Materials — shieldmaster @ 12:46 am

Let’s step back in time – before Windows Installer, and setups had no special security issues. In this situation I had to modify an existing installation – essentially frozen with no ability to recreate the application setup. I needed to replace an executable with a newer version, but leave intact the ability for the setup to work properly.

The CAB file associated with InstallShield v6x does not use the same Zip/Archive technique as PKZip or Microsoft. Consequently you cannot modify a CAB file unless you use the special batch command line tools provided by InstallShield.

Tools

ISCab.exe – command line tool used to add/modify/delete files

ISCabVu.exe – GUI tool used to view contents of a CAB file

Process

 

  • Create a INI file listing of the CAB contents

We need to use the ISCab.exe in batch mode to create an INI file of the existing CAB file. Note we are only going to specify the DATA1.CAB – all other CAB files (Data2/Data3, ect) will be included in the INI file.

 

  • Modify the INI file listing to reflect the revised or new files

Clone the output INI file from Step #1 and modify it. Look for all occurrences of the file we need to replace (in this sample it is “Archiver.exe”. To add or replace a file, we will use the same convention. Identify the File Group and signify which file is to be added. Here is a sample of Archiver.exe which was found in only one location.

 

[ISCAB Info]

Product=ISCAB

Version=2.0

 

[[Archiver]NS_NSR_NPL_1___<TARGET_DIR_ARCHIVER>_1]

File1=”Archiver.exe”

 

 

  • Update the CAB contents

We need to use the ISCab.exe in batch mode to read the modified INI file and point to the CAB file we want to update.. Note the tool is relative stupid – we need to store the new/replacement files in the same directory as the ISCab.exe. The CAB will be updated in place – so copy it elsewhere if needed.

 

  • Verify the CAB has been successfully changed

There are two methods we need to verify that the change was successful”

  • Run step #1 again and specify a different output INI name. Use this to compare against the original INI – very that all of the other files are still within the CAB. The match should be perfect if you are replacing a file.
  • Use the GUI CAB viewer “ISCabVu.exe” (in Expert Mode) to open up the DATA1.CAB that was modified. Using the File Group, look for the file with an altered TimeStamp and size. Sometimes the Version number does not get reflected. You can Extract the File to compare the file more closely.

 

Sample Batch Command file

The contents are from the file “AlterCab.bat” in which I have demonstrated how to handle CAB modification with the same revised executable “Archiver.exe”

REM ************************************************

REM ** Replacing Files in INSTALLSHIELD v6.x CAB

REM ** These are notes on how to replace individual

REM ** files within an InstallShield v6.x CAB file

REM ** Remember, only deal with DATA1.CAB – other cab

REM ** files (Data2, Data3) are handled when you

REM ** change DATA1.cab

REM ************************************************

 

REM ************************************************

REM ** First need to obtain INI listing of CAB

REM ************************************************

REM “c:\Archiver781_HotFix\iscab.exe” “c:\Archiver781_HotFix\Setups\DVD2 – Recorder\data1.cab” -i”Recorder_Witness_datacab.ini” -lx

 

REM ************************************************

REM ** Clone INI file “Datacab.ini” and only

REM ** leave in the entry for files to be replaced

REM ** The new files should be in the same directory

REM ** as the ISCAB.exe file..

REM ************************************************

REM “c:\Archiver781_HotFix\iscab.exe” “c:\Archiver781_HotFix\Setups\DVD2 – Recorder\data1.cab” -i”Revised_Recorder_Witness_datacab.ini” -a

 

REM ************************************************

REM ** To ensure correct updating, obtain another

REM ** INI listing of CAB after replacement and

REM ** use Text Compare tool to verify all files

REM ************************************************

REM “c:\Archiver781_HotFix\iscab.exe” “c:\Archiver781_HotFix\Setups\DVD2 – Recorder\data1.cab” -i”AfterRevised_Recorder_Witness_datacab.ini” -lx

 

REM ************************************************

REM ** To ensure correct updating of the File Size

REM ** and timestamp, you need to use ISCabVu.exe

REM ** (in Expert Mode)to view the Data1.cab

REM ** contents to verify the files changed

REM ************************************************

 

 

 


 

December 1, 2011

Converting a MSI to an InstallShield Basic Project

Filed under: Reference Materials — shieldmaster @ 11:07 pm

Recently I had two separate situations that arose in which I had a MSI and needed to convert each to an InstallShield Project. One was a project that was originally a WISE installation, and the other was a InstallShield MultiPlatform package. In both situations I had access to a MSI Package, and chose to convert it to an InstallShield package.

Apparently the built-in Conversion feature is not as well known as I thought – and it’s been around since v10.5, so it seems to be a good candidate for a BLOG entry, so here it goes!

First, you need to open the InstallShield project and then select OPEN from the File Dropdown menu.

Notice that there are three data entry fields ‘File Name:’; ‘Files of Type:’; and ‘Open as:’ entries. Notice that the ‘Open as:’ entry has two choices, Auto and Wizard.

Choose Wizard and open the MSI Package.

You will receive the next dialog which allows you to choose to open the MSI for Direct Editing or Convert the MSI/MSM to an InstallShield project. Now if you did not realize it, when you open a MSI you can change quite a few items, such as System Search Entries, string values, etc. This has been helpful in many situations, but I don’t recommend it due to a lack of auditing capabilities. IT has been a great solution to validate entries, such as to verify whether files are included in the MSI.

Let’s continue – select the Convert option:

The next dialog screen will be prefilled with generic information – as shown here:


You should name it uniquely and set the disk location for the new project to be stored – as I have done:

Selecting Finish will most likely result in a verification dialog, as shown here:

 

The InstallShield will complete the conversion and it creates a Basic MSI Project, ready for you to finish dressing up:

Depending on what type of Project you started with will depend on the effort to finish the project. For example a Wise created MSI will end up creating a project with non-standard Dialog names and Custom Actions.

Just start at the top and work thru the project, cleaning up as you go:

The nice aspect is the files are extracted from the Binary table and placed in an sub-directory “Files” under the new ISM Project. But it’s much easier than rebuilding an old project from scratch!

 

Hope this helps!

ShieldMaster

 

 

October 23, 2011

Creating additional Destination Folder dialog

Filed under: Reference Materials — shieldmaster @ 12:39 am

For some projects I occasionally find that it is necessary to prompt the user for a destination location in addition to the default INSTALLDIR.

 

For example, what if I want to confirm the Java JRE directory that I found installed is the one the user wants to associate with their applications (quite possible they certified an older JRE version – not the most current). The only reference I found on how to do this was for InstallScript MSI project, but I am working solely in Basic MSI projects.

In order to provide the end user with the same Browse to a folder dialog used in a default installation, the following steps can be followed for use in a Basic MSI InstallShield project:

  1. Create a new Directory that will be used to hold the JRE directory found – and will be displayed in the Browse directory. Since I have never, (repeat never) mastered the Directory Table (using Direct Editor), here is how I approach it. I create a new component (delete if afterwards) and select the dropdown to create a new directory entry.


     

    Now a directory browse dialog is presented:


    Using the INSERT key, create a new directory “JRE Path”


    Now rename the Directory Identifier to be all CAPS, such as “JRE_PATH” – this will be the MSI Property that we will use as our Directory. Now we need to create some dialog screens to display and allow the user to browse to a new directory.

     

    Go to the Dialogs section, and export a dialog that we will need to “repurpose” for our needs. For our example, we are going to export the dialog “AdminChangeFolder” by selecting the dialog and right-clicking. Export the dialog ISD to a folder you can retrieve it from later.


     

    Now rename the original “AdminChangeFolder” to “AdminChangeFolder_ORIG” to preserve it. I do this because even though I tried to rename the dialog during export, it always appears with the same name – overwriting the original.

     

    Now import back the “AdminChangeFolder” dialog by right-clicking on the “All Dialogs” title. The repository appears:


    Browse to the saved dialog, and select it – it will appear in the repository as shown here:


     

    Select OK and the dialog will appear back in your listing of dialogs.


    WARNING: if this popup dialog appears:


    You must select the red conflict item and select “Overwrite”, like this:


    What is happening is that the internal bitmaps are being exported as “NewBinary1″ files and stored in the same directory as the project ISM file (Hint: look for a file “NewBinary1″ and copy as “NewBinary.jpg” and you will see the banner bitmap). Here is the result you might find – the banner bitmap points to a file “NewBinary1″ – not to the original file location:


     

    The solution is to replace the “File Name” with the original value, such as: <ISProductFolder>\Redist\Language Independent\OS Independent\IsDialogBanner.ibd (With InstallShield v10.5 it will ripple this NewBinary1 reference to ALL of your dialogs, so you may have to create a new InstallShield project to determine the original file values. If this happens, then you either must go to each dialog and correct it, or you can open the Direct Editor, go to the “Binary” table and alter the displayed value for NewBinary1,


     

    Now rename “AdminChangeFolder_ORIG” to “JavaChangeFolder”.

     

    We are going to leave this dialog and create a new dialog “JavaDirectory” that will display the Java JRE directory along with a “Change” button.

    Here is a sample of one I created:


     

    Essentially it contains a text box, a PathEdit box and a Change pushbutton. The property associated with the PathEdit box is “JRE_PATH”.

    We want the user to see a directory browse button when they hit the ‘Change’ pushbutton, so we need to switch to the ‘Behavior’ to edit the JavaDirectory dialog behavior. On the Change pushbutton (titled ‘PushButton1′ add an Event “SpawnDialog” with the argument “JavaChangeFolder” and a condition of 1 – as shown here:


     

    Now change to the dialog “JavaChangeFolder” and in the dialog view, change ALL of the property values from “TARGETDIR” to the property “JRE_PATH” as shown:


     

    Then you will need to switch to the ‘Behavior’ view and alter the event OK and change the argument from “TARGETDIR” to “JRE_PATH”


    FINALLY – go to the project Property Manager section and delete the property “JRE_PATH” – if you don’t the path will be incorrectly set as “0″ and your project will hang during the starting and fail with error 1603!! For some reason, this value will keep appearing during your development, so you may need to double check it a couple of times.


    Now, to prime the directory “JRE_PATH” you can setup an Custom Action to grab the environment variable JAVA_HOME and prime the directory with this value, or you can execute a Custom Action InstallScript that will evaluate the machine and set this MSI Property (MsiSetProperty xxx) to a directory value. Here is a sample display of the dialogs when running:


     


     


     

     

    Hope this helps!

    ShieldMaster

     

     

     

     

     

     


 

June 27, 2011

InstallShield Upgrade Strategy

Filed under: Reference Materials — shieldmaster @ 9:42 pm

Quite a concern with customers is what strategy should they follow when delivering future updates to their application. The confusion as to what to delivery (Small Updates, Minor Updates, Major Upgrades, Patches) leaves the customer paralyzed with indecision. Couple that with having a part-time InstallShield developer (or consultant), and you will need to evaluate a strategy that blends reliability with ease in creating and QA testing an upgrade.

In this post, I would like to outline a roadmap for your Upgrade Strategy, giving both Pros and Cons as well as realistic guidance that experience has provided.

Packaging Options

First, let’s discuss the various packaging options that are available to you.

  • Each upgrade can be packaged for delivery as a full MSI installation which can offer existing clients a method to deliver just the updated files, or a full replacement of the original package. The advantage of creating a full MSI installation is that it can be delivered to new customers and they will be able to install and configure as easily as the original installation.
  • An upgrade can be packaged as a Windows Installer patch file that offers existing customers a smaller footprint, and will apply binary file differences that will upgrade a file from the previous version to the newer version. The effort to create this is relatively simple, but must be tested as much as a full upgrade package. In addition it can only deliver updates to existing customers after a full installation – a new customer cannot install a Patch package and have a working program.

Windows Installer GUID Codes

The GUID Codes associated with each InstallShield package play a major role in how Windows Installer determines whether the package being installed is considered a new installation, or an update that is being handled as a Major or Minor upgrade.

  • Package Code – must change for each build. Pretty much ignored for your requirements.
  • Product Version – MSI Property – Only 1st three fields used by Windows Installer for version comparisons (Build # ignored)
  • Product Code– MSI Property – GUID of product. If two packages with same name have different ProductCode’s, MSI treats both packages as different!
  • Upgrade Code – MSI Property holds GUID of family of products – used for patching purposes. Essentially never change for life of application!

 

Here is a matrix that graphically displays when each GUID should be changed:

Now, let’s discuss the various vehicles that InstallShield provides to deliver updates to your customer.

Small Update

This type of update is characterized by just some simple product changes – so small in scope that you don’t alter the Product Version number. Some requirements you must adhere to when preparing the installation to be delivered as a Small Update:

  • Can add a new component to an existing feature
  • Can add a new component to a new feature
  • Can add new sub-feature with new components
  • Cannot change MSI Package name
  • Cannot move or delete a feature
  • Cannot move/delete component
  • Cannot change Component GUID
  • Cannot change the Key file of a component

In practice, delivering a new full MSI Package without changing the Product Version ensures you will have no means to track which customer has received this package. Granted the Package Code will always be regenerated, but that is not easy for the customer to determine. Realistically this might be a method to rebuild the package while it’s in the QA stages – I just don’t see a practical use for delivery to customers.

Minor Upgrade

This is the typical solution that most developers deliver to their customer base. Characterized by a full rebuild of the package with the Product Version changing (goes from version 2.1.3.xx to 2.2.0.xx), it most often will contain newly compiled binary files that resolve a customer reported defect. When the new customer receives this package, a full installation will occur with all of the User Dialogs presented with version 2.2.0.xx installed.

When an existing customer (v2.1.3.xx) receives this package, they will see a small dialog asking “Do you want to upgrade the application? Y/N) – and then they would just see the progress bar as the updated binaries are applied. Note that no User Dialogs will appear, the same destination drive/directory are maintained, plus any features selected within original installation are preserved with no ability to change.

A patch can be created that provides a method to deliver the Minor Update changes in a smaller footprint versus delivering a full MSI package.

Note that it is critical that you have followed “Best Practices” when creating the components – and key files are set for all versioned binary files. If you keep all of the non-versioned files in a component, it would be recommended that you select a versioned file as the Key file of the component.

Some requirements you must adhere to when preparing the installation to be delivered as a Minor Upgrade:

  • Can add a new component to an existing feature
  • Can add a new component to a new feature
  • Can add new sub-feature with new components
  • Cannot change MSI Package name
  • Cannot move or delete a feature
  • Cannot move/delete component
  • Cannot change Component GUID
  • Cannot change the Key file of a component

 

Major Upgrade

This is the method by which developers introduce a significant change to the application, which would require the user to completely uninstall the original application and then the new application is installed. With the authoring of a Major Upgrade entry, this process is accomplished seamlessly when the new installation is executed by an existing customer.

Most importantly, you decide when a new release qualifies as a Major Upgrade, for example version 2.2.0.xx to 3.0.0.xx might qualify, but you may want to have 2.2.0.xx to 2.3.0.xx be handled as a Major Upgrade, especially if a new feature is introduced and you want the customer to be able to choose it during installation.

Some requirements you must adhere to when preparing the installation to be delivered as a Major Upgrade:

  • Can add a new component to an existing feature
  • Can add a new component to a new feature
  • Can add new sub-feature with new components
  • Can change MSI Package name
  • Can move or delete a feature
  • Can move/delete component
  • Can change Component GUID
  • Can change the Key file of a component

As you can see, it’s pretty flexible since the original installation is being removed you have free rein in doing anything you want with Features and Components.

You can specify the behavior of how the Major Update is applied, you have the following choices:

  1. Completely remove the original application, registry entries, and files, then install the new application. Note that none of the original files are preserved or backed up during the process.
  2. Overwrite the original application, then weed out obsolete files as necessary.

Realistically, I always choose option #1, because it offers the customer the flexibility of choosing a different drive and destination folder.

 

Considerations

Here are the Pros and Cons that I am aware of with each upgrade approach ( I am ignoring Small Updates completely):

Minor Update

Pros

  • Works consistently when a versioned binary files has newer version number (matches InstallShield product version).
  • Allows you to create small “Patches/Updates” from this new MSI package.
  • Process is typically “built” into an installation, requiring overt entries to the Upgrade table. Accomplished simply by altering the Version number.
  • Can use Patch process to deliver changes in a smaller footprint

Cons

  • No user dialogs presented, so customer has to live with the original drive and directory.
  • If package delivers a registry entry, which is modified by InstallScript Custom Actions – or during the user dialogs, this may not be done during Minor Update, consequently you might have empty variables in the registry after the update. Modifying the REINSTALLMODE properties can prevent the registry from being rewritten. Creating a new Custom Action that runs with Condition=Installed will also work towards resolving this issue.
  • Application files that are configured by the customer during application execution should be preserved – but you have to watch to ensure they are not overwritten by the template within the CAB files. Sometimes a InstallScript Custom Action that preserves the user configuration files before the Upgrade process and then another to restore it after the Upgrade process is necessary.
  • Delivering new non-versioned files (XML, INI, CFG, etc) may not be delivered consistently (Refer to link regarding File Versioning rules). Only alternative to ensure new non-versioned files are consistently delivered are to modify the REINSTALLMODE properties to force all files to be delivered (overkill at best), or create an InstallScript Custom Action before the update step to delete the critical non-versioned files to ensure that they are always delivered.
  • Cannot make significant changes to organization of the package (for example, restructure the Features)

 

 

Major Update

Pros

  • Allows unlimited reorganization of Features and Components – essentially a vastly different package than the original one
  • Allows you the ability to wipe out troublesome packages that were originally delivered that are not easy to properly apply updates to.
  • Full user dialogs presented, allows existing customers to choose different Features, specify a different drive or destination folder
  • Removes existing product silently at beginning
  • To denote a Major Update, you must:
    • Regenerate the Product Code GUID
    • Change the Version Number
    • Author a Major Upgrade entry in the Updates table

     

    Notes:

  1. to run a Custom Action during uninstall of Original Product, use condition “Remove=”ALL” not “UPGRADINGPRODUCTCODE”
  2. To run a Custom Action during upgrade, use condition “UPGRADINGPRODUCTCODE

Cons

  • Must be mindful that the uninstall may not completely remove all or the original installation, which could pose problems for the new installatino

 

Recommendations

These recommendations are based on years of providing consulting services to small development shops that don’t have a Full Time Dedicated InstallShield Developer. Consequently, your upgrade strategy should focus on creating Upgrade packages that are:

  • easy for the customer to apply and relatively Bulletproof so that valuable hours are not wasted dealing with customer upgrade issues.
  • Able to consistently build with repeatable results
  • QA can handle the iterative testing to ensure files are delivered correctly in all scenarios

 

  1. Small Update – don’t even think of them in a customer environment!
  2. Realize that creating Minor Upgrades will require extensive InstallShield package testing and particular attention to the treatment of non-versioned files. Don’t create a Minor Update unless you are going to devote the testing to ensure all files correctly updated.
  3. Patches require extensive testing, far beyond their worth in the field – which is mainly a smaller download size. I would just create Minor Updates, test correctly and release this to both existing and new customers.
  4. If you have no user configured data to be concerned with, then I recommend that you consider every release a Major Upgrade. It removes the requirement to ensure non-versioned files are correctly, and you are sure everyone is correctly updated at the end. If you don’t have a dedicated InstallShield developer, or limited QA testing time this is the way to go.

    As far as the treatment of user configuration data/files goes, if you put in the System Search and/or InstallScript Custom Actions, and they are proven to work correctly – then releasing a Major Upgrade becomes quite straightforward and easy to manage for future releases.

     

Hope this helps!

ShieldMaster

March 17, 2011

Preselecting Features within an InstallShield Basic MSI Project

Filed under: Reference Materials — shieldmaster @ 9:44 pm

My previous blog discussed a method using InstallScript to determine whether a Feature had been selected by the customer in the Custom Setup dialog .

This blog posting will be about preselecting Features, the methodology and the issues involved.

 

In my sample Custom Setup Dialog, I have three major Features as shown in this Custom Setup Dialog:

 

I have some scripting to do, checking various components installed on the workstation. Now suppose that if:

  • .NET Framework 2.0 is not installed, deselect Feature “.NET Applications” before the dialog Custom Setup is presented
  • .NET Framework 2.0 was found installed, have the Feature “.NET Applications” preselected before the dialog Custom Setup is presented

 

I abbreviated the script logic to the critical script that sets a MSI Property “DOTNET_FEATURE” to a value of “FALSE” to test the logic:

 

NOTE: This script function MUST be sequenced before the standard action “CostFinalize”!

Now we need to set a Condition on the Feature “.NET Applications” that will make the feature be preselected or deselected.

Navigate to the Feature panel and create a Feature condition:

 

This Condition will alter the InstallLevel to be 200 if the MSI Property “DOTNET_FEATURE”=”FALSE”.

The InstallLevel, by default is set to 100, so any Feature or component that has a value from 1 to 100 will install. If you reset the level for a Feature (or sub-feature) to any number >100, the feature will be displayed Unselected.

Here are the results:

 

WARNING: if you set the InstallLevel to a value of 0, then the entry for Client Server will disappear from viewing in the Custom Setup Dialog.

If might be a nice option, but then the customer can never select the feature!

Hope this helps!

SHIELDMASTER

 

 

March 8, 2011

Setting up a Combo Box Dialog

Filed under: Reference Materials — shieldmaster @ 11:02 pm

Setting up the Windows Installer ComboBox can be hard to understand, but once mastered, you can use some flexible methods to create the list entries.

Here, I show a basic interior dialog “ISI_ComboBox” created with a Combo Box dropped onto it. The MSI Property associated with the Combo Box is “ISI_COMBOBOX”

To supply some fixed entries for the Combo Box, I switch to the Direct Editor, and select the ComboBox table.

I create three entries for the same MSI Property “ISI_COMBOBOX”, ensure the Order for display is in the sequence that I want and supply unique values. Now to specify the default value, I switch to the Property Manager and specify the default value for the MSI Property “ISI_COMBOBOX”

Here is the finished dialog – upon initial display the default instructor “Mike” is displayed:

And when the user selects the drop down, the other instructors are displayed:

But what if the entries in the Combo Box are dynamic – say you want to supply the user with a list of Client ODBC entries that should be linked to your Client installation.

Obviously this list is very dynamic , and will change for each user. Here is some InstallScript code that allows you to take as input a list “ODBC_CLIENTS” and inject these entries into the MSI table before the dialogs are displayed:

//**   Open view into ComboBox table

//*****************************************************************

MsiDatabaseOpenView(ISMSI_HANDLE,”SELECT * FROM `ComboBox` WHERE `Property`=’ODBC_CLIENTS’”, hViewlist);

   

MsiViewExecute(hViewlist, NULL);  

r = 0;                               

// Get the first string in the list.

nResult = ListGetFirstString (sKeys, szODBClients);

MsiSetProperty (ISMSI_HANDLE, “ODBC_CLIENTS”, szJODBClients);

    // Loop while list items continue to be retrieved.

    while (nResult != END_OF_LIST)

                szODBClientsTemp=szODBClients;

        StrReplace ( szODBClientsTemp, “_”, “”, 0 );

        StrReplace ( szODBClientsTemp, “.”, “”, 0 );

        StrToNum (szODBClientsNum, szODBClientsTemp);       

                if szODBClientsNum > 14200 then

                                r = r + 1;

                hRecordlist = MsiCreateRecord(4);                                                

                MsiRecordSetString(hRecordlist, 1, “ODBC_CLIENTS”);

                MsiRecordSetInteger(hRecordlist, 2, r);

                MsiRecordSetString(hRecordlist, 3, szODBClients);

                MsiRecordSetString(hRecordlist, 4, “”);

                // can only temporarily modify running .msi database

                MsiViewModify(hViewlist, MSIMODIFY_INSERT_TEMPORARY, hRecordlist);

                // Get the next string in the list.   

        endif;

        nResult = ListGetNextString (sKeys, szODBClients);   

                                                 

    endwhile;    

Note: It is up to you to create and populate the String list “ODBC_CLIENTS”, then select a string to populate the MSI Property ISI_COMBOBOX for the default value.

Here is additional reference from Robert Dickau here:

Hope this helps!

ShieldMaster

January 19, 2011

How to verify Feature selection within an InstallScript Custom Action

Filed under: Reference Materials — shieldmaster @ 1:42 am

I have a requirement to determine within an InstallScript Custom Action, when an application feature has been selected. Essentially there is a lot of discussion how you can set a condition based on Feature selection to launch a Custom Action – but very little regarding how to script logic to determine whether a feature was selected during the installation.

For example, here is a sample of a Custom Setup screen with Features and sub-features:

Nothing complicated, but I have a unique dialog screen “Software Prerequisites” that will display whether specific software prerequisites have been installed on the workstation – if they have not been installed, then I need to prevent the installation from continuing. Here is a sample showing how the NEXT button is disabled because Microsoft Office/Excel was not installed.

 

Now realistically, what if the sub-feature “Client Server 2″ was a Feature that when selected will require that Microsoft Office, Excel and the Office Primary Interop Assemblies be present? Obviously, only when this feature is selected by the user should the dialog “Software Prerequisites” allow the installation to be failed if they are not installed. If the customer did not select “Client Server 2″ for installation, then we can safely ignore the fact that Microsoft Office was not installed.

The scripting should be relatively simple? Well I initially thought so – but it’s turned out harder that I imagined!

Here is how I was able to get the script to function as I required:

  1. Create a InstallScript function – here is some script for evaluation:

    nReturnCode = MsiGetFeatureState (ISMSI_HANDLE, "CS2", nvInstallState, nvActionState);

       switch (nvActionState)

        case INSTALLSTATE_ADVERTISED:

            szString = "The advertised feature";

            MessageBox ("C2 state is:" + szString, INFORMATION);

        case INSTALLSTATE_ABSENT:

            szString = "The feature was uninstalled";

            MessageBox ("C2 state is:" + szString, INFORMATION);

        case INSTALLSTATE_LOCAL:

            szString = "The feature was installed on the local drive";

            MessageBox ("C2 state is:" + szString, INFORMATION);

        case INSTALLSTATE_SOURCE:

            szString = "The feature must run from the source, CD-ROM, or network";

            MessageBox ("C2 state is:" + szString, INFORMATION);

        case INSTALLSTATE_DEFAULT:

            szString = "The feature is installed in the default location: local or source";

            MessageBox ("C2 state is:" + szString, INFORMATION);

        case INSTALLSTATE_UNKNOWN:

            szString = "An unrecognized product or feature was specified";

            MessageBox ("C2 state is:" + szString, INFORMATION);

        case INSTALLSTATE_SOURCEABSENT:

            szString = "The feature must run from the source, and the source is unavailable.";

            MessageBox ("C2 state is:" + szString, INFORMATION);

        case INSTALLSTATE_INCOMPLETE:

            szString = "The installation is suspended or in progress";

            MessageBox ("C2 state is:" + szString, INFORMATION);

        default:

            szString = "The return code is not supported";

            MessageBox ("C2 state is:" + szString, INFORMATION);

        endswitch;

 

 

Notes:

  1. Here is how the InstallShield GUI displays the Features - for scripting to reference a Feature, you need to use the feature name "CS2" - not the Description, which would be what is displayed in the Custom Section dialog - "Client Server 3"
    

 

        
			

 

 

  1. Create a InstallScript Custom Action, referencing the InstallScript function. In my situation, I called the Custom Action using a “DoAction” on the NEXT button of the Custom Setup dialog.

     

    Here is what happens when the script executes Immediately after the NEXT button is pressed for the Custom Action:

    1. When Feature “CS3″ is selected by the user – the script case “ INSTALLSTATE_LOCAL” is activated.
    2. When Feature “CS3″ is not selected by the user – the script case “ INSTALLSTATE_UNKNOWN ” is activated.

       

  2. If you create a InstallScript Custom Action, referencing the InstallScript function – and set the Custom Action’s In-Script execution as “Immediate”, but run the CA in the Execute Sequence – just before the files are installed, here is what happens:
    1. When Feature “CS3″ is selected by the user – the script case “ INSTALLSTATE_LOCAL” is activated.
    2. When Feature “CS3″ is not selected by the user – the script case “ INSTALLSTATE_UNKNOWN ” is activated.

     

  3. If you create a InstallScript Custom Action, referencing the InstallScript function – and set the Custom Action’s In-Script execution as “Deferred”, and run the CA in the Execute Sequence – just before the files are installed, here is what happens – essentially :
    1. When Feature “CS3″ is selected by the user – the script case “ INSTALLSTATE_ UNKNOWN
      is activated.
    2. When Feature “CS3″ is not selected by the user – the script case “ INSTALLSTATE_UNKNOWN ” is activated.

    Note: This scripting won’t work at all if the Custom Action is deferred – you will need to capture the status and preserve it for retrieval later for a Deferred Custom Action.

  4. If you create a InstallScript Custom Action, referencing the InstallScript function – and set the Custom Action’s In-Script execution as “Immediate”, and run the CA in the Execute Sequence – just before the files are installed. Now suppose you use the Add/Remove Control Panel, specify MODIFY and uninstall feature CS3, – here is what happens:
    1. Feature “CS3″ – the script case “ INSTALLSTATE_ABSENT “ is activated.

 

So we have a working solution, we can utilize! I know the value from a selected feature is INSTALLSTATE_LOCAL” – so that is good enough to make my scripting easier!

 

There is another method you can check – you can retrieve the MSI Property “ADDLOCAL” for a comma separated list of selected features, such as ADDLOCAL=”ClientServer,CS1,CS2,Server,S1″. This somewhat tricky to capture – its only available after the Standard Action “InstallValidate”, and you can only capture it within the UI Sequence – it’s not available at all during the Execute Sequence. So, essentially you won’t be able to gather this information until after the dialogs have completed – so the script MsiGetFeatureState is a better solution.

 

 

 

 

August 23, 2010

Alternative method to extract COM Data

Filed under: Reference Materials — shieldmaster @ 11:58 pm

On a recent project, I was using the “tried and proven” method to extract COM Data by performing on-site registration using scripting (InstallScript).  With Windows 7 the Custom Action is not being elevated with the correct permissions and the registration was failing.

Since I did not want the project to use the InstallShield “KEY” file attributes (a subject of a later post), I reverted to manually extracting the COM Object by using this process:

  1. Right-click the file in the Component and selecting “Set Key File”
  2. Right-click the file again in the Component and selecting “Extract COM Data for key file”
  3. Right-click the file in the Component and selecting “Clear Key File”

The customer reported issues with the extracted COM Data being incomplete!  Apparently the CLSID entries were not being correctly extracted – as compared to running RegSvr32.

Now my research did find quite a few reported problems with COM Extraction – and they have been going back as far as IS 10.5!  Consequently,  I switched methods, and went to www.InstallSite.org and pulled down the utility “RegSpy.exe”  http://www.installsite.org/pages/en/msi/tips.htm .  This utility will manually extract the correct COM data.  I did not like the summation of how to extract to the registry – so I made these steps to accomplish this:

1.  Created a BAT file that will run RegSpy.exe and output a .REG file – here is a sample that I used:

ECHO ON

REM ***************************************************

REM **  Use RegSpy to extract COM Objects

REM **  Note:  Place RegSpy.exe in root of InstallPath!

REM ***************************************************

REM ***************************************************

REM **  Set base directory!

REM ***************************************************

SET InstallPath=E:\Project – OCXs Files\DeploymentFiles

REM ***************************************************

REM **  Set File to extract COM Objects

REM **  Set output registry file and Extract COM Object

REM ***************************************************

SET File=Cal32x30.ocx

SET RegOutputFile=%InstallPath%\%File%.reg”%InstallPath%\regspy.exe” “%InstallPath%\FarPoint\%File%” > “%RegOutputFile%”

2.  Edit each output .REG file created and substitute [INSTALLDIR] for the path statement – a sample shown here in the Before state:

[HKEY_CLASSES_ROOT\CLSID\{DEE22B42-FCA5-11D2-A05D-00A0C90DC755}\InprocServer32]

@=”E:\Project~1\DEPLOY~2\FarPoint\Cal32x30.ocx”

“ThreadingModel”=”Apartment”

3.  Since I used the input Deployment directory, this differs from the Installed directory, so I substituted [INSTALLDIR] for the path statement – a sample shown here in the After state:

[HKEY_CLASSES_ROOT\CLSID\{DEE22B42-FCA5-11D2-A05D-00A0C90DC755}\InprocServer32]

@=”[INSTALLDIR]Cal32x30.ocx”

“ThreadingModel”=”Apartment”

4.  Now go to the InstallShield project and navigate to the Component’s Registry section – and right-click on the center panel for the Destination Machine and select “Import Reg File”.  This will import all of the correct COM Data for the component.

Hope This Helps!

ShieldMaster

July 26, 2010

Primer on creating InstallScript Custom Actions

Filed under: InstallShield Scripting, Reference Materials, Techniques — shieldmaster @ 10:11 pm

I extensively use InstallScript for my custom actions – it provides great flexibility in accomplishing specialized requirements.  I have tried some custom actions using VBScript – but I have encountered some hardened Operating Systems in which VBScripts are considered malware and they have removed the extension association for .vbs – so your custom actions will fail.

In this blog, I will walk you thru the steps needs to create and sequence a custom action using InstallScript.  As an example, I will create scripts that will determine what the Operating system and log it to the MSI logfile.

  1. Create the initial script file by right-clicking on the InstallScript file and selecting “New Script File

2.  A new file “setup.rul” will appear with quite a lot of commentary.  In my InstallScript functions, I want only the following to appear in the setup.rul:

  • Includes for InstallScript functions and any Windows API functions
  • Prototype statements for all InstallScript functions called by the Script Engine
  • Prototype statements for all InstallScript functions called by other script functsion.
  • Include statement for other script RUL files.

Remove the script statements and replace with these entries

/////////////////////////////////////////////////////////////////
//
//       IIIIIII SSSSSS   IIIIIII
//           II       SS                II             Install Solutions, Inc.
//          II        SSSSSS      II               (c) 2001-2010, Install Solutions, Inc.
//         II                 SS      II              All rights reserved.
//    IIIIIII  SSSSSS   IIIIIII
//
//  This template script provides the code necessary to build an
//  entry-point function to be called in an InstallScript custom
//  action.
//
/////////////////////////////////////////////////////////////////
// Include Ifx.h for built-in InstallScript function prototypes,
// for Windows Installer API function prototypes and constants
#include “ifx.h”
// Prototype statements for Custom Action entry points export prototype ISI_CheckOS(HWND);
// Prototype statements for functions called by other Scripts prototype ISI_WriteLogFile(STRING);
// Include statements for external script files
#include “ISI_CheckOS.rul”
#include “ISI_WriteLogFile.rul”

For each Custom Action that is called directly by the script engine, it will need a “prototype” statement.  The only Custom Action (CA) we will be calling will be “ISI_CheckOS”.  The script for that CA will call another script function “ISI_WriteLogFile” that will submit an logging line to the MSI logfile.

Now, create two more script files by right-clicking on the same files section and create:

  • ISI_CheckOS.rul
  • ISI_WriteLogFile.rul

Note: that if the extension .RUL is not included, the InstallShield IDE will not properly color code the variables

Within the script RUL file for “IS_CheckOS.rul” enter the following:

////////////////////////////////////////////////////////////
//
//       IIIIIII SSSSSS   IIIIIII
//           II       SS                II             Install Solutions, Inc.
//          II        SSSSSS      II               (c) 2001-2010, Install Solutions, Inc.
//         II                 SS      II              All rights reserved.
//    IIIIIII  SSSSSS   IIIIIII
//
// Function: ISI_CheckOS
// Purpose: This function will be called by the script engine
// when Windows Installer executes your custom action
// and will verify that the Operating System version
// is correct.
//////////////////////////////////////////////////////////////

function ISI_CheckOS (hMSI)
STRING szParm, szPath;
STRING strKey;
NUMBER nvSize, nResult, nReturnCode;
STRING szBuffer, szLogMessage;
begin
//WriteToLogFiles
ISI_WriteLogFile (“ISI–> Entering ISI_CheckOS Function”);
// Approve Windows XP Workstation
if (SYSINFO.WINNT.bWinXP) then
szLogMessage = “ISI–> Operating System is Windows XP “;
ISI_WriteLogFile (szLogMessage);
nReturnCode = 0;
goto ExitCheckOS;
endif;
// If WinXP was not found, then -1 will be returned
szLogMessage = “ISI–> Operating System is not an approved OS”;
ISI_WriteLogFile (szLogMessage);
nReturnCode = -1;
ExitCheckOS:
//WriteToLogFiles
ISI_WriteLogFile (“ISI–> Exiting ISI_CheckOS Function”);
return nReturnCode;
end;

The CheckOS function accomplishes the following:

  • Immediately upon entry into the CA – will log a message to the MSI Logfile that entry was accomplished
  • Using predefined constant – will check if the OS is Windows XP and if it is then will log a message to the MSI Log file and pass a 0 (represents a good return code) back to the MSI Engine.
  • If the Operating System was not Windows XP, it will log that it was not and set the return code to be -1 (bad return code)
  • Prior to exiting the Script function, will log its exit to the MSI logfile.

Note:  if the InstallScript Custom Action has the Return Processing option set to “check exit code’, then a -1 passed back to the MSI Engine will abort the installation.

Within the script RUL file for “IS_WriteLogFile.rul” enter the following:

/////////////////////////////////////////////////////////////////
//       IIIIIII SSSSSS   IIIIIII
//           II       SS                II             Install Solutions, Inc.
//          II       SSSSSS      II               (c) 2001-2010, Install Solutions, Inc.
//         II                SS      II              All rights reserved.
//    IIIIIII  SSSSSS   IIIIIII
// Function:  ISI_WriteLogFile
//
//  Purpose:  This function will be called by the script engine
//            when Windows Installer executes your custom action
//            and will write entries to the MSI LogFile
/////////////////////////////////////////////////////////////////
function ISI_WriteLogFile(szLogMessage)
STRING  szTimeParm;
STRING  szDate, szTime;
NUMBER  nResult;
begin
// Get Time and Date information to append to log message
GetSystemInfo ( DATE, nResult, szDate );
GetSystemInfo ( TIME, nResult, szTime );
szTimeParm = “[" + szDate + ":" + szTime + "]“;
//WriteMessageToMSILog
SprintfMsiLog (“ISI CA Msg: %s %s”, szTimeParm, szLogMessage);
end;

The WriteLogFile function accomplishes the following:
    • Obtains the time and date stamps and appends it before the log message.
    • Write the log message to the MSI Logfile

Now to create the CA, go to the Custom Actions section on the left most panel, and right click on the Custom Actions entry in the middle panel:

Select “New InstallScript” and a new entry will be created – title this CA “ISI_CheckOS” and press enter.  Now we will fill in the CA selections:

For the simple InstallScript Custom Action, enter the following selections:

Function Name – using the drop-down, select the script prototype function “ISI_CheckOS” – which should appear in the drop-down selection.  If it does not, it is possible you will need to either build the application or save and reopen the InstallShield project.

Return Processing – select “Synchronous (Check exit code)”

In-Script Execution – select “Immediate Execution”

Execution Scheduling – select Always Execute

UI Sequence –  using the drop-down, select “After CostInitialize”

UI Sequence Condition – enter “NOT Installed”

Well, this should give you an excellent example on how to create an InstallScript Custom Action.

Hope this helps!

ShieldMaster

April 5, 2010

Launching a webpage on final dialog

Filed under: Reference Materials — shieldmaster @ 9:37 pm

Recently, I had a customer want to launch a webpage when the final installation dialog was presented. 

Obviously the original request was for a traditional web page link shown by the traditional underscored phrase.  No version of InstallShield supports this feature – although in the Release Notes for InstallShield 2010, there is a mention of being able to embed a hyperlink within a dialog.  For for all of you who are not up-to-date with the latest IS version, here are the steps that I took to handle this request.

I modified the existing link that enabled you to “Launch a program” that is built into the final dialog “SetupCompleteSuccess”.  The important parts of the dialog are:

  • CheckLaunchProgram – this is the CheckBox field
  • LaunchProgramText – this is the text that accompanies the CheckBox field, relatively small
  • UpdateTextLine2 – this is another text field that I commandeered to provide more accomplanying text than what was available.

Step 1: 

Ensure all fields have the same launch conditions.  The one I grabbed had a different launch conditions – so ensure the conditions are the same - alter the SHOW Condition

“SHOWLAUNCHPROGRAM=”-1″ And PROGRAMFILETOLAUNCHATEND <> “” And NOT Installed And NOT ISENABLEDWUSFINISHDIALOG

This allows all of the fields to show on the dialog that you are working with. 

Step 2:

Alter the wording on the Text fields to your requirements.  Then reshift the TOP and LEFT values so that it lines up on the screen.  The original locations tend to bunch up near the top screen.  Suggestion – if you have a massive installation project, you won’t be able to view the changes easily – I used a “testbed” project with no files to get the look and feel of the dialog to my likeing before I injected the changes into the final project.

Step 3:

Add the properties that control the visibility of the new fields into the Property Manager.  These are:

IE_EXPLORER_PATH   (no value needed for this one)

LAUNCHPROGRAM=”1″
SHOWLAUNCHPROGRAM=”-1″
PROGRAMFILETOLAUNCHATEND=”-1″

Note that the last two properties have “-1″ – this matches up with the Launch Conditions.

Step 4:

Now create the new InstallShield Custom Action that will be triggered by the checkbox.  I named my Custom Action “ISI_LaunchURL” and when using the Custom Action Wizard, it was a “New EXE” that had a “Path in Property Value”.  Since its execution is from a DOACTION, there is no sequencing required.  Since you want the installation to finish while the URL is being launched, specify for the Return Processing property – Asynchronous (Don’t wait for completion).  The property that holds the path is “IE_EXPLORER_PATH” and will be created next via a System Search function.  The command line will be something like this:

[WEB_ADDRESS]/Docs/Help.aspx#ServiceInstallation

Now, the [WEB_ADDRESS] is a MSI Property that comes across within one of the Dialogs - the customer had entered that value, so I know that the value contains Http://www.XXXX.com – if the format was not correct, then I would need to append/prepend the required values.  Warning:  Be aware that if the customer enters a space at the end of the  WEB_ADDRESS field, then that space would be incorrectly carried forward to this URL – so you may need to edit the field after the entry was made in the dialog.

Step 5:

Now create the new System Search entry.  Use the Wizard and choose “Registry – File Path as specified by a reg entry”  On the next screen, enter “HKEY_LOCAL_MACHINE” for the Registry Root entry and enter “SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\IEXPLORE.EXE” and leave the remaining fields blank.  On the MSI Property, enter “IE_EXPLORER_PATH”.  This System Search will kick off at the very beginning of the install and will retrieve the path entry of the Internet explorer and put the value in the MSI Property “IE_EXPLORER_PATH”, which should be like this “C:\Program Files\Internet Explorer\IEXPLORE.EXE”

Step 6:

Now we need to modify the dialog “SetupCompleteSuccess” and have it launch the web page URL when the button is checked.  Navigate to the dialog, and select the dialog’s “Behavior” section.  Find the OK button and enter the following condition:  DOACTION as the Event, then select from the Argument dropdown  ”ISI_LAUNCHURL” and finally put in the condition  LAUNCHPROGRAM=”1″

Now you must move that Event up to be in front of the EndDialog EXIT event! 

Step 7:

Now Test / evaluate your finished work.  Note that when the final dialog is displayed, the checkbox will automatically be checked.  This is because the MSI Property was present within the Property Manager.  You had to put it there to be able to reference it within the above steps.  If you now remove it from the Property Manager, the default action is that the box is unchecked.  When testing, you can check the box, hit FINISH button and the URL should be launched.

Regards

ShieldMaster

 

Older Posts »

Theme: Silver is the New Black. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.