Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

How to create single installer package for multi CPU architecture MSI installers with SFX and HTA?

4.83/5 (8 votes)
17 Sep 2015CPOL9 min read 20.6K   334  
Explains how to create single package for multi CPU installers and run the right installer based on user machine configuration.

Single Installer Package

Introduction

Software deployment is one of the complex task in the software development world and nowadays we need to create separate installers for different CPU Architectures like 32 bit, 64 bit and Itanium, it adds more complexity to software deployment. End users often confused to choose the right one when we give different installers for the same product, so in this article we are going to see how to create single installer package for multiple CPU architecture and how to trigger the right installer based on user machine configuration.

Background

Recently, I worked in a product which needs to deploy with different CPU architecture. End user wanted a single installer for different host applications and operating systems and also we need to perform some custom operations before start installing the MSI installer. For that we found a solution with SFX and HTA, we are going see it in details with rest of this article so the reader of this article should have knowledge on how to create an archive file, HTML/HTML Applications (HTA), Java Script and VBScript. Please read the following links when you don’t have any prior knowledge on above topics.

SFX

SFX stands for Self Extractor. It is a compressed and archived executable file which decompresses and extracts the content without any archival programs.

Most of the archival programs support to create SFX files and some programs convert the archive files to SFX files.

Refer this link for more information.

HTA

HTA stands for HTML Application. It is a HTML based windows program and it supports Java Script and VB Script.

HTA structure exactly same like HTML page, additionally it will include the hta host tag which look as below,

HTML
<HTA:APPLICATION ID="oHTA"
     APPLICATIONNAME="myApp"
     BORDER="thin"
     BORDERSTYLE="normal"
     CAPTION="yes"
     ICON=""
     MAXIMIZEBUTTON="yes"
     MINIMIZEBUTTON="yes"
     SHOWINTASKBAR="no"
     SINGLEINSTANCE="no"
     SYSMENU="yes"
     VERSION="1.0"
     WINDOWSTATE="maximize"/>

This tag should place under header tag of html and rest of things are similar to HTML. We can use any one script from Jscript or VBScript or both. Here the sample hta file with script,

HTML
<html>
<head>
    <title>My First HTA Splash Screen</title>
    <style type="text/css">
        html, body
        {
            margin: 0;
            padding: 0;
            height: 100%;
        }
        body
        {
            background-color: #FFF;
            border: 0px;
            margin: 0px;
            font-family: @Calibri;
            background-color: LightGray;
        }
        #container
        {
            min-height: 100%;
            position: relative;
        }
        #header
        {
            background-color: Lime;
        }
        #body
        {
            background-color: LightGray;
            padding: 5px;
            position: relative;
        }
        #footer
        {
            background-color: Gray;
            position: absolute;
            bottom: 0;
            width: 100%;
            min-height: 60px;
        }
    </style>
</head>
<script language="javascript" type="text/javascript">
    function CloseMe() {
        //CloseWindow();
        window.close();
    }
    function ShowBrowserVersion() {
        var browser = GetBrowserInfo();
        alert(browser.name + " - " + browser.version);
    }
    function GetBrowserInfo() {
        var ua = navigator.userAgent, tem, M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
        if (/trident/i.test(M[1])) {
            tem = /\brv[ :]+(\d+)/g.exec(ua) || [];
            return { name: 'IE', version: (tem[1] || '') };
        }
        if (M[1] === 'Chrome') {
            tem = ua.match(/\bOPR\/(\d+)/)
            if (tem != null) { return { name: 'Opera', version: tem[1] }; }
        }
        M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?'];
        if ((tem = ua.match(/version\/(\d+)/i)) != null) { M.splice(1, 1, tem[1]); }
        return {
            name: M[0],
            version: M[1]
        };
    }
</script>
<hta:application id="htaSplash" applicationname="Splash Screen" scroll="No" scrollflat="no"
    caption="No" singleinstance="Yes" borderstyle="none" minimizebutton="No" maximizebutton="No"
    showintaskbar="no" innerborder="no" border="none" />
