Click here to Skip to main content
Click here to Skip to main content

Invoke another MSI from an MSI

By , 4 Mar 2009
 

Introduction

I was looking for a way to solve the problem of Windows’ concurrent (nested) installations as described in the URL: http://msdn.microsoft.com/en-us/library/aa368010(VS.85).aspx. My goal is to wrap an MSI based InstallShield EXE or MSI within the Visual Studio Windows Installer Project. I was able to find some useful tips online, and I have converged the information and found a solution described below. I also found Arnaldo Sandoval's "Installer Class and Custom Actions" article very helpful (URL: http://www.devcity.net/Articles/339/1/article.aspx).

How it works

I created two projects in the solution:

  • InstallerHelper – A console application project with C# code to enable code based custom actions.
  • MsiInstaller – A Windows installer project that creates the MSI.

First, for the InstallerHelper project, I created two simple classes:

  • InstallerClass - This installer class overrides the base installer class to provide additional functionality for Custom Actions.
  • InstallerHelper - This helper class is used to invoke the MSI based InstallShield EXE or MSI.

In general, the InstallerClass class calls the InstallerHelper class to invoke the MSI based InstallShield EXE or MSI. Here is what I have achieved in my MSI installer demo:

MsiDemo

Next, for the MsiInstaller project, I added to the File System both the output from the InstallerHelper project, and the MSI based InstallShield EXE or MSI to be installed on the target machine. I found that you can actually drag and drop multiple dependency files and folders to the File System view.

VS001

I added the primary output InstallerHelper as the Custom Actions for all.

VS002

This achieves the goal of invoking an MSI within a Visual Studio Windows Installer Project. When I run the MSI, it will first install the MSI based InstallShield EXE or MSI, but not executing it. Then, it runs the InstallerHelper which kicks-off the EXE or MSI.

Tips

A tip I found is that if the imported MSI based InstallShield EXE or MSI already contains Custom Actions, which is very common, then when you add the EXE or MSI to the Visual Studio Windows Installer Project, the Custom Actions is carried over to the Windows Installer Project. This gives the undesirable result of concurrent installation because some of the Custom Actions from the embedded MSI are invoked while the wrapper MSI is running. A simple solution is to use Orca.exe, select the CustomAction, and delete the ones that are being imported form the embedded EXE or MSI install process.

History

  • Feb 2009 - first release.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

A. Kwan
Systems Engineer
Canada Canada
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
SuggestionIf the main objective is just to call a second *.msi than...membernetxsk11 Jan '13 - 3:37 
In the InstallerHelper.cs you can only have the Main method, like this:
using System;
using System.Diagnostics;
using System.IO;
 
//-----------------------------------------------------------------------------

namespace InstallerHelper
{
    static class InstallerHelper
    {
        static void Main(string[] args)
        {
 
        }
    }
}
 
//-----------------------------------------------------------------------------
 
and in the InstallerClass.cs you call:
...
protected override void OnCommitted(IDictionary savedState)
{
    base.OnCommitted(savedState);
 
    Process installerHelperProcess = new Process();
 
    installerHelperProcess.StartInfo.UseShellExecute = <bool>;
    installerHelperProcess.StartInfo.CreateNoWindow  = <bool>;
    installerHelperProcess.StartInfo.WorkingDirectory = <Path to the second msi>;
    installerHelperProcess.StartInfo.FileName         = <msi file name and extension>;
    installerHelperProcess.StartInfo.Arguments        = <arguments for /passive or /quiet and other params>;
 
    installerHelperProcess.StartInfo.WindowStyle = <ProcessWindowStyle>;
 
    installerHelperProcess.Start();
}
...
 
You will continue to your primary.msi while the other is intalling in the background.
GeneralRe: If the main objective is just to call a second *.msi than...memberMember 961819220 Mar '13 - 2:03 
Not worked
GeneralRe: If the main objective is just to call a second *.msi than...membernetxsk26 Apr '13 - 2:43 
Well, with that extensive explanation i can only reply:
 
It worked for me. Smile | :)
SuggestionYou can also do to the same thing by using Visual Studio Custom Prerequisitesmemberkensurferca13 Dec '11 - 14:07 
Here is the 2008 link, you can change the version to the Visual Studio release you are using.
 
http://msdn.microsoft.com/en-us/library/ms165429(v=VS.90).aspx
kensurferca

GeneralUsing predefined installation path in nested installermembertonyt2 Dec '09 - 5:52 
Hi, and thanks for this excellent example.
 
I'm wrangling with a similar problem right now, that involves two .MSI installations, where one is run by the user, that must launche a second .MSI to install some common files in the same location where the user chose to install the application.
 
The problem I've come across is that I cannot find any simple way to launch the second MSI and have it install to the location selected by the user as the application folder in the first installer.
 
So, user runs 'Primary.msi' which allows them to select the application folder, and then installs all files including the 'Secondary.MSI' to that folder. Then, I must launch 'Secondary.MSI' from the Primary.msi via a custom action, and have it install to the same folder (the application files folder selected by the user).
 
What I can't find any documentation on, is how to specify the destination folder as a parameter to the second .MSI file, which has no UI and runs silently.
 
Any tips or pointers appreciated.
GeneralRe: Using predefined installation path in nested installermembernetxsk11 Jan '13 - 3:17 
In some cases like (Pervasive.msi) you have a "ptksetup.ini" associated.
In that *.ini you'll find something like this:
    [PROPERTIES]
    ...
    ;-----------------------------------------------------------------------------------
    ; *** Destination Folder *** Custom Setup Only ***
    ;-----------------------------------------------------------------------------------
    ;
    ; *** Destination folder ***
    ;    KEY: sets the Destination Folder dialog display
    ; VALUES: 0 = displays the Destination Folder dialog
    ;         1 = hides the Destination Folder dialog and uses default destination paths
    ;             unless paths specified by the Directory Locations keys described below
    PVSW_PSQL_SKIP_INSTALLDIR=1
    ;
    ;-----------------------------------------------------------------------------------
    ; *** Directory Locations ***
    ;-----------------------------------------------------------------------------------
    ;
    ; *** Application data files ***
    ;   KEY: target directory for installing PSQL data (user modifiable) files
    ; VALUE: the fully qualified path for installing  PSQL data files
    ; MAXIMUM LENGTH: 204 characters
    ;  NOTE: DO NOT enter a path length greater than the MAXIMUM LENGTH specified above.
    PVSW_PSQL_DATADIR=[CommonAppDataFolder]Pervasive Software\PSQL\
    ...
 
In this *.ini that some installers have you can set the path to where your second *.msi will install.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130516.1 | Last Updated 4 Mar 2009
Article Copyright 2009 by A. Kwan
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid