Thursday, November 20, 2014

Check PostgreSQL version on the machine

Hi All,
Please use the reference from the below custom action I have created for checking the PostgreSQL version on your machine.

function CheckPostgresSQLVersion(hMSI)
STRING ProcessName, szLine, Text,svReturnLine;
NUMBER nvFileHandle, ExitCode,nvResult,nvLineNumber,nLoc;
begin
ProcessName = "CheckPostgresSQLVersion";
OpenFileMode (FILE_MODE_APPEND);
if (CreateFile (nvFileHandle, SUPPORTDIR, "PostgresSQLVersion.bat") = 0) then
szLine = "psql --version";
WriteLine(nvFileHandle, szLine);
endif;

// Close the file.
CloseFile (nvFileHandle);

ExitCode = RunApplication(hMSI, SUPPORTDIR^"PostgresSQLVersion.bat", " >PostgresSQLVersion.txt", "");
if (ExitCode = 0) then
GetFullErrorText(hMSI, 60, SUPPORTDIR, "PostgresSQLVersion.txt", Text);
nvResult = FileGrep (SUPPORTDIR ^ "PostgresSQLVersion.txt", "psql (PostgreSQL)", svReturnLine,nvLineNumber, RESTART);
if(nvResult = 0) then
nLoc = StrFind(svReturnLine,"9.1");