</head>
<body>
    <div id="container">
        <div id="header">
            <table width="100%">
                <tr>
                    <td align="center">
                        Header
                    </td>
                </tr>
            </table>
        </div>
        <div id="body">
            <table width="100%">
                <tr>
                    <td align="center">
                        Body
                    </td>
                </tr>
                <tr>
                    <td>
                        <a href="#" onclick="javascript:ShowBrowserVersion();">Browser Version - Javascript</a>
                    </td>
                </tr>
                <tr>
                    <td>
                        <a href="#" onclick="vbs:SayHello">Say Hello - VBscript</a>
                        <br />
                    </td>
                </tr>
                <tr>
                    <td>
                        <a href="#" onclick="javascript:CloseMe();">Close</a>
                        <br />
                    </td>
                </tr>
                <tr>
                    <td>
                        <br />
                        <br />
                        <br />
                        <br />
                        <br />
                    </td>
                </tr>
            </table>
        </div>
        <div id="footer">
            <table width="100%">
                <tr>
                    <td align="center">
                        Footer
                    </td>
                </tr>
            </table>
        </div>
    </div>
    <script language="VBScript" type="text/vbscript">
        'Resize the window
        intHeight = 250
        intWidth = 500
        Me.ResizeTo intWidth, intHeight
        'Align window to center of the screen
        Me.MoveTo (screen.width / 2) - (intWidth / 2), (screen.height / 2) - (intHeight / 2)
        Sub SayHello
        MsgBox "Hello World!"
        End Sub
        Sub CloseWindow
        window.Close
        End Sub
    </script>

Snapshot of above sample HTA markup:

Sample Output

For more information on HTA refer the following links,

Solution

After some research we found a possible solution and it is as below,

  • Archive the all installer and other required resources as a Self-extractor.
  • Create a utility to detect the installed host application versions and Operation System bit size and run this utility after self-extraction completed.
  • Utility will run the appropriate the installer based on information which gathered from the client machine.

Since HTA supports for VB Script we can achieve almost same thing what we can do with it. It also provides the user interface to show our brand, product information and install guide, etc.

Alternatively, we can use SFX and VB Script to achieve the above solution when we don’t want to show the UI after extraction.

This is not only solution we got to solve this issue, you may find some other solutions (with third party installer tools) better than this. Here, I just want to share what I have used in a product with the combination of SFX and HTA.

Now, it is the time to put all our knowledge into action.

Implementation

In order to implement the above solution we need to do the following three steps,

  1. Create MSI Installer for different CPU Architecture.
  2. Create a Splash Window.
  3. Create SFX.

Create MSI Installer

Create your product installer for different CPU Architecture. I used Visual Studio 2010 for this article sample, you may use other MSI creator programs. Here I am not going to explain how to create a MSI installer and you can refer this article when you need a reference.

Create Splash Window

Create a splash window with HTA. Here, you can design for your won taste and requirements but I designed the following splash window to demonstrate.. It includes the following functionalities,

  • Read Operating System Details.
  • Read CPU Details.
  • Read Physical Memory Details.
  • Scan for prerequisites (not implemented in this sample but you can add your own).
  • Display the above information.
  • Choose the appropriate installer based on CPU Architecture.
  • Show installer guide.

Splash Window Source:

HTML
<html>
<head>
    <title>Installer Splash</title>
    <style type="text/css">
         html, body
        {
            margin: 0;
            padding: 0;
            height: 100%;
        }
        body
        {
            background-color: #FFF;
            border: 0px;
            margin: 0px;
            font-family: @Calibri;
            background-color:LightGray;
        }
         #container
        {
            min-height: 100%;
            position: relative;
        }
        #header
        {
            background-color:Orange;
        }
        #body
        {
            background-color:LightGray;
            padding: 5px;
            position: relative;
        }
         #background
        {
           
            /*padding: 5px; */
            background: url(images/product.png) no-repeat center center;
            filter: alpha(opacity=20); /* For IE8 and earlier */
            z-index:-1;
            position: absolute;
            top: 0px;
            right: 0px;
            bottom: 0px;
            left: 0px;
            width: 100%;
            height: 100%;
        }
        #footer
        {
            background-color:Gray;
            position: absolute;
            bottom: 0;
            width: 100%;
            min-height: 60px;
        }
         .pdtitle
        {
            padding-top: 20px;
            padding-left: 10px;
            color: #fff;
            vertical-align: middle;
        }
        .copyright
        {
            color: #fff;
            font-size: x-small;
        }
        .sysinfotable
        {
            /*background-color:#f3f4f4;*/
            border: 1px solid #B5B5B5;
            font-size: smaller;
        }
        
        .inforow
        {
            height: 30px;
        }
        .bodyheader
        {
            font-size: large;
            font-weight: bold;
        }
        .infocaption
        {
            font-weight: bold;
            background-color: White;
            color: Orange;
        }
        .infovalue
        {
            padding-left: 2px;
        }
        .bottomborder
        {
            border-bottom: 1px #B5B5B5 solid;
        }
        .leftborder
        {
            border-left: 1px #B5B5B5 solid;
        }
        #installmenu a
        {
            color: #0066FF;
            font-weight: bolder;
        }
        .pageVisible
        {
            display:block;
        }
        .pageInVisible
        {
            display:none;
        }
        .loading
        {  
            padding-top:100px;
            padding-left:10px;
            font-size:30;
            color:#7C6D5A;
            font-weight:bold;
        }
        #pageLoading
        {
            width:100%;
        }
        
        
    </style>
