This website uses cookies. By clicking Accept, you consent to the use of cookies. Click Here to learn more about how we use cookies.
Turn on suggestions
Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.
- Revenera Community
- :
- InstallShield
- :
- InstallShield Forum
- :
- Re: Determine if a msi was installed successfully
Subscribe
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Subscribe
- Mute
- Printer Friendly Page
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Oct 20, 2008
10:27 AM
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?
But unfortunately the LaunchAppAndWait return value could not be used to determine that.
Is there another way to achieve it?
(3) Replies
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Oct 20, 2008
12:41 PM
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.
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Oct 20, 2008
03:51 PM
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]
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]
- Mark as New
- Subscribe
- Mute
- Permalink
- Report Inappropriate Content
‎Oct 21, 2008
07:32 AM
Another option is to use LaunchAppAndWait and check the LAAW_PARAMETERS.nLaunchResult for the MSI return code.