if(nLoc<0 p="" then=""> MsiSetProperty(hMSI, "INVALID_POSTGRESQL_VERSION", "1");
MessageBox("Invalid version of PostgreSQL",SEVERE);
else
MsiSetProperty(hMSI, "INVALID_POSTGRESQL_VERSION", "0");
endif;
endif;
endif;
DeleteFile(SUPPORTDIR^"PostgresSQLVersion.bat");
end;

Tuesday, April 15, 2014

Aborting from a basic msi project using custom Action

To abort in a basic msi project through a custom action, one needs to return ERROR_INSTALL_FAILURE in the installer code.

The custom actions which gets executed successfully should return the value ERROR_SUCCESS.

Tuesday, March 25, 2014

Remove temporary records in msi database (vbscript)

Set viewlist = Database.OpenView("SELECT * FROM `ComboBox` WHERE `Property`='DEFAULT_ENGINE'")
viewlist.Execute

Set reclist = viewlist.Fetch

' delete any existing LISTBOXPROP records
While Not (reclist Is Nothing)
    viewlist.Modify 6, reclist ' 6 = delete
    Set reclist = viewlist.Fetch
Wend

viewlist.Close

Populating combobox at runtime in basic msi project

////////////////////////////////////////////////////////////////
//
// Function: PopulateDefaultEngineslist
//
//  Purpose:  Populates engines list combobox for selection to be default.
//
//
////////////////////////////////////////////////////////////////
prototype PopulateDefaultEngineslist(HWND,STRING,STRING,STRING);
function PopulateDefaultEngineslist(hMSI,SelectCM,SelectCPE,SelectUE)
HWND hDB, hView,hPropView,hPropRecord, hRecord;
LIST listID;
NUMBER nResult, nCounter;
STRING svListString, szTmp,szFirstItem;
begin
hDB = MsiGetActiveDatabase(hMSI);
MsiDatabaseOpenView(hDB,"SELECT * FROM ComboBox", hView);
    // Create an empty string list.

    listID = ListCreate (STRINGLIST);
    // If an error occurred, report it; then terminate.
    if (listID = LIST_NULL) then
        MessageBox ("Unable to create list.", SEVERE);
        abort;
    endif;

if (ListAddString (listID, "Select Engine", AFTER) < 0) then
MessageBox ("ListAddString failed.", INFORMATION);
endif;

    // Add a string to the list. This string becomes the current element.
if ( SelectCM = "true" ) then
if (ListAddString (listID, "CM", AFTER) < 0) then
MessageBox ("ListAddString failed.", INFORMATION);
endif;

if(szFirstItem == "") then
szFirstItem = "CM";
endif;
endif;

if ( SelectCPE = "true" ) then
if (ListAddString (listID, "CPE", AFTER) < 0) then
MessageBox ("ListAddString failed.", INFORMATION);
endif;

if(szFirstItem == "") then
szFirstItem = "CPE";
endif;
endif;

    // Add a third string; insert it before the current element.
if ( SelectUE = "true" ) then
if (ListAddString (listID, "UE", AFTER) < 0) then
MessageBox ("ListAddString failed.", INFORMATION);
endif;

if(szFirstItem == "") then
szFirstItem = "UE";
endif;
endif;

    // Retrieve and display the current element.

    //ListCurrentString (listID, svString);

nResult = ListGetFirstString (listID, svListString);

while (nResult != END_OF_LIST)
hRecord = MsiCreateRecord(4);
NumToStr(szTmp,nCounter);
MsiRecordSetString(hRecord, 1, "DEFAULT_ENGINE");// Column 1 PROPERTY
MsiRecordSetInteger(hRecord, 2, nCounter); // Column2: Display order of the item
MsiRecordSetString(hRecord, 3, svListString); // Column3: Value to set property to
MsiRecordSetString(hRecord, 4, svListString); // Column4: Display text for item
MsiViewModify(hView, MSIMODIFY_INSERT_TEMPORARY, hRecord);
nCounter=nCounter+1;
nResult = ListGetNextString (listID, svListString);
endwhile;
MsiCloseHandle(hRecord);

MsiViewClose(hView);
MsiCloseHandle(hView);
MsiCloseHandle(hDB);

    // Remove the list from memory.

    ListDestroy (listID);


end;


-----------------------

Thursday, October 17, 2013

Can't open include file Setup.inx

Hi,
This error mostly appears when you had moved the Installshield projects from one machine to another. It may happen that Installshield directory path may be different on machines. You may need to update the path in the "Path Variables" in the Installshield IDE.


Tuesday, December 18, 2012

Writing custom strings to MSI Log File

Its a general practise to create a log file for troubleshooting installation related issues. By default installshield writes log file but it does not contain the logs related to our own created custom actions. We could write our own strings to the msi file by using SprintfMsiLog. 

For this we need to declare the prototype and defintion of our installscript code as below:

Custom action name: LoggingCustomAction

Code:
#include "ifx.h"
//prototype
export prototype LoggingCustomAction(HWND);

//custom action definition
function LoggingCustomAction(hLogInstall)
begin
    SprintfMsiLog("Writing Custom Log...");
    //return success to MSI
    return ERROR_SUCCESS;
end;


In order to be called, the custom action must be scheduled in the sequences. For this example, open the Custom Actions view and create an immediate-mode InstallScript custom action called callLoggingTest that calls the LoggingTestInstallScript function, and schedule it to run after LaunchConditions.

After building the package and running it with the /L*v switch, you should see a line similar to the following in the log file:
InstallShield 25:00:00: Invoking script function LoggingTestInstallScript
1: Calling LoggingTestInstallScript...

Wednesday, June 20, 2012

Change text in the Title bar of Installshield dialogs

IFX_SETUP_TITLE

This system variable contians the value to be displayed in the title bar of all the built-in dialogs (except dialogs generated directly by Windows API function calls) and all message boxes generated by the MessageBox function.

This system variable is automatically initialized to the value of the string entry TITLE_CAPTIONBAR, if that entry exists; if that entry does not exist, IFX_SETUP_TITLE is initialized with the following internal code:

Sprintf( IFX_SETUP_TITLE, SdLoadString( IDS_IFX_FORMAT_SETUP_TITLE ), IFX_PRODUCT_DISPLAY_NAME );

Changing the value of IFX_SETUP_TITLE automatically resets the title of all dialogs displayed by the setup.

Monday, May 28, 2012

Stop running processes

Hi,
Below is the code I had developed in C# for stopping the running processes on a user machine. This will be helpful while installing certain custom applications from installer.

 Process[] myProcesses;
// Returns array containing all instances of Notepad.
myProcesses = Process.GetProcessesByName("Notepad");
foreach(Process myProcess in myProcesses){
    myProcess.CloseMainWindow();

Thursday, March 1, 2012


Basics of MSI Log File


An MSI log file is a text file that provides a great deal of information about an installation program during a given run on a particular system, including:

  •  Final property values
  •  Startup information for actions
  •  Status, warning, and error messages


There are several ways to create an MSI log file, including:

1. Use the /L switch to msiexec.exe, as in this command:
msiexec /i product.msi /L*v Custom.log
The characters "*v" after the /L switch indicate to perform verbose logging of every
action taken by Windows Installer. The MSI help library describes the other switches
you can use to limit the information contained in a log file.

If your release settings include creation of a setup.exe launcher, you can use the MSI Command Line Arguments setting in the release properties to pass in the /L switch to msiexec.exe, with a value such as this:
/L*v "%TEMP%\everything.log"

Note that you cannot use MSI properties in the log-file path, as properties will not be
available until after the installation has initialized. The command above relies on the
command processor expanding the %TEMP% environment variable.

2. With MSI 4.0 on Windows Vista, you can set the MsiLogging property to a string
containing the logging flags you want to use. With InstallShield 2008, you can set this using the Create MSI Logs setting in the Product Properties view. The path to the log file will be stored in the MsiLogFileLocation property. 

Tuesday, February 21, 2012

Friday, January 20, 2012

Silently uninstalling previous version of product

Syntax:

1)   msiexec /x {PRODUCT_ID}

2)   msiexec.exe /i { PRODUCT_ID } /qn REMOVE=ALL