</head>
<script language="javascript" type="text/javascript">
    function CloseMe() {
        //CloseWindow();
        window.close();
    }
    function InstallAddin() {
        Install();
    }
    function ShowBrowserVersion() {
        var browser = GetBrowserInfo();
       alert(browser.name + " - " + browser.version );
    }
    function GetBrowserInfo() {
        var ua = navigator.userAgent, tem, M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
        if (/trident/i.test(M[1])) {
            tem = /\brv[ :]+(\d+)/g.exec(ua) || [];
            return { name: 'IE', version: (tem[1] || '') };
        }
        if (M[1] === 'Chrome') {
            tem = ua.match(/\bOPR\/(\d+)/)
            if (tem != null) { return { name: 'Opera', version: tem[1] }; }
        }
        M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?'];
        if ((tem = ua.match(/version\/(\d+)/i)) != null) { M.splice(1, 1, tem[1]); }
        return {
            name: M[0],
            version: M[1]
        };
    }
   
</script>
<hta:application id="htaSplash" applicationname="Installer Splash" scroll="No" scrollflat="no" caption="No"
    singleinstance="Yes" borderstyle="none" minimizebutton="No" maximizebutton="No"
    showintaskbar="no" innerborder="no" border="none"/>
</head>
<body>
<div id="container">
   <div id="header">
        <table width="100%">
            <tr>
                <td width="75%" valign="middle">
                    <h2 class="pdtitle">Product Name V1.0</h2>
                </td>
                <td width="25%" align="center">
                   <a href="http://www.yourproductsite.com"><img src="images/pdlogo.png" height="64px" border="0" alt="Product Logo" /></a>
                </td>
            </tr>
        </table>
   </div>
   <div id="body">
        <div id="pageLoading">
            <table cellpadding="0" cellspacing="0" width="100%" height="100%" border="0">
                <tr>
                    <td class="loading" align="center">
                        Loading...
                    </td>
                </tr>
            </table>
        </div>
         <div id="pageInfo" class="pageInVisible">
            <table width="100%" border="0">
                <tr>
                    <td class="bodyheader">
                        Welcome to Product
                    </td>
                </tr>
                <tr>
                    <td style="font-size:smaller; padding-right:10px">Product introduction here
                    </td>
                </tr>
                <tr>
                    <td style="font-size:small;font-weight:bold;">
                        System/Pre-requisites Information :
                    </td>
                </tr>
                <tr>
                    <td>
                        <table width="100%" border="0">
                            <tr>
                                <td width="70%">
                                    <table width="100%" class="sysinfotable" border="0" cellpadding="0" cellspacing="0">
                                        <tr>
                                            <td  class="inforow infocaption bottomborder" align="right">
                                                Operating System :
                                            </td>
                                            <td class="inforow bottomborder infovalue leftborder" id="lblOS">
                                           
                                            </td>
                                        </tr>
                                        <tr>
                                            <td  class="inforow infocaption bottomborder " align="right">
                                                Processor :
                                            </td>
                                            <td class="inforow bottomborder infovalue leftborder altbackground" id="lblProcessor">&nbsp;
                                            </td>
                                        </tr>
                                        <tr>
                                            <td  class="inforow infocaption bottomborder" align="right">
                                                Phycial Memory :
                                            </td>
                                            <td class="inforow bottomborder infovalue leftborder" id="lblRAM">&nbsp;
                                            </td>
                                        </tr>
                                        <tr>
                                            <td  class="inforow infocaption bottomborder" align="right">
                                                 Pre-requisites 01 :
                                            </td>
                                            <td class="inforow bottomborder infovalue leftborder altbackground" id="lblReq01">
                                            </td>
                                        </tr>
                                        <tr>
                                            <td  class="inforow infocaption " align="right">
                                                 Pre-requisites 02 :
                                            </td>
                                            <td class="inforow infovalue leftborder" id="lblReq02">
                                            </td>
                                        </tr>
                                    </table>
                                </td>
                                    <td width="1%">
                                        &nbsp;
                                    </td>
                                <td width="29%">
                                    <table width="100%" cellpadding="1" cellspacing="0" id="installmenu">
                                        <tr>
                                            <td align="right">
                                                <a href="#" onclick="vbs:Install" title="Click here to install the product">Install Product</a>
                                           
                                            </td>
                                                <td>
                                                <a href="#" onclick="vbs:Install"><img src="images/setup.png" style="border:0px" width="32" height="32" alt="Click here to install the product"/></a>
                                            </td>
                                        </tr>
                                            <tr>
                                            <td align="right">
                                                <a href="#" onclick="vbs:Help" title="Click here to read the installation guide">Installer Guide</a>
                                            
                                            </td>
                                            <td>
                                                <a href="#" onclick="vbs:Help"><img src="images/Help.png" style="border:0px" width="32" height="32" alt="Click here to read the installation guide"/></a>
                                            </td>
                                        </tr>
                                        <tr>
                                            <td align="right">
                                                <a href="#" onclick="javascript:CloseMe();" title="Click here to close">Exit</a>
                                           
                                            </td>
                                            <td>
                                                <a href="#" onclick="javascript:CloseMe();" style="border:0px"><img src="images/close.png" style="border:0px" width="32" height="32" alt="Click here to close" /></a>
                                            </td>
                                        </tr>
                                    </table>
                                    </td>
                                    <td width="1%">&nbsp;
                                    </td>
                            </tr>
                        </table>
                    </td>
                </tr>
            </table>
        </div>
        <!-- replace br tags by setting dynamic hight background div tag -->
        <div id="background">&nbsp;<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /></div>
   </div>
   <div id="footer">
    <table width="100%">
        <tr>
            <td align="right">
                <div class="copyright" id="copyright"></div>
                <a class="copyright"  href="http://www.yourwebsite.com">www.yourcompanywebsite.com</a>
            </td>
        </tr>
    </table>
   </div>
