cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
UNeverNo
Level 6

Determine if a msi was installed successfully

I'm installing a couple of msi-files with an own Installscript setup.exe. I now need to know if one of these failed, so I can skip installing the next ones.

But unfortunately the LaunchAppAndWait return value could not be used to determine that.
Is there another way to achieve it?
Labels (1)
0 Kudos
(3) Replies
Jeff2008
Level 6

To detect if a msi is installed (or if it installed correctly), you can check under HKLM\Software\Microsoft\Windows\CurrentVersion for a key with the product code name. If you don't know the product code of the msi, you can open the msi file with a program like Orca and find it in the property table.
0 Kudos
gripper4hire
Level 3

I'll assume you are doing this from an Installscript only project.

Instead of using "LaunchAppAndWait", use the MSI API "MsiInstallProduct" and check for the return value.

Here is a snippet of code that I use to install MSI files silently from an Installscript only project. I stripped out some proprietory stuff, so I didn't check if it'll compile, but you are free to give it a try.

The key concept is to reinclude the MSI APIs that are not included in "Installscript only" projects, and call the MSI APIs directly. This, of course, won't work from an Installscript MSI project.

[CODE]
//#defines and prototypes needed to call MSI APIs from Installscript//
#ifndef INSTALLUILEVEL_NONE
#define INSTALLUILEVEL_NONE 2 // completely silent installation
#endif

#ifndef ERROR_SUCCESS
#define ERROR_SUCCESS 0
#endif

#ifndef MsiSetInternalUI
prototype LONG MSI.MsiSetInternalUI(BYVAL LONG, POINTER);
#endif

#ifndef MsiOpenPackageExA
prototype INT MSI.MsiOpenPackageExA(BYVAL STRING, BYVAL LONG, POINTER);
#endif

#ifndef MsiOpenProductA
prototype INT MSI.MsiOpenProductA(BYVAL STRING, POINTER);
#endif

#ifndef MsiGetPropertyA
prototype INT MSI.MsiGetPropertyA(HWND, byval string, byref string, byref int);
#endif

#ifndef MsiCloseHandle
prototype INT MSI.MsiCloseHandle(HWND);
#endif

#ifndef MsiInstallProductA
prototype INT MSI.MsiInstallProductA(BYVAL STRING, BYVAL STRING);
#endif



//function to install MSI package from installscript installation
//strMSIPackage = full path to msi
//strCommandLine = properties to pass. Do not include any msiexec params for logging, silent, etc. If you want to use these params, you'll have to call the appropriate MSI APIs prior to MsiInstallProductA
function BOOL InstallPackage(strMSIPackage,strCommandLine)
HWND hwndInstallWindow;
HWND hPackage, hProduct;
LONG dwOptions;
LONG dwBuff;
STRING svProductCode[MAX_PATH];
STRING svProductVersion[MAX_PATH];
STRING svPackageVersion[MAX_PATH];
BOOL bRet;
INT nResult;
begin

bRet = TRUE;

if (UseDLL (WINSYSDIR ^ "msi.dll") == 0) then

hwndInstallWindow = FindWindow( "#32770", IFX_SETUP_TITLE );

//Enable silent and suppress "Microsoft Installer is configuring..." dialog
if ( hwndInstallWindow ) then
MSI.MsiSetInternalUI(INSTALLUILEVEL_NONE,&hwndInstallWindow);
else
hwndInstallWindow = 0;
MSI.MsiSetInternalUI(INSTALLUILEVEL_NONE,&hwndInstallWindow);
endif;

//find if the package exists
if (Is (FILE_EXISTS,
strMSIPackage) != TRUE) then
bRet = FALSE;
endif;

if (bRet == TRUE) then

dwOptions = 1;

//Open the package to get productcode and version
if (MSI.MsiOpenPackageExA(strMSIPackage,dwOptions,&hPackage) != ERROR_SUCCESS) then
bRet = FALSE;
endif;

if (bRet == TRUE) then
dwBuff = SizeOf (svProductCode);
if (MSI.MsiGetPropertyA(hPackage,"ProductCode",svProductCode,dwBuff) != ERROR_SUCCESS) then
bRet = FALSE;
endif;
endif;

if (bRet == TRUE) then
dwBuff = SizeOf (svPackageVersion);
if (MSI.MsiGetPropertyA(hPackage,"ProductVersion",svPackageVersion,dwBuff) != ERROR_SUCCESS) then
bRet = FALSE;
endif;
endif;

MSI.MsiCloseHandle (hPackage);

endif;

if (bRet == TRUE) then

nResult = -1;

//Find if product already installed, to use correct install mode.
if (MSI.MsiOpenProductA(svProductCode,&hProduct) == ERROR_SUCCESS) then
//Product is installed...

dwBuff = SizeOf (svProductVersion);

if (MSI.MsiGetPropertyA(hProduct,"ProductVersion",svProductVersion,dwBuff) != ERROR_SUCCESS) then
bRet = FALSE;
endif;
MSI.MsiCloseHandle (hProduct);

if (bRet == TRUE) then
//Compare version of installed product, with the one trying to install.
//Only install is package is same or newer version
//Also, remove the ".0" if you use four field version numbers in your MSIs.
if (VerCompare (svProductVersion + ".0",svPackageVersion + ".0",VERSION) != 0) then
//Package is LESSTHEN or EQUAL to installed version, so reinstall it.
nResult = MSI.MsiInstallProductA(strMSIPackage, strCommandLine + " REINSTALL=ALL REINSTALLMODE=vomus");
endif;

endif;

//Product not found installed, so install it
else

nResult = MSI.MsiInstallProductA(strMSIPackage, strCommandLine);

endif;

if (nResult != ERROR_SUCCESS) then
//Error. nResult is the MSI Error Code, or -1 if a newer version of product is installed.
bRet = FALSE;
endif;

endif;

else
//Error, cannot open the MSI.DLL
bRet = FALSE;
endif;

return bRet;

end;
[/CODE]
0 Kudos
KathyMorey
Level 10

Another option is to use LaunchAppAndWait and check the LAAW_PARAMETERS.nLaunchResult for the MSI return code.
0 Kudos