Commands helpful in accessing IIS 7.0

AppCmd.exe is a command which can be very helpful in accessing various types of information from IIS 7.0.

This exe resides in SYSTEM32\INETSRV directory on a local machine.

Some commands are:


appcmd list site "Default Web Site" /xml | appcmd list app /in /xml | appcmd list apppool /in /xml | appcmd recycle apppool /in
appcmd list app /site.name:"Default Web Site" /xml | appcmd list apppool /in /xml | appcmd recycle apppool /in


I will describe the purpose of these commands soon...

Tuesday, June 21, 2011

Removing the Installshield Brand from the dialogs in Basic MSI type projects

Hello Friends, yesterday my client told me to remove all the Installshield Brand text at the left bottom of all dialogs. At first glance, it seems simple, as to just click and remove the Installshield text. But when I tried it, then it was really shocking to notice that the text I want to remove is disabled. Neither the line is enabled.

It was a real headache. Nowhere in the installshield help, nor in many forums, I failed to find any solution. This task was easy to do in Installscript MSI type projects, as there you are having that line and Installshield brand as a control, which you could delete from the control table.

Well, today I got a solution, which will hide Installshield brand, and the line adjoining it.

We will look one by one in different types of projects.

Installscript MSI:
In Installscript MSI type projects, first edit the dialog in which you want to Remove the Installshsield branding as shown below:

Then, goto Control table in Direct Editor, and remove the entry for ContorlId_7 as shown below:

Then make the width of the line same as the width of the dialog as shown below:

After editing the left coordinates and the width of the line, the design time preview should be like:

Basic MSI:
A Basic MSI dialog will look by default as:

Now we need a final dialog like: 

Now the question of concern is how could we achieve it. At first, it all seems to be as simple as selecting and deleting the control, but its not so similar to the steps performed in Installscript MSI project. Here we need to edit the "Control" table in Direct Editor.
By default values for Branding1 and Branding2 controls are shown below:

We need to edit attributes value for Branding1 from 3 to 2 and value for Branding2 from 65537 to 65536 as shown below:
Now, if you test the installer dialog then it will look like:


Now to put he line from left, we need to create a line control from the Installshield IDE controls toolbar as shown below:













Specify the left coordinates for the line control to 0 and width equal to that of dialog.

Finally the dialog will look like:

So, this way we can remove the Installshield brand name from the dialogs. Hope this post will be very helpful to you to customize your custom dialogs.

Tuesday, June 7, 2011

How to prevent application to show in ADD REMOVE Panel

In some cases, we need to hide the appearance of our product in Add or Remove Programs. 


Basic Msi Projects:
For Basic Msi Projects, we have a property named "ARPSYSTEMCOMPONENT". By setting this Windows Installer Property to 1 in the Property Manager, we could achieve this task. By setting this property, we simply suppress the display of our product in Add or Remove Programs. An end user can still remove our product by running the installation in maintenance mode or from the command line. 


Installscript Msi Projects:
To prevent our product from appearing in the Add or Remove Programs, select Yes for the Hide Add/Remove Panel Entry setting in the Releases view. 

Thursday, June 2, 2011

Running patch using admin execution level

Hi, I got a lot of appreciation for creating installer for my current project. After that project I was involved in some different projects. Almost after an year when I was shifted again to my last year installer project, at first glance it looks like to be little uncomfortable, to look into what modifications have been done in last one year.