</div>
<SCRIPT Language="VBScript" type="text/vbscript">
Dim osBit
Dim osName,ramSize,cpuDetails,preReq01,preReq02
intHeight = 380
intWidth = 600
'Resize the main window to specific size
Me.ResizeTo intWidth, intHeight
'Align window to center of the screen
Me.MoveTo (screen.width / 2) - (intWidth / 2), (screen.height / 2) - (intHeight / 2)

'Read current machine details like OS Name, CPU details, Physical Memory and required prerequisites
Sub ReadSystemInfo
On Error Resume Next
strComputer = "."
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
strOS="" 
Set colOperatingSystems = objWMIService.ExecQuery("Select * from Win32_OperatingSystem")
For Each objOperatingSystem in colOperatingSystems
        strOS = objOperatingSystem.Caption
    Next
osBit = 32

If Trim(strOS) <> "" Then
    'Detect the CPU architecture
    Set WshShell = CreateObject("WScript.Shell")
    OsType = WshShell.RegRead("HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\PROCESSOR_ARCHITECTURE")
    
    If OsType = "AMD64" then
        osBit = 64
    End If
End If
    osName = strOS & "," & osBit & "bit"


Set colItems = objWMIService.ExecQuery("Select * from Win32_PhysicalMemory")
For Each objItem in colItems
    TotalRam = TotalRam + objItem.Capacity / 1024 / 1024 / 1024 
Next
ramSize = TotalRam & " GB"

Set colItems = objWMIService.ExecQuery("Select * from Win32_Processor",,48)
For Each objItem in colItems
    cpuDetails = objItem.Name 
Next

preReq01 = "Installed / Not Installed"
preReq02 = "Installed / Not Installed"
Set objWMIService = Nothing
Set WshShell = Nothing
End Sub 

'Diplay the system information to user on the screen
Sub ShowSystemInfo
On Error Resume Next
lblOS.InnerHTML = osName
lblProcessor.InnerHTML = cpuDetails
lblRAM.InnerHTML = ramSize
lblReq01.InnerHTML = preReq01
lblReq02.InnerHTML = preReq02
pageInfo.ClassName  = "pageVisible"
pageLoading.ClassName = "pageInVisible"
End Sub

'Run the appropriate addin installer based on current machine CPU architecture
Sub Install
   Set objFSO = CreateObject("Scripting.FileSystemObject") 
    strFilePath = objFSO.GetAbsolutePathName(".")
   Set objShell = CreateObject("WScript.Shell")
   If osBit = 64 Then
       strFilePath = strFilePath & "\Install\ProductSetup_x64.msi"
   Else
     strFilePath = strFilePath & "\Install\ProductSetup_x86.msi"
   End if 
   objShell.Run strFilePath, 1, False
   Set objFSO = Nothing
   Set objShell = Nothing
End Sub


'Show the installation guide to user 
Sub Help
   Set objFSO = CreateObject("Scripting.FileSystemObject") 
    strFilePath = objFSO.GetAbsolutePathName(".")
   Set objShell = CreateObject("WScript.Shell")
   strFilePath = strFilePath & "\InstallerGuide.pdf"
   'MsgBox osBit
   objShell.Run strFilePath, 1, False
   Set objFSO = Nothing
   Set objShell = Nothing
End Sub

'Show the dynamic copyright year information
Sub ShowCopyRight
copyRight.InnerHTML = " © Your Company " & Year(Date)
End Sub

Sub CloseWindow
window.Close
End Sub

ReadSystemInfo
ShowSystemInfo
ShowCopyRight
</Script>

Splash Window Snapshot:

Image 3

The following code is responsible for to trigger the right installer based on user machine CPU architecture.

VBScript
'Detect the CPU architecture
    osBit = 32
    Set WshShell = CreateObject("WScript.Shell")
    OsType = WshShell.RegRead("HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\PROCESSOR_ARCHITECTURE")
    
    If OsType = "AMD64" then
        osBit = 64
    End If

'Run the appropriate addin installer based on current machine CPU architecture
Sub Install
   Set objFSO = CreateObject("Scripting.FileSystemObject") 
    strFilePath = objFSO.GetAbsolutePathName(".")
   Set objShell = CreateObject("WScript.Shell")
   If osBit = 64 Then
       strFilePath = strFilePath & "\Install\ProductSetup_x64.msi"
   Else
     strFilePath = strFilePath & "\Install\ProductSetup_x86.msi"
   End if 
   objShell.Run strFilePath, 1, False
   Set objFSO = Nothing
   Set objShell = Nothing
End Sub

Create the HTA project folder with following structure then copy MSI installers and other resources to it.

Project Folder:

  • Product Setup
    • Splash.hta
    • InstallerGuide.pdf
    • Images
      • Close.png
      • Help.png
      • Pdlogo.png
      • Product.png
      • Setup.png
    • Install
      • ProductSetup_x86.msi
      • ProductSetup_x64.msi

Make sure that everything is ready before going to next step.

Create SFX

Now we are ready to create the self-extractor package with all deployment files including installer splash file. To do that we need some special programs, we have lots of SFX creator in the market but we are going to use two open source applications to accomplish the task and those are,

  • 7 Zip File manager – which creates the archive file in .7z format.
  • 7 Zip SFX Maker – which creates the self-extractor for 7 Zip archive.