Above all that I was told to create Patch installer. Ufff... again a lot of R&D's as I was working for the first time on a patch installer project. Well again I came out through with flying colours, as the patch installer was appreciated by the client.

But one concern was raised, that when we execute the full installer directly by just clicking it, it runs by using "Admin Execution Level", as it was done by using a setting in the installer project as shown in the screenshot below.







But there was not such setting when we look into Patch installer properties. I was told to look into how to execute Patch as an Administrator without using right click and selecting "Run as admin".

Well I find a solution after doing a lot of R&D. There is a tool named isremane.exe. This tool can be find at link http://support.installshield.com/kb/...isremanexe.zip


Open a command prompt window and run the following command:
isreman.exe /manifest:"C:\PathToNewManifest\setup.exe.manifest" "C:\PathToSetup\setup.exe"

for C:\PathToNewManifest\setup.exe.manifest use the file...
C:\program Files\InstallShield\2009\support\SetupExe.Admin.manifest

That should do it.


Saturday, May 14, 2011

Check and get list of existing AppPools and Websites on a machine for IIS 7.0


I have been using Installshield for so long, but tasks related to IIS 7.0 found to be most amazing, as it make me learn about IIS quite a lot. I got introduced with AppCmd.exe which is a single command line tool for managing IIS 7. AppCmd enables us to easily control the server without using a graphical administration tool and to quickly automate server management tasks without writing code.

Some of the things you can do with AppCmd:

  1. Create and configure sites, apps, application pools, and virtual directories
  2. Start and stop sites, and recycle application pools
  3. List running worker processes, and examine currently executing requests
  4. Search, manipulate, export, and import IIS and ASP.NET configuration

I had a requirement in one of my web project, for showing users a list of available App Pools and Web-sites for selection. Using vb-script found to be little uncomfortable, but AppCmd.exe makes my life easy.

Note: AppCmd.exe is located in the %systemroot%\system32\inetsrv\ directory. Because it is not path of the PATH automatically, you need to use the full path to the executable when executing commands like in "%systemroot%\system32\inetsrv\AppCmd.exe list sites". Alternatively, you can manually add the inetsrv directory to the path on your machine so that you can access AppCmd.exe directly from any location.

List of App Pools can be get by using command: "AppCmd.exe list apppool".







Similarly we can get the list of available websites: "AppCmd.exe list site".

We can take the output of the above commands in a text file, and can read the AppPool list. Similary we can do for Website.

Wednesday, May 11, 2011

Check existence of any program installed on a machine through registry

Hi, reading this post? It means you are really looking for how to check for existence of MS Office or any other program via script, or through registry. There are some standard locations in the registry editor, where you could manually search for existence of some program installed on the local machine. But not everyone is comfortable with it. Also, there are chances of any accidental deletion of any wrong key, if done by some immature user.

But when it comes to script, and especially from checking within the installer, then we had some options:

  1. System Search View: The system search view provides the Windows Installer capability to search for a particular file, folder, registry key, .ini file, or .xml file value on an end user's sytem prior to installation. this view is location in the left pane of the Installshield IDE, as shown in the image below:



    When you do right-click in the right pane as shown in the image below, a system Search Wizard opens which guides you to specify your search options for any Files, Folders, Registry Entries, and so on...




    You can specify your options according to your requirement.

  2. Installscirpt Code: Another option we have is through installscipt code. We need to specify a key to search in registry. There are some in-built installscript functions which can help you in accessing registry details. One of such function of our use at the moment is RegDBKeyExist(szKeyRoot) which checks for the key in the registr yspecified by parameter szKeyRoot.

    A typical example for your best understanding is given below which could check for existence of MS Office on the target machine.

         szKeyRoot="SOFTWARE\Wow6432Node\Microsoft\Office\Word\\";  \\key to search in registry 
        // get the registry value
        nResult = RegDBSetDefaultRoot( HKEY_LOCAL_MACHINE );
        if (RegDBKeyExist (szKeyRoot) < 0) then 
             return FALSE;
       else
             return TRUE;
       endif;

    Hope the above content will be helpful to you. In case you have some query, then please feel free to put some comments on this post, or reply to me.

Checking whether IIS 7.0 exist on a machine

Hi, This article will help to check if IIS 7.0 or lower version is installed on the target machine. There are several ways to check, both manually and through custom code by searching in registry.

  1. Go To Start -->  Run. Type inetmgr and press OK. If you get an IIS configuration screen, it is installed, otherwise it isn't.
  2. You can also check ControlPanel->Add Remove Programs, Click Add Remove Windows Components and look for IIS in the list of installed components.