First we need to create archive file with 7 Zip file manager then we need to create self-extractor with 7 Zip SFX Maker. It required following steps to get the final output.

  1. Install the 7 Zip File Manager from here. Skip this step if you already installed it on your machine.
  2. Create 7 Zip archive file with following items,
    • Splash.hta
    • Images folder
    • Install folder
    • InstallerGuide.pdf
  3. Name the archive file whatever you want but here we going to give it as Productsetup.7z
  4. Install the 7 Zip SFX Maker from here. Skip this step if you have installed it already on your machine.
  5. Open 7 Zip SFX Maker.
    7 Zip SFX Maker
  6. 7 Zip SFX Maker contains five important tabs and those are,
    1. File tab – where we need add our 7 zip archive files.
    2. Dialog tab – it contains the configuration for UI for various state of extractor.
    3. Icon – which contains the list icons for extractor, here we can choose our icon for self-extractor exe.
    4. Tasks- where we can specifics the actions which need to perform after extraction completed and it allows the following action types,
      1. Create Shortcut
      2. Run Program
      3. Delete File or Folder
      4. Set Environment Variable
    5. Metadata – which contains the standard file attributes and here we can change their values.
  7. Go to Files tab, click on plus button to add 7 zip archive files, it will display the file open dialog.
  8. Choose the productsetup.7z from the hard disk then click on “Open” button.
  9. Now we can see the selected file added in the file list box. You can repeat the step 7 to 8 to add more files.
  10. Go to Dialogs tab and do the following things,
    1. Change the default title to your custom title and here we going to give as “Product Setup”.
    2. Choose the Overwrite mode as what you want. By default it set to “Overwrite all files”, for our example leave the default one.
    3. We can set the predefined folder or temporary folder to extract the archived files and select the extract to temporary folder option for our example.
    4. Select Use XP style when you want windows XP based UI theme and select this option for our example.
    5. Select Compress SFX stub with UPX when you want to reduce the file size, UPX provides excellent compress ratio. Select this option for our example.
    6. Select Delete SFX file after extraction when you want to remove the extractor exe and don’t select this option for our example.
    7. Select Hide Icon in Title bar of all windows when you want to hide the icon from the title bar and select this option for our example.
    8. Select Show SFX icon in Begin, Finish and Cancel Prompt when you want to show the prompt for each state of extraction and don’t select this option for our example.
    9. Go to all sub tabs and do the appropriate settings.
    10. In our example, we are interested to trigger the appropriate MSI installer based on current machine CPU architecture and operating system, so we should hide the all self extractor UIs except our HTA splash window. Go through all dialog tabs and unselect the checkbox which given in the all sub tabs (as shown in the snapshot).
      SFX Maker Dialog Tab
  11. Go to Icon tab and choose your icon from the list. When you are not happy with existing list then do the following steps to add custom icon to your self-extractor.
    1. Click on File -> Save Settings menu or “Save Settings…” button at bottom of the screen.
    2. It will display the Save File Dialog, give your name here and give it as Product.xml for our example.
    3. Go to Prodcut.xml folder and open it any xml/text editor.
    4. Go to Settings -> General -> Icon tag, here you can set the path for your custom icon file (path of .ico file).
    5. Save the settings file and open the updated file through 7 Zip SFX Maker. Make sure that “Allow user to change path” option is unselected under Dialogs -> Extract Path tab. There is bug in this application whenever we open any saved settings file the specified option set to default value.
      Icons Tab
  12. Go to Tasks tab and click on plus button to add a task to execute after the extraction complete. Please do the following things to show our HTA splash window after the extraction,
    1. Click on “Add” button.
    2. It will display the new task option window, here you select the “Run Program” option.
    3. It will display the Run Program option window and enter the following details.
      1. Enter Splash.hta at end of the Program textbox.
      2. Select the Do not wait for program to finish option.
      3. Select the Hide Console windows option.
      4. Finally click on “OK” button.
    4. Now you can see an entry in the task list box.
      Run Program
  13. Go to Metadata tab, select each attributes and change the value according to your need.
    Metadata
  14. Save the settings one more time.
  15. Click on “Make SFX”.
  16. Finished message will be displayed on the status bar once it build successfully.
  17. We almost done with our example and now we are going to do the test the output.
  18. Go to Product Setup folder, here you can find a self-extractor exe file with name of ProductSetup.sfx.exe.
  19. Double click on ProductSetup.sfx.exe, it will extract the ProductSetup.7z to temporary folder and start the Splash.hta after the extraction.
  20. While loading splash.hta scan for system information like OS, CPU and physical memory and custom pre-requisites information and display it on the screen.
  21. Click on “Install Product”, the splash window run the appropriate MSI installer based on OS bit size.
  22. Click on "Installer Guide" to see the installer guide so user can go through it before starting the installation.

As we expected, we got a single installer package and it helps user to run the right installer based on his/her machine configuration and also it facilitates us to show our brand and product information to user during every installation.

Conclusion

In this article we have seen how to create single package for multiple CPU architecture MSI installers and I hope it has delivered some useful information to you. Please provide your valuable feedback under comment section.

License

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