To Reinstall IIS.

Control Pane -> Add Remove Programs -> Click Add Remove Windows Components Uncheck IIS box Click next and follow prompts to UnInstall IIS. Insert your windows disc into the appropriate drive. Control Pane -> Add Remove Programs -> Click Add Remove Windows Components Check IIS box Click next and follow prompts to Install IIS.

There are such situations in which you need to check IIS existence from the installshield using code, then you need to search for its registry on the target machine. For a helping deed, I am presenting an example below:


szKeyRoot="SOFTWARE\\Microsoft\\InetStp\\Components\\";     //key to search in registry
// Set the Default root
nResult = RegDBSetDefaultRoot( HKEY_LOCAL_MACHINE );
    
if (RegDBKeyExist (szKeyRoot) < 0) then 
  return FALSE;
else
    return TRUE;
endif;


The return value will determine whether IIS 7.0 exist or not.

MsiDoAction

MsiDoAction is used in Basic Msi type projects, where we are not having events like OnFirstUiBefore like we have in Installscript based projects. To call a custom action, we need to use this function.


The MsiDoAction function executes a built-in action, custom action, or user-interface wizard action.
Syntax
UINT MsiDoAction(
  __in  MSIHANDLE hInstall,
  __in  LPCTSTR szAction
);
Parameters:
hInstall [in]
Handle to the installation provided to a DLL custom action or obtained through MsiOpenPackage, MsiOpenPackageEx, or MsiOpenProduct.

szAction [in]
Specifies the action to execute.

Return Value:
ERROR_FUNCTION_FAILED
The function failed.

ERROR_FUNCTION_NOT_CALLED
The action was not found.

ERROR_INSTALL_FAILURE
The action failed.

ERROR_INSTALL_SUSPEND
The user suspended the installation.

ERROR_INSTALL_USEREXIT
The user canceled the action.

ERROR_INVALID_DATA
A failure occurred while calling the custom action.

ERROR_INVALID_HANDLE
An invalid or inactive handle was supplied.

ERROR_INVALID_HANDLE_STATE
The handle state was invalid.

ERROR_INVALID_PARAMETER
An invalid parameter was passed to the function.

ERROR_MORE_DATA
The action indicates that the remaining actions should be skipped.

ERROR_SUCCESS
The function succeeded.

The MsiDoAction function executes the action that corresponds to the name supplied. If the name is not recognized by the installer as a built-in action or as a custom action in the CustomAction table, the name is passed to the user-interface handler object, which can invoke a function or a dialog box. If a null action name is supplied, the installer uses the upper-case value of the ACTION property as the action to perform. If no property value is defined, the default action is performed, defined as "INSTALL".

Actions that update the system, such as the InstallFiles and WriteRegistryValues actions, cannot be run by calling MsiDoAction. The exception to this rule is if MsiDoAction is called from a custom action that is scheduled in the InstallExecuteSequence table between the InstallInitialize and InstallFinalize actions. Actions that do not update the system, such as AppSearch or CostInitialize, can be called.

Deffered Custom Actions

Deferred Execution Custom Actions:
Deferred custom action's purpose is to delay the execution of a system change to the time when the installation script is executed. This differs from a regular custom action, or a standard action, in which the installer executes the action immediately upon encountering it in a sequence table or in a call to MsiDoAction.

The installer does not execute a deferred execution custom action at the time the installation sequence is processed. Instead the installer writes the custom action into the installation script. The only mode parameter the installer sets in this case is MSIRUNMODE_SCHEDULED. See MsiGetMode for a description of the run mode parameters.

A deferred execution custom action must be scheduled in the execute sequence table within the section that performs script generation. Deferred execution custom actions must come after InstallInitialize and come before InstallFinalize in the action sequence.

Custom actions that set properties, feature states, component states, or target directories, or that schedule system operations by inserting rows into sequence tables, can in many cases use immediate execution safely. However, custom actions that change the system directly, or call another system service, must be deferred to the time when the installation script is executed.

Because the installation script can be executed outside of the installation session in which it was written, the session may no longer exist during execution of the installation script. This means that the original session handle and property data set during the installation sequence is not available to a deferred execution custom action.