1. Introduction to InstallBuilder

InstallBuilder is a modern, fully-featured, cross-platform installation tool. It is designed to simplify the deployment of both desktop and server software, helping you reduce support costs related to installation and provide a positive end-user experience.

This document provides an overview of InstallBuilder capabilities and architecture, as well as in-depth coverage of common installation topics. A companion appendix provides detailed information on each one of the XML configuration options.

1.1. What Sets InstallBuilder Apart

To fully understand the architecture and capabilities of InstallBuilder, it is useful to consider the previous generation of cross-platform installers. These were built using the Java programming language. Java is a fine choice for multiple scenarios and indeed over half of your users use InstallBuilder to package Java-based applications. However, it has a set of major drawbacks when the goal is to create setup programs. For example, it requires a Java runtime environment to be present in the machine, which increases the chances of something going wrong if one is not present or the one present is not a suitable version. Alternatively, if the user decides to bundle a JRE with the installer in order to avoid these potential problems, it will increase significantly the footprint of the installation. Java-based installers also require a self-extraction step, in which the files are first unpacked to disk before installation can begin. For large installers, this can be a time-consuming step and another source of installation-related issues if the end-user runs out of disk space during this process. Finally, and although alternative toolkits like SWT finally emerged, Java GUI development has traditionally suffered from poor performance and lack of a truly native look-and-feel. End-users react much more favorably to setup applications that are responsive and provide a familiar native interface, even if the functionality is identical.

The above is not intended as a rant against Java-based installers, rather as an illustration of the challenges that a cross platform installation tool faces. So, how does InstallBuilder address these issues? Installers generated with InstallBuilder are native applications that do not require any runtime to be present in the system to run. This means that the overhead the installer introduces is very small, typically around 2 to 3 Mb, versus the 15 Mb to 20 Mb that a bundled JRE requires. In addition to this, the installers do not perform a self-extraction step, meaning that they start up instantaneously, whereas some Java-based installers can take up to minutes to initialize for large installers. Installers created with InstallBuilder use the underlying system libraries for displaying their GUI interfaces, so users get a native look and feel for each platform the installers run on, such as Windows and Mac OS X. On Linux and other Unix platforms, there is not a single standard look and feel. In those cases, InstallBuilder provides a choice between the most common toolkits, Qt and GTK, as well as a built-in fallback mode.

1.2. What’s New In InstallBuilder 8

InstallBuilder 8 provides a host of new features, including:

  • Built-in debugger: An optional debugger packed within the installers, facilitating troubleshooting or installer development.

  • New dynamic parameter pages: Two new parameter groups allow dynamic interaction with the end user.

  • Tree component selection: Components can now be grouped to allow the features to be displayed as a tree in the component selection

  • Downloadable Components: Components can now be marked as downloadable so they will not be packed in the installer but separated into external data files that will be downloaded at runtime if needed.

  • Individual management of component installation/uninstallation: The installers are now capable of adding and removing components from an existing installation.

1.3. Features

InstallBuilder is a fully-featured tool capable of addressing multiple installation scenarios, from desktop games to engineering simulation tools to enterprise-level server software.

  • Multiplatform Support: BitRock installers are native binaries that can run on Windows, OS X and Linux and most other flavors of Unix, including FreeBSD, OpenBSD, AIX, OS/400, HP-UX and IRIX.

  • Desktop Integration: BitRock installers provide native look and feel and desktop integration for Windows, OS X and Linux (KDE and Gnome).

  • Optimized: BitRock installers are optimized in size and speed and do not require a self-extraction step, reducing download, startup and installation time. Built-in LZMA support provides great compression ratios.

  • No External Dependencies: BitRock installers are single-file, self-contained native executables with no external dependencies and minimal overhead. Unlike competing products, all BitRock installers are truly native code and do not require bundling a Java Runtime Environment.

  • Ease of Use: BitRock installers provide an intuitive and easy to use interface on all platforms, even for end users without previous Linux experience.

  • Ease of Development: InstallBuilder includes an easy to learn, easy to use GUI environment. Design, build and test installers with the click of a button.

  • Time Saving Functionality: For advanced users, a friendly XML project format supports source control integration, collaborative development and customizing projects both by hand and using external scripts. A command line interface allows you to automate and integrate the building process. QuickBuild functionality allows you to update installers in a few seconds, without having to repack the entire application.

  • Built-in Actions: InstallBuilder provides convenient built-in actions for commonly required installation functionality such as auto-detecting a Java(tm) Runtime, changing file permissions and ownership, substituting text in a file, adding environment variables, adding directories to the path, creating symbolic links, changing the Windows registry, launching external scripts and so on.

  • Crossplatform Build Support: The installer builder tool can run on Windows, Mac OS X, Linux and all other supported Unix platforms and generate installers for all target platforms from a single project file. Create all your installers from a single build environment!

  • Customization: BitRock installers can be customized in a variety of ways, both graphically and in functionality. It is possible to ask for multiple parameters, like username and passwords, in the same installer screen. This functionality helps to simplify the installation process for end-users.

  • Multiple Installation Modes: BitRock installers provide: several GUI modes with native look-and-feel, for installation in a variety of desktop environments, a text-based installation mode, for console-based and remote installations, and a silent/unattended install mode which can be used for integration in shell scripts for automated deployment.

  • Support for Qt® GUI Frontend: The InstallBuilder for Qt family of products provides a GUI installation mode using the Qt crossplatform toolkit, enhancing the end-user experience

  • Rollback Functionality: BitRock installers by default perform a backup of all the files overwritten during installation, so if there is an error, the system can be recovered to its previous state.

  • Native Package Integration: BitRock installers can register your software with the RPM and DEB package databases, combining the ease of use of an installer wizard with the underlying native package management system.

  • RPM and DEB generation: In addition to creating native executables that can register with the RPM subsystem, BitRock InstallBuilder can generate self-contained RPM and Debian packages that can be installed using the native package management tools.

  • Uninstall Functionality: An uninstall program is created as part of every installation, allowing users to easily uninstall the software. Like the installers, it can be run in a variety of modes. On Windows, uninstall functionality can also be accessed from the Add/Remove Programs entry in the Control Panel.

  • Startup Failure Detection: BitRock installers will automatically and gracefully detect the best installation mode available. Users also have the option to manually select a mode.

  • Language and Platform Independent: BitRock installers can install applications written in any language, including: Java, PHP, Perl, Python, Ruby, C/C++ and .NET/Mono.

  • Multiple Language Support: BitRock installers support a variety of installation languages, including English, German, Japanese, Spanish, Italian, French, Portuguese, Traditional Chinese, Dutch, Polish, Valencian, Catalan, Estonian, Slovenian, Romanian, Hungarian, Russian and Welsh. Installers in Qt mode support right to left languages such as Arabic. The full list can be found in the Languages section. You can specify a default language or let the user decide. Please contact us if you require additional language support.

1.4. Supported Platforms

InstallBuilder provides support for all common (and not so common!) operating systems out there. If you want to know if InstallBuilder supports a particular platform, please contact us - chances are that it does. InstallBuilder-generated installers will run on:

  • Windows ME, 2000, XP, 2003, 2008, Vista, Windows 7, Windows 8

  • Mac OS X (PPC & Intel) 10.2 and later

  • Linux (Intel x86/x64, Itanium, s390 and PPC) All distributions and version including Ubuntu, RHEL, SLES and Meego.

  • Solaris (Intel and Sparc) 8, 9, 10

  • HP-UX (PA-RISC, Itanium)

  • FreeBSD 4.x and later

  • OpenBSD 3.x and later

  • AIX 4.3 and later

  • OS/400

  • IRIX 6.5

1.5. Requirements

The command line builder tool will run on any of the supported platforms, allowing you to generate installers for any of the other supported platforms for the InstallBuilder edition you are using. For example, if you are running InstallBuilder Professional on Linux, you will be able to generate installers for Windows, Linux and OS X. This is particularly useful for situations in which you need to build the installers as part of a continuous integration/daily build scenario.

The GUI installer design tool helps you to visually create installation projects. The GUI design tool runs on Linux x86/x64, OS X and Windows with a minimum of 800x600 screen resolution. Note that you can always edit XML projects directly or even alternate between using the GUI and editing the XML project file as needed.

1.6. Editions

InstallBuilder is distributed in multiple editions, with the primary differentiation being the supported platforms that you can create installers for. The link below provides a detailed comparison of the available editions:

1.7. The GUI

InstallBuilder allows projects to be created and edited with an easy to use graphical editor tool. Adding new actions to the installation logic or files to pack is as easy as double-clicking the appropriate element and navigating through the organized dialogs. The GUI is only available on Linux x86/x64, Windows and OS X.

Once the GUI is launched, you will be welcomed with the screen displayed in Figure 1. From this main screen you can use the top menu entries to create a new project or open an existing one, launch the build process, check for an updated version of InstallBuilder, register your copy of the tool and open the documentation.

GUI welcome screen
Figure 1: GUI welcome screen

Alternatively, you can use the shortcut buttons to perform the most common actions:

GUI Toolbar
Figure 2: GUI Toolbar

Some of the toolbar buttons will be disabled depending on whether a project is loaded or not. Figure 2 also shows the notification you will see when a new version is available. If the builder has access to the Internet and is configured to check for updates, it will automatically report these notifications for each new version released. The process can also be manually triggered using the Update menu. Clicking on the blue arrow will open the downloads page in a web browser.

Note
Disabling checking for new versions of InstallBuilder

If you do not want the installer to check for updates on startup, you can edit the update.dat file located in the same directory as the builder and set check_for_updates=0

After loading or creating a new project, a new UI will appear, divided in different sections:

  • Product Details: This section presents a quick overview of the basic configuration settings for the project (Figure 3).

New project
Figure 3: New project

The main project settings Vendor name, Product Name, Product Filename and Version Number are defined once and used multiple times when displaying information during the installation process; in the Add/Remove Program menu, the installer filename and so on. It is always possible to override these default values when necessary.

Enabling Save Relative Paths will convert all of the absolute paths related to the build process (files to pack, images, readme…) to relative paths, using the location of the project file as the reference. This setting will be applied automatically and transparently when saving and loading the project so it will not be noticeable while working in the GUI. This particular setting is especially useful when sharing a project between developers or operating systems, as the location of the resources is not hardcoded, as explained in theWhen is it necessary to use the Save Relative Paths option? note. If the paths were already manually configured as relative, they will be preserved and resolved when building, also using the location of the project to absolutize them.

The License File setting specifies a license file that will be displayed during installation. The end user will need to accept this license text before continuing with the installation process. If you do not provide a license file, the license acceptance screen will not be displayed to the end user.

You can also provide an alternate HTML License File. This HTML-formatted license will be used if the front-end supports it (currently only the case for the Qt front-end). Otherwise the default license text specified in the License File setting will be displayed.

You can also display multiple licenses in different languages or display them conditionally, as described in the Displaying a localized license and readme section.

  • Files: This section allows managing all of the resources included in the project such as files to pack, and shortcuts to create. These resources are organized in components, designed to group common functionalities, and files, which are divided into folders (Figure 4).

Files screen
Figure 4: Files screen

Shortcuts may also be added in this section.

  • Advanced: The same way the Files section specifies the resources that will be packaged, the Advanced section deals with the configuration of the actions and rules associated with them (Figure 5). It also allows you to describe the inputs that the installer will accept and the pages to display at runtime to interact with the end user. The nodes in the tree can also be reordered, moved (you can drag and drop them) and copied (press shift while performing a drag and drop operation). In addition, the root node, representing the project, allows configuring the global project properties.

Advanced screen
Figure 5: Advanced screen
  • Customization: The Customization section (Figure 6) provides a convenient way to configure the most common project properties. It is a subset of the properties available in the Advanced tab.

Customization screen
Figure 6: Customization screen
  • Packaging: This section allows you to specify the target platform for which you want to build the installer. It provides a log of the build process, including a progress bar and displaying build-errors in red when they occur (Figure 7).

Packaging screen
Figure 7: Packaging screen
Note

The GUI is only available on Linux, Linux x64, Windows and OS X. The command line builder is available on all platforms.

1.8. The XML

InstallBuilder project files are stored in XML format. This enables and simplifies source control integration, collaborative development and customizing projects both by hand and using external scripts.

Our XML is human friendly, and although the project can be fully managed through the GUI, advanced users can also directly edit the XML project using the built-in XML editor or their preferred text editor or IDE. The following is a complete example of what an InstallBuilder project looks like. This particular project does not package any files.

<project>
    <shortName>sample</shortName>
    <fullName>Sample Project</fullName>
    <version>1.0</version>
    <enableRollback>1</enableRollback>
    <enableTimestamp>1</enableTimestamp>
    <componentList>
        <component>
            <name>default</name>
            <description>Default Component</description>
            <canBeEdited>1</canBeEdited>
            <selected>1</selected>
            <show>1</show>
            <folderList>
                <folder>
                    <description>Program Files</description>
                    <destination>${installdir}</destination>
                    <name>programfiles</name>
                    <platforms>all</platforms>
                    <shortcutList>
                        <shortcut>
                            <comment>Uninstall</comment>
                            <exec>${installdir}/${project.uninstallerName}</exec>
                            <icon></icon>
                            <name>Uninstall ${project.fullName}</name>
                            <path>${installdir}</path>
                            <platforms>all</platforms>
                            <runAsAdmin>0</runAsAdmin>
                            <runInTerminal>0</runInTerminal>
                            <windowsExec>${installdir}/${project.uninstallerName}.exe</windowsExec>
                            <windowsExecArgs></windowsExecArgs>
                            <windowsIcon></windowsIcon>
                            <windowsPath>${installdir}</windowsPath>
                        </shortcut>
                    </shortcutList>
                </folder>
            </folderList>
            <startMenuShortcutList>
                <startMenuShortcut>
                    <comment>Uninstall ${project.fullName}</comment>
                    <name>Uninstall ${project.fullName}</name>
                    <runAsAdmin>0</runAsAdmin>
                    <runInTerminal>0</runInTerminal>
                    <windowsExec>${installdir}/${project.uninstallerName}.exe</windowsExec>
                    <windowsExecArgs></windowsExecArgs>
                    <windowsIcon></windowsIcon>
                    <windowsPath>${installdir}/</windowsPath>
                </startMenuShortcut>
            </startMenuShortcutList>
        </component>
    </componentList>
    <parameterList>
        <directoryParameter>
            <name>installdir</name>
            <description>Installer.Parameter.installdir.description</description>
            <explanation>Installer.Parameter.installdir.explanation</explanation>
            <value></value>
            <default>${platform_install_prefix}/${project.shortName}-${project.version}</default>
            <allowEmptyValue>0</allowEmptyValue>
            <ask>yes</ask>
            <cliOptionName>prefix</cliOptionName>
            <mustBeWritable>yes</mustBeWritable>
            <mustExist>0</mustExist>
            <width>30</width>
        </directoryParameter>
    </parameterList>
</project>

If your XML editor supports it, you can use a RELAX NG schema for validation. It is included as InstallBuilder.rng, inside the docs directory of your installation.

Most of the examples presented in this guide are provided as XML snippets, but you can achieve identical functionality using the GUI

Note

The XML specification requires that specific characters are escaped. This is done automatically if entering the values through the GUI but if you are directly editing the XML code you must take it into account. The table below summarizes the most common characters and their escape sequence:

Table 1. Common XML escape sequences
Character XML escaped sequence

&

&amp;

<

&lt;

>

&gt;

'

&apos;

"

&quot;

\n

&#xA;

Some of the values only need to be escaped if provided as part of an attribute value, not an element.

The snippet below adds some lines to an existing file, separating them using escaped line breaks (\n):

 <addTextToFile>
    <file>${installdir}/foo.txt</file>
    <text>line1&#xA;line2&#xA;line3</text>
 </addTextToFile>

It is also possible to escape a full block of code using the <![CDATA[ .. ]]> notation

  <writeFile>
    <path>${installdir}/${project.vendor}-x-my-mime.xml</path>
    <text><![CDATA[
<?xml version="1.0"?>
<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
  <mime-type type="application/x-my-mime">
    <comment>My new file type</comment>
    <glob pattern="*.mymime"/>
  </mime-type>
</mime-info>
 ]]></text>
  </writeFile>

The text inside the <![CDATA[ .. ]]> block will be interpreted literally, so you do not need to escape any character.

2. Installation and Getting Started

2.1. Installation

This section describes how to get up and running with InstallBuilder on a variety of platforms

2.1.1. Installing on Windows

You can download BitRock InstallBuilder from the BitRock website: installbuilder.bitrock.com. To start the installation process, double-click on the downloaded file.

You will be greeted by the Welcome screen shown in Figure 8:

Windows Welcome Screen
Figure 8: Windows Welcome Screen

Pressing Next will take you to the License Agreement page, shown in Figure 9. You need to accept the agreement to continue with the installation. The next step is to select the installation directory Figure 10. The default value is C:\Program Files\BitRock InstallBuilder\

Windows License Agreement
Figure 9: Windows License Agreement
Windows Select Installation Directory
Figure 10: Windows Select Installation Directory

The rest of this guide assumes you installed BitRock InstallBuilder in C:\Program Files\BitRock InstallBuilder\

You are now ready to start the installation process itself (Figure 11), which will take place once you press Next (Figure 12). When the installation completes, you will see the Installation Completed page shown in Figure 13. You may choose to view the README file at this point.

Windows Ready To Install
Figure 11: Windows Ready To Install
Windows Installation Under Way
Figure 12: Windows Installation Under Way
Windows Installation Completed
Figure 13: Windows Installation Completed
Note

If you found a problem and could not complete the installation, please refer to the Troubleshooting section or contact us at support@bitrock.com. Please refer to the Support section for details on which information you should include with your request.

2.1.2. Installing on Unix

The process for installing on Linux and other Unix platforms is similar. The rest of this section assumes you are running Linux. You can download the BitRock InstallBuilder binary from the BitRock website. It should have a name similar to installbuilder-professional-8.0.2-linux-installer.run. Make sure it has read and executable permissions by right clicking on the file, selecting "Properties" and then setting the appropriate permissions. Alternatively you can issue the following shell command:

  $> chmod +x installbuilder-professional-8.0.2-linux-installer.run

You can now start the installation by double-clicking on the file from your Desktop environment or by invoking it directly from the command line with:

  $> ./installbuilder-professional-8.0.2-linux-installer.run

You will be greeted by a Welcome screen if you are running in a Desktop environment or a text message (if no GUI mode is available).

The default value for installation will be a folder in your home directory if you are running the installer as a regular user (recommended) or /opt/installbuilder-8.0.2/ if you are running the installation as superuser (root).

2.1.3. Installing on Mac OS X

The Mac OS X version of InstallBuilder is distributed as a zip file containing a .app that will be uncompressed automatically at download time by the browser. Alternatively you can uncompress it with:

  $> unzip installbuilder-professional-8.0.2-osx-installer.app.zip

You can launch the application by double-clicking on it in Finder or from the command line with the following instruction

  $> open installbuilder-professional-8.0.2-osx-installer.app

2.2. Registering your Copy of InstallBuilder

The InstallBuilder version you can download from installbuilder.bitrock.com is a fully functional evaluation version. It can only be used for a period of 30 days, and is intended for evaluation purposes only. It will add a reminder message to each installer ("Created with an evaluation version of BitRock InstallBuilder") which will disappear once you purchase and register a license.

There are two ways of registering your license with the product:

  • Using the GUI interface: From the main application menu select "License", then "Register License", and a window will appear where you can enter the location of your license file.

  • Manually: The product can be manually registered by copying the license.xml file to the directory where InstallBuilder was installed.

2.2.1. Specifying a License in the Command Line

Sometimes you may need to specify a license at build time, instead of registering your copy of InstallBuilder. For example, this is necessary when you do not have write permissions for the InstallBuilder installation directory.

To do so, you can use the --license flag both with the GUI and command line builder.

$> builder build ~/project.xml --license ~/licenses/license.xml
$> builder --license ~/licenses/license.xml

The code above will launch the command line or GUI builder and all generated installers will be registered with the license ~/licenses/license.xml. If the GUI builder is closed and then reopened without specifying the --license flag, the generated installers will use a previously registered license. If no license is registered or an incorrect one is provided, the message Built with an evaluation version of InstallBuilder will be displayed while building. A similar message will also be displayed in the Welcome page of the generated installers.

2.2.2. Windows-specific License Registration Details

On certain Windows versions, especially those that are UAC-enabled such as Vista and Windows 7, regular users cannot write to the default installation directory of InstallBuilder under c:\Program Files. When registering a new license, the builder will try first to write it to the main installation directory. If it is not writable, it will be placed in the user’s personal folder.

When the builder is launched, it will try to load the license from the user’s personal folder and if none is found, it will look for it in the installation directory.

This process allows multiple users to share the same installation of Installbuilder without interference, even if they do not have administrative rights. It also allow using different licenses for each user. The output directory follows a similar approach as explained in the "Directory structure" section.

2.3. Directory Structure

The installation process will create several directories:

  • bin: BitRock InstallBuilder application binaries.

  • paks: Support files necessary for creating installers.

  • autoupdate: Support and binary files for the bundled automatic update tool.

  • projects: Project files for your installers. See note below for Windows Vista.

  • docs: Product documentation.

  • demo: Files for the sample demo project.

  • output: Generated installers. See note below for Windows Vista and Windows 7.

On Windows Vista and Windows 7, in line with the Application Development Requirements for User Account Control (UAC), the projects and output directories are installed under the user Documents folder, so usually they can be found at C:\Users\user\Documents\InstallBuilder\projects and C:\Users\user\Documents\InstallBuilder\output, respectively.

You are ready now to start the application and create your first installer, as described in the next section "Building your First Installer".

2.4. Building Your First Installer

This section explains how to create your first installer in a few simple steps.

2.4.1. Startup and Basic Information

If you are running Gnome or KDE and performed the installation as a regular user, a shortcut was created on your Desktop. You can either start BitRock InstallBuilder by double-clicking on it or by invoking the binary from the command line:

 $> /home/user/installbuilder-8.0.2/bin/builder

If you are running Windows, the installer created the appropriate Start Menu entries. Additionally, a shortcut was placed on your Desktop. Please refer to the Using the Command Line Interface section later in the document for more information on building installers from the command line.

The initial screen will appear (Figure 14). Press the "New Project" button or select that option from the File menu on the top left corner. A pop-up Window will appear, asking you for four pieces of information:

  • Product Name: The full product name, as it will be displayed in the installer

  • Product Filename: The short version of product name, which will be used for naming certain directories and files. It can only contain alphanumeric characters

  • Version Number: Product version number, which will be used for naming certain directories and files.

  • Vendor name: Vendor name that will be used to generate native packages, register the application with the package database or the Windows Add/Remove/Program menu

The rest of this tutorial assumes you kept the default values: "Sample Project", "sample", "1.0" and "Name of your Company".

Main Screen
Figure 14: Main Screen

Once you enter the information, the "Basic settings screen" (Figure 15) will be shown. Here you can specify additional settings:

  • License File: Path to the license file that the user must accept in order to install the software

  • Readme File: Path to the README file that can be shown to the user after installation is completed

  • Save Relative Paths: Determines whether or not to convert absolute paths to relative when saving project files. This is important if the same project file is used by multiple developers. The path will be relative to the location of the project file.

If you do not want to display a license agreement or a README file during installation, you can leave those fields blank.

Note
When is it necessary to use the Save Relative Paths option?

It is necessary when the same project file is shared by multiple developers on different machines or when using the same project file on Windows and Unix. This is due to the differences in how paths are specified on each platform. For example, a Windows path includes a drive identifier, such as c:\myproject\images\logo.png This is fine if only one developer is building the project in the same machine, but will cause problems if the project needs to be rebuilt on a Unix machine. With the save relative paths setting enabled, it is possible to specify the location of the file as ..\images\logo.png which will be appropriately translated as ../images/logo.png on Unix systems.

Basic Settings
Figure 15: Basic Settings

2.4.2. Select the Files

The next step is to click on the "Files" icon, which will lead to the screen shown in Figure 16.

The "Program Files" folder represents the target installation directory. You can add files and directories to this folder by selecting the "Program Files" folder and using the "Add File" and "Add Directory Tree" buttons. You can add multiple files by pressing down the Control key and clicking on them in the File selection dialog. Multiple selection is not available for directories at this time. The selected files and directories will be copied to the destination the user chooses during installation. If a folder only supports a particular target platform, such as Linux, it will only be included in installers for that particular platform.

Most applications only install files under the main installation directory ("Program Files" folder in the Files screen). It is possible, however, to add additional folders to copy files and directories to, such as /usr/bin or /etc/ by pressing the "Add Destination Folder" button in the Files screen. If you need special permissions to write to the destination folders, you may need to require installation by root (see "Customization of the installer" below).

Files Screen
Figure 16: Files Screen

Shortcuts can also be added to folders or the component. Depending on where it is added, it will be created in different places. For example, if a shortcut is added to a folder, it will be created in the destination of that folder. If the shortcuts are added to the Desktop or the Start Menu sections of the component they will be created in those locations (if applicable, Start Menu shortcuts are just created on Windows).

Please refer to the "Menus and Shortcuts" section to find additional information.

2.4.3. Add Logic to the Installer

You can add logic to the installer, such as asking for information from the end user, creating users or writing some information to the registry. The Advanced section allows managing both custom pages and actions.

In most cases, a <initializationActionList> or <preInstallationActionList> element is used to perform a first validation of the system, such as checking for previous installations or enough disk space and the <postInstallationActionList>, executed after the unpack process, is used to perform actions with the installed files. For example, tasks such as changing permissions or starting a bundled Apache server would be performed after your software is installed. You can get a comprehensive list of available actions in the Actions appendix. A listing of all available points during the installation process in which these actions will be executed can be found in the Action Lists section.

With regards to getting information from the end user such as the installation directory, ports or passwords, the User Input and Pages sections include countless examples of how to retrieve all of the information required and how to properly create complex layouts.

2.4.4. Add a license key page

In some cases it is desirable to prevent your users from installing your software without providing a previously purchased license key. The example below explains how to create a custom license key page and how to validate its input:

<project>
  ...
  <!-- Component bundling the validator -->
  <componentList>
    <component>
    <name>tools</name>
       <folderList>
          <folder>
             <name>license</name>
             <destination>${installdir}</destination>
             <distributionFileList>
                <distributionFile origin="/path/to/validator.exe"/>
             </distributionFileList>
          </folder>
       </folderList>
    </component>
  </componentList>
  ...
  <parameterList>
    ...
    <!-- License key page -->
    <parameterGroup>
       <name>licensekey</name>
       <title>License Key</title>
       <explanation>Please enter your registration key</explanation>
       <value></value>
       <default></default>
       <orientation>horizontal</orientation>
       <parameterList>
          <!-- A stringParameter for each field. We include a "-" as description to simulate the license-type format -->
          <stringParameter name="field1" description="" allowEmptyValue="0" width="4"/>
          <stringParameter name="field2" description="-" allowEmptyValue="0" width="4"/>
          <stringParameter name="field3" description="-" allowEmptyValue="0" width="4"/>
          <stringParameter name="field4" description="-" allowEmptyValue="0" width="4"/>
       </parameterList>
       <validationActionList>
          <!-- Check all the fields have the appropriate length -->
          <foreach variables="field">
             <values>"${field1}" "${field2}" "${field3}" "${field4}"</values>
             <actionList>
                <throwError>
                   <text>${field}: Field should be four digits length</text>
                   <ruleList>
                       <compareTextLength text="${field}" logic="equals" length="4" negate="1"/>
                   </ruleList>
                </throwError>
                <throwError>
                   <text>${field}: Should be a pure digit string</text>
                   <ruleList>
                       <stringTest text="${field}" type="digit" negate="1"/>
                   </ruleList>
                </throwError>
             </actionList>
          </foreach>
          <!-- Join all the fields to create the license number -->
          <setInstallerVariable name="${normalizedkey}" value="${field1}${field2}${field3}${field4}"/>
          <!-- Unpack a bundled validator program and check if the license is correct -->
          <unpackFile>
            <destination>${system_temp_directory}</destination>
            <component>tools</component>
            <folder>license</folder>
            <origin>validator.exe</origin>
          </unpackFile>
          <runProgram>
            <program>${system_temp_directory}/validator.exe</program>
            <programArguments>${normalizedkey}</programArguments>
          </runProgram>
          <throwError text="Wrong license key, please enter a valid one">
            <ruleList>
              <compareText text="${program_stdout}" logic="equals" value="1"/>
            </ruleList>
          </throwError>
       </validationActionList>
       <ruleList>
          <compareText text="${installer_ui}" logic="equals" value="gui"/>
       </ruleList>
    </parameterGroup>
    ...
  </parameterList>
  ...
</project>

Please note that this layout won’t be properly displayed in text mode so the example hides the page if the ${installer_ui} is not gui (see Installation Modes for additional details). If you plan to support it, you should create an additional simplified page to be displayed in text mode:

 <stringParameter>
    <name>licensekeytext</name>
    <title>License Key</title>
    <description>Please introduce your registration key:</description>
    <validationActionList>
       ...
    </validationActionList>
    <ruleList>
       <compareText text="${installer_ui}" logic="equals" value="text"/>
    </ruleList>
 </stringParameter>

In the example, the validation code makes use of an external tool to validate the license. If you do not have any tool, you could implement an algorithm in your XML code to validate it. A very simple validation would be to check that:

${field1}+${field3}==${field2}+${field4}

<validationActionList>
    <mathExpression>
        <text>${field1}+${field3}</text>
        <variable>sum1</variable>
    </mathExpression>
    <setInstallerVariableFromRegEx>
        <name>trimmedSum1</name>
        <pattern>.*(\d{4})$</pattern>
        <substitution>\1</substitution>
        <text>${sum1}</text>
    </setInstallerVariableFromRegEx>
    <mathExpression>
        <text>${field2}+${field4}</text>
        <variable>sum2</variable>
    </mathExpression>
    <setInstallerVariableFromRegEx>
        <name>trimmedSum2</name>
        <pattern>.*(\d{4})$</pattern>
        <substitution>\1</substitution>
        <text>${sum2}</text>
    </setInstallerVariableFromRegEx>
    <throwError>
        <text>Invalid License or License Count Exceeded</text>
        <ruleList>
            <compareValues>
                <logic>does_not_equal</logic>
                <value1>${trimmedSum2}</value1>
                <value2>${trimmedSum1}</value2>
            </compareValues>
        </ruleList>
    </throwError>
 </validationActionList>

Please note this is a very simple algorithm. If you plan to use this in your installer you can create more complex checks using <setInstallerVariableFromRegEx> and <md5> actions.

Another option is to send the provided license key to your server to validate:

<validationActionList>
    <httpPost>
        <filename>${system_temp_directory}/post_result</filename>
        <url>http://www.example.com/validate.php</url>
        <queryParameterList>
            <queryParameter name="key" value="${normalizedkey}"/>
        </queryParameterList>
    </httpPost>
    <md5>
      <text>${normalizedkey}+secretKey</text>
      <variable>expected</variable>
    </md5>

    <readFile name="result" path="${system_temp_directory}/post_result"/>
    <throwError text="Invalid License or License Count Exceeded">
        <ruleList>
            <compareText>
                <logic>does_not_contain</logic>
                <text>${result}</text>
                <value>${expected}</value>
            </compareText>
        </ruleList>
    </throwError>
    <deleteFile path="${system_temp_directory}/post_result"/>
 </validationActionList>

You can also send additional information, such as a required username and password so you can track which user is providing the license key. The drawback of using this approach is that it requires an Internet connection.

2.4.5. Customize the Installer

On the Customization (Figure 17) and the Packaging screens, you can change the default installation settings to match your needs:

User Interface Settings

  • Logo Image: 48x48 GIF or PNG logo image that will be placed at the top right corner of the installer. If no image is specified, the default image will be used

  • Left Side Image: 163x314 GIF or PNG image that will be placed at the left side of the installer in the Welcome and Installation Finished pages. If no image is specified, the default image will be used

  • Windows Executable Icon: ICO file with an specific format -see below- to set the icon for the installer executable file on Windows systems.

  • Default Installation Language: Default language for the installer

  • Allow Language Selection: Allow language selection. If this setting is enabled, the user will be required to specify the language for the installation

  • Wrap License File Text: Wrap license file text displayed to the user

  • Splash screen delay: Extra display time of the splash screen

Installer Settings

  • Require Install by Administrator: Whether or not installation will require super user privileges (root on Linux, Administrator user on Windows and OS X). This setting will prevent the installer from running if the user is not root or Administrator on all operating systems except for OS X. In OS X, the regular authentication dialog window will be shown, asking the user for the administrator password so the installer can be run with root privileges

  • Installer Name: Name of the installer created by the build process.

  • CDROM Files Directory: Name of the directory that will contain the CDROM files created by the build process

  • Uninstaller Directory: Directory where the uninstaller will be created

  • Compression Algorithm: Compression algorithm that will be used to pack the files inside the installer. LZMA compression is available only on Linux, Windows and OS X platforms

  • Backup Directory: Path to a directory where existing files will be stored if enableRollback property is enabled

  • Installation Scope: Whether or not to install Start Menu and Desktop links for All Users or for the current user. If set to auto, it will be installed for All Users if the current user is an administrator or for the current user otherwise.

It is recommended that instead of using the above settings, you use the equivalent action lists, such as <postInstallationActionList> and <preUninstallationActionList>.

Permissions

Please note that these options only take effect when creating installers for Unix platforms from Windows.

  • Default Unix File Permissions: Default Unix file permissions in octal form

  • Default Unix Directory Permissions: Default Unix directory permissions in octal form

Customization screen
Figure 17: Customization screen

Check the Customization section for an in-depth customization guide.

All of these project-level configuration settings can be customized based on the platform using the <platformOptionsList> tag:

<platformOptionsList>
   <platformOptions>
      <platform>linux</platform>
      <leftImage>images/abc_linux_left.png</leftImage>
      <height>400</height>
   </platformOptions>
   <platformOptions>
      <postInstallationScript>${installdir}/linux-x64-script.sh</postInstallationScript>
      <platform>linux-x64</platform>
   </platformOptions>
   <platformOptions>
       <platform>solaris-sparc</platform>
       <leftImage>images/abc_solaris_sparc_left.png</leftImage>
   </platformOptions>
   <platformOptions>
       <platform>solaris-intel</platform>
       <leftImage>images/abc_solaris_intel_left.png</leftImage>
   </platformOptions>
   <platformOptions>
       <platform>windows</platform>
       <leftImage>images/abc_left.png</leftImage>
   </platformOptions>
   <platformOptions>
       <platform>osx</platform>
       <leftImage>images/abc_osx_left.png</leftImage>
       <height>500</height>
   </platformOptions>
</platformOptionsList>

2.4.6. Packaging the Installer

You can now build the installer by pressing the "Build" button. This will take you to the Packaging screen and start the installer building process, as shown in Figure 18. If the build process succeeds, an installer named sample-1.0-linux-installer.run will be placed at the output directory (C:\Users\user\Documents\InstallBuilder\projects under Windows Vista and Windows 7, as explained earlier). If you are building a Windows installer, the file will be named sample-1.0-windows-installer.exe. If you are building a Mac OS X installer, its name will be sample-1.0-osx-installer.app. The Mac OS X installer binary will need to be packaged inside an archive file or disk image. If any problem is found, such as a file not being readable, a message will be displayed in red and the build will stop.

Building the installer
Figure 18: Building the installer

You can test the generated installer by pressing the "Test Run" button, as seen in Figure 19.

Note
What is the difference between Full Build and Quick build?

Creating an installer can take a long time if your product is hundreds of megabytes in size. You can use the Quick Build button to avoid rebuilding an installer from scratch if you are just making changes to installer-specific settings, such as license and readme files, the default installation path or logo image. It will also do incremental packaging of files that have been added or removed. This incremental package will increase the size of the installer, so it is recommended that you do a full build after development of the installer has completed and before release.

You can customize additional installer functionality as explained in the Advanced Functionality section.

Testing the installer
Figure 19: Testing the installer

2.4.7. CDROM Installers

It is possible to select a CDROM build target. In this case, a directory including a folder with common installer files and a setup file for each one of the supported architectures is created. This allows you to provide a single CDROM for all platforms, avoiding duplication of data.

This method is also the recommended approach for installers above 1GB, especially on Windows, where the UAC mechanism tries to copy the full installer to the %TEMP% folder before launching it, which results in very high delays when starting the installer. Another known issue on Windows is that executables above 1GB do not show their icons.

Using the cdrom-type build will create a set of lightweight installers for the configured platforms and the packed files separately.

To build a CDROM installer you just have to select Multiplatform CDROM as Build Platform in the Packaging screen when using the GUI mode or just provide cdrom as the target in the command line interface:

$> bin/builder build project.xml cdrom

InstallBuilder will then generate a set of folders, each of them containing the files to be burned in the CDROM disk. For example, for a 4 disk installer you will get:

$> ls output/

sample-1.0-cdrom
sample-1.0-cdrom.1
sample-1.0-cdrom.2
sample-1.0-cdrom.3

Where the name of the folders is defined through the <cdromDirectory> project property. The first disk is contained in the folder named sample-1.0-cdrom and, apart from the packed files, it will contain the installers for the different platforms. The other folders will just contain the rest of the files to install. When installing the generated multidisk installer, InstallBuilder will automatically ask for the next disk when needed.

A CDROM build is configured through the below project properties:

  • <cdromFirstDiskSize>: The size (in bytes) of the first CDROM (default value: 650000000). This tag will allow you to reserve some space in the first disk to include presentations, images or video tutorials without affecting the size of the rest of the disks. If you don’t need this extra space in the first disk you can just set it to the same value as the <cdromDiskSize> property.

  • <cdromDiskSize>: The size (in bytes) of the remaining CDROMS (default value: 700000000)

  • <cdromPlatforms>: Space-separated list of platforms that the CDROM installer will support. A launcher binary will be added in the first disk for each of these platforms.

  • <cdromDirectory>: Name of the directory that will contain the CDROM files created by the build process (defaults to ${project.shortName}-${project.version}-cdrom)

  • <compressPackedFiles>: Compress files as if they were being packed into the installer file (defaults to 0). Setting this option to true results in the creation of a dist file that has packed all the files inside it. It usually achieves better compression rates.

Note
Creating DVD disks

In case of DVD disks, the appropriate values for the <cdromFirstDiskSize> and <cdromDiskSize> tags are:

<project>
  ...
  <cdromFirstDiskSize>4650000000</cdromFirstDiskSize>
  <cdromDiskSize>4700000000</cdromDiskSize>
  ...
</project>
Note
Distributing big installers in other media formats

If your product is distributed in other media formats such as a USB drive or SD card you can still use the CDROM-type build.

You just need to set a <cdromFirstDiskSize> above your required disk space so InstallBuilder does not split the data into multiple disks. As internally calculating the required disk space for each disk does not currently take into account the compression gain, a safe value to set would be twice the size of your files.

In the case of a USB bundling your 10GB of files:

<project>
  ...
  <cdromFirstDiskSize>20000000000</cdromFirstDiskSize>
  ...
</project>
How are disks on multidisk installers detected

A common error while testing the multidisk installers is not being able to detect the next disk when the installer requests it. To understand why this happens, it is important to understand how InstallBuilder detects that the inserted disk is valid:

1) When the unpack process starts, InstallBuilder looks for the dist file (or folder depending on the value of the <compressPackedFiles> property) in its parent directory and starts unpacking the files

2) When InstallBuilder finds a file that requires a new disk during the unpack process, a dialog prompts for it.

3) After the new disk is inserted and the user accepts the dialog, InstallBuilder looks for a dist file in the same location of the previous one. If InstallBuilder cannot find it, it will report that the disk is incorrect and will ask again for the disk.

The most common mistake in this step is to rename the dist or to move it to another directory in the new disk.

4) If the dist file is correctly placed and InstallBuilder finds it, it will then look for the next file to unpack. If the dist file does not contain the requested file, InstallBuilder will report that it cannot find the disk as in the previous step.

This error may occur because the wrong disk number was inserted. If this is not the case and you are not using <compressPackedFiles>1</compressPackedFiles>, the filenames inside the dist folder may have been shortened by the burning software. For example, a Joilet file system will only allow you to write up to 64 characters filenames. Using <compressPackedFiles>1</compressPackedFiles> or properly burning the disk to allow long filenames will solve the problem.

5) Once the new file is found, the installation process continues, requesting a new disk if necessary.

2.5. Sample installers bundled with InstallBuilder

InstallBuilder provides several sample projects to help you get started with building your installer.

The welcome screen in the InstallBuilder GUI shows a list of the available projects. These projects will be automatically loaded when clicked:

List of example projects
Figure 20: List of example projects in GUI

Each of these projects can be opened, built and tested without applying any changes. You can also try modifying them to see how the solutions shown in the examples can be reworked to suit your product’s needs.

2.5.1. Basic demo project

This project provides a simple, ready to use installer that will:

  • Prompt the user to accept a license agreement.

  • Display a page to select the installation directory.

  • Install the packed files.

  • Show an optional README file with information about the installation, selectable through a checkbox in the final page.

Demo project's sample license
Figure 21: Demo project's sample license

The demo project includes files for multiple platforms. Depending on the platform built, it will pack different sets of files.

2.5.2. Components, component groups and downloadable components

This project demonstrates how components and component groups can be used to package a complex application. It demonstrates how component groups can be used to organize common files and functionality. Deselecting or selecting the parent parameter group will also affect the installation of its child components.

Component selection for structured components
Figure 22: Component selection for structured components

The project will help you to understand how parent and child components interact. Selecting the Text Editor component will cause some of its child components (Printing support by default) to be installed while Slides and Presentations will enable Printing support and Projector support by default.

Deselecting Import / Export filters causes all of its children to automatically be deselected. Selecting Import / Export filters again will cause the selection status of XML / XSLT filters and Other filters to be restored.

Additional details regarding components and child components can be found in the component groups section of the documentation.

This example project also shows how downloadable components work and how to implement more advanced functionality such as mirror selection for downloads. Several components are marked as component.downloadable, which means that they will be created as separate files when built with the downloadable components flag enabled.

More information about creating installers with downloadable components can be found in downloadable components section of the manual.

Note
Downloadable components and being able to run the installer

When building the project with the downloadable components option enabled during build, the installer will try to download the created components from mirror1.example.com or mirror2.example.com and will fail.

In order to test that the downloadable components functionality is working, copy the generated packages from components/componentgroupsexample-1.0 under the output directory to a web server (you can easily setup a web server using LAMPStack (Linux), WAMPStack (Windows) or MAMPStack (OS X) from BitNami.org) and modify the link in the <componentsUrl> in demo project:

<componentsUrl>http://localhost:8080/components/componentgroupsexample-1.0/</componentsUrl>

2.5.3. Showcase of available parameters

This project shows what types of parameters are available and how you can use them to retrieve information from the user.

It explains how to combine them using parameter groups to create more complex GUIs.

The rest of the section provides examples of the available parameters, including their XML code and how they look in the GUI:

Additional license dialog

<licenseParameter>
    <title>Second License Agreement</title>
    <name>other_license</name>
    <file>docs/otherLicense.txt</file>
    <wrapText>1</wrapText>
</licenseParameter>
Show a text and image with a <labelParameter>

<labelParameter>
  <name>non_linux_user</name>
  <title>Introduction</title>
  <description>Dear ${platform_name} user, you'll now try an example installer that
will display to you examples of the InstallBuilder parameters functionality.</description>
  <image>img/icon.png</image>
</labelParameter>
Installation directory selection with a <directoryParameter>

<directoryParameter>
  <name>installdir</name>
  <description>Installation directory</description>
  <explanation>Please specify the directory where
${project.fullName} will be installed</explanation>
  <insertAfter>welcome_label</insertAfter>
  <default>${platform_install_prefix}/${project.shortName}-${project.version}</default>
  <cliOptionName>prefix</cliOptionName>
  <mustBeWritable>yes</mustBeWritable>
  <mustExist>0</mustExist>
</directoryParameter>
Group multiple fields using a <parameterGroup>

<parameterGroup>
  <name>user_data</name>
  <title>User data</title>
  <explanation>Please insert the desired username and password</explanation>
  <parameterList>
    <stringParameter>
      <name>username</name>
      <description>User Name</description>
      <value>admin</value>
      <allowEmptyValue>0</allowEmptyValue>
    </stringParameter>
    <passwordParameter>
      <name>userpasswd</name>
      <title>User Password</title>
      <description>Password</description>
      <descriptionRetype>Re-enter</descriptionRetype>
      <!-- throw an error if password is empty -->
      <validationActionList>
        <throwError>
          <text>You need to provide a non-empty password</text>
          <ruleList>
            <compareText text="${userpasswd}"
              logic="equals" value="" />
          </ruleList>
        </throwError>
      </validationActionList>
    </passwordParameter>
  </parameterList>
</parameterGroup>
Ask if a database should be installed with a <booleanParameter>

<booleanParameter>
  <name>install_db</name>
  <title>Install a database</title>
  <description>Do you want to install a database?</description>
  <default>1</default>
</booleanParameter>
Select the preferred database using radiobuttons

<choiceParameter>
  <name>preferred_database</name>
  <title>Choose a database</title>
  <explanation>Choose a database to be installed
and configured</explanation>
  <default>mysql</default>
  <cliOptionName>${project.shortName}_database</cliOptionName>
  <displayType>radiobuttons</displayType>
  <optionList>
    <option>
      <text>MySQL</text>
      <image>img/mysql.png</image>
      <value>mysql</value>
      <description>The project will be configured
to use MySQL database.</description>
    </option>
    <option>
      <text>PostgreSQL</text>
      <image>img/postgres.png</image>
      <value>postgres</value>
      <description>The project will be configured
to use PostgreSQL database.</description>
    </option>
    <option>
      <text>SQLite</text>
      <image>img/sqlite.png</image>
      <value>sqlite</value>
      <description>The project will be configured
to use SQLite database.</description>
    </option>
  </optionList>
</choiceParameter>
Multiple <booleanParameter> parameters in a <parameterGroup>

<parameterGroup>
  <name>apps_and_server</name>
  <title>Web framework and server</title>
  <explanation>Is there anything else you wish to install?</explanation>
  <parameterList>
    <booleanParameter>
      <name>install_webframework</name>
      <value>1</value>
      <description>Install a web framework</description>
      <displayStyle>checkbox-left</displayStyle>
    </booleanParameter>
    <booleanParameter>
      <name>install_server</name>
      <value>1</value>
      <description>Install a web server (this is an example of a
right aligned checkbox)</description>
      <displayStyle>checkbox-right</displayStyle>
    </booleanParameter>
  </parameterList>
</parameterGroup>
Choose the preferred framework using radiobuttons

<choiceParameter>
  <name>preferred_apps</name>
  <title>Web Frameworks</title>
  <explanation>Choose the web frameworks you want to install</explanation>
  <default>django</default>
  <cliOptionName>${project.shortName}_apps</cliOptionName>
  <displayType>radiobuttons</displayType>
  <optionList>
    <option>
      <text>Django</text>
      <value>django</value>
      <description>A web framework for Python.</description>
    </option>
    <option>
      <text>Ruby on Rails</text>
      <value>ror</value>
      <description>The famous web framework for Ruby.</description>
    </option>
    <option>
      <text>Cake</text>
      <value>cake</value>
      <description>A web framework
for PHP.</description>
    </option>
  </optionList>
  <ruleList>
    <compareValues>
      <value1>${install_webframework}</value1>
      <logic>equals</logic>
      <value2>1</value2>
    </compareValues>
  </ruleList>
</choiceParameter>
Choose between multiple web server using a combobox

<choiceParameter>
  <name>preferred_server</name>
  <title>Web Servers</title>
  <explanation>Choose the web server you want to install </explanation>
  <default>apache</default>
  <cliOptionName>${project.shortName}_server</cliOptionName>
  <displayType>combobox</displayType>
  <optionList>
    <option>
      <text>Apache</text>
      <value>apache</value>
    </option>
    <option>
      <text>Lighttpd</text>
      <value>light</value>
    </option>
  </optionList>
</choiceParameter>
Choose a file using a <fileParameter>

<fileParameter>
  <name>chooseAFile</name>
  <title>Configuration File</title>
  <explanation>Please include a file</explanation>
  <mustExist>1</mustExist>
</fileParameter>
Using a <booleanParameterGroup> to show optional configuration options

<booleanParameterGroup>
  <name>advanced</name>
  <description>Advanced Mode</description>
  <parameterList>
    <choiceParameter>
      <name>emailNotifications</name>
      <description>Email notifications</description>
      <value>always</value>
      <allowEmptyValue>1</allowEmptyValue>
      <displayType>combobox</displayType>
      <ordering>default</ordering>
      <width>40</width>
      <optionList>
        <option description="Always send notifications"
          text="Always" value="always" />
        <option description="Never send notifications"
          text="Never" value="never" />
      </optionList>
    </choiceParameter>
    <stringParameter name="subject"
      description="Notifications Subject"
      value="[NOTIFICATION] #" />
    <directoryParameter name="cacheDir"
      description="Cache Dir"
      value="${system_temp_directory}/cache" />
  </parameterList>
</booleanParameterGroup>
Using a <choiceParameterGroup> to show multiple options for registration

<choiceParameterGroup>
  <name>keyChoice</name>
  <description>Select how to provide your license key </description>
  <parameterList>
    <fileParameter
      name="keyFile"
      description="Load from file"/>
    <stringParameter
      name="licenseText"
      description="Enter license key"/>
  </parameterList>
</choiceParameterGroup>
<booleanParameterGroup> page with embedded <choiceParameterGroup>

<booleanParameterGroup>
  <name>registerNested</name>
  <description>Register Installation</description>
  <value>1</value>
  <validationType>ifSelected</validationType>
  <parameterList>
    <stringParameter>
      <name>registerUser</name>
      <description>Username</description>
    </stringParameter>
    <choiceParameterGroup>
      <name>registerKeyChoice</name>
      <description>Select how to provide your license key</description>
      <parameterList>
        <fileParameter
          name="registerKeyFile"
          description="Load from file"/>
        <stringParameter
          name="registerLicenseText"
          description="Enter license key"/>
      </parameterList>
    </choiceParameterGroup>
  </parameterList>
</booleanParameterGroup>
Show multiple lines of text with an <infoParameter>

<infoParameter>
  <name>final_review</name>
  <title>Almost done</title>
  <value>These were some examples of what parameters in InstallBuilder
allow you to do in a simple and intuitive way.

After the installation there will be more examples of parameters.</value>
</infoParameter>
Show a clickable link using a <linkParameter>

<linkParameter>
  <name>open_browser</name>
  <title>Open Browser</title>
  <explanation>You can also add parameters to be shown after the installation is complete.

Here's a link parameter:</explanation>
  <insertAfter>installation</insertAfter>
  <clickedActionList>
    <launchBrowser>
      <url>http://www.bitrock.com</url>
    </launchBrowser>
  </clickedActionList>
  <description>Open BitRock Website</description>
</linkParameter>

2.5.4. Actions and when they are executed

This project shows when actions are run during build, before, during and after the installation, uninstallation and actions related to parameters.

Actions run during various stages of installation and uninstallation and can be set for both project and its individual components.

More information about when certain actions are run and their execution order can be found in the action list section.

2.5.5. Creating multiple components

This is a basic project with multiple components and shows how components can be put in separate files.

It shows how the <include> tag can be used to extract components into external files, which can be reused in multiple projects. You can use this approach to create reusable features such as Apache, MySQL or Tomcat and use them as construction blocks in your projects.

You can find more information about the <include> directive in the adding components from external files section.

2.6. Additional Support Resources

In addition to the current document, you can find additional information regarding developing with InstallBuilder in the following resources:

  • A Community Support Forum found at answers.bitrock.com

  • A Relax-NG schema (InstallBuilder.rng) is bundled in the docs directory. It can be used with code editors to validate the code being written.

  • We aim to provide useful and timely support services. If you have any questions or suggestions, please do not hesitate to contact us online at http://installbuilder.bitrock.com/contact-support.html or email us at support@bitrock.com

3. Architecture

3.1. Installer basics

3.1.1. Structure of a Generic Installer

At a high level, you can think of an installer as three related components (resources, logic and user input) delivered together as part of an installation package.

  • Installation Resources

These are the objects that will be bundled in the installer to be delivered to the end-user machine. They may be executable files for your software, SQL scripts or image files.

  • Installation Logic

The installation logic specifies a set of actions that will be performed on the resources, such as copying files around and substituting values in them or the system itself, starting or stopping services or creating a new user. The installation logic can be conditional, based on a set of rules that can take into account multiple factors such as the operating system the installer is running on or which options the end-user selected.

  • External Input

Often, you want to make the installation logic depend on input from the end user, such as the installation directory or the TCP/IP port the application should listen to. The user input is usually collected through a GUI frontend, but could also be provided using command line options passed to the installer or written in a response file.

  • Installation Package

The installation package contains the installation logic and resources. It can be a self-contained executable or a native package, such as an RPM or Debian package.

The following section explains how the previous concepts are implemented within InstallBuilder.

3.1.2. Structure of a BitRock Installer

  • Installation Resources

InstallBuilder supports multiple types of resources. The most important ones are files and directories that will be bundled when the installer is created, but also supports desktop and start menu shortcuts. Files and directories get assigned to folders, which specify a location in the target machine. The location does not need to be fixed and can be changed at runtime. Installer resources can be further organized in components that specify multiple folders and shortcuts that go together. In addition to the resources that will be installed in the end user’s system, there are resources for customizing the installer itself, such as graphics, language files and descriptions of the installer screens.

  • Installation Logic

InstallBuilder allows controlling the flow of the installation using actions and rules. InstallBuilder includes built-in actions for the most common functionality, such as creating users, starting services or changing file permissions, but it is also possible to invoke external programs. Actions can be run at multiple points during the installer lifecycle, such as at build time, startup time or when certain UI screens are displayed. Rules can be attached to these actions to decide which of them should be executed at runtime based on the external input.

  • External Input

InstallBuilder presents a set of pages to collect user input in addition to a command line interface. It is also possible to retrieve environment variables or information about the OS in which the installer is running.

  • Installation Package

By default, InstallBuilder generates single-file, self-contained installers which can easily be distributed over the Internet. The end user just needs to download the file, and double-click or execute it from a console prompt in order to launch the installer. It is also possible to generate multiplatform CDROM/DVD installers and native Linux packages, such as Debian and RPM. For native packages, the end result of the build process is an .rpm or .deb package that contains the installation files and a small binary that encapsulates the installation logic and will be run automatically at package install time. Installation values are fixed at build time for native packages and there is no external input collected at runtime.

4. Variables

4.1. Basic Syntax

Installer variables are an important concept in InstallBuilder. They allow you to store user input, temporary values, establish flags and use that information at different points during the build and installation processes. There are a number of built-in variables and you are also able to create them directly. The basic way of creating or changing the value of a variable in InstallBuilder is using the <setInstallerVariable> action:

 <setInstallerVariable name="foo" value="bar"/>

The action above will store the value bar in the variable foo. Once you have defined the variable, its value can be accessed in any other part of the project as ${foo}. If you require a variable that you are creating at install time to be also available in the uninstallation steps, you have to set the optional persist attribute to 1:

 <setInstallerVariable name="foo" value="bar" persist="1"/>

Variable names must not contain characters other than digits, letters, dashes and underscores. There is only one exception to this rule: it is possible to use a variable as part of the name of another variable (as long as it is a valid one).

For example, if you have a variable foo with a value of bar, then:

 <setInstallerVariable name="${foo}" value="Hello"/>

will be equivalent to:

 <setInstallerVariable name="bar" value="Hello"/>

In addition to regular variables, parameters can also be accessed as variables. One good example is the well-known installdir variable which is in reality a <directoryParameter>:

<runProgram program="${installdir}/myApplication.run" programArguments="--install"/>

Some additional information to take into account when working with variables is:

  • Curly brackets are mandatory: Although the syntax is similar to the notation used in Unix bash-like shells to access variables, it is not the same. If $foo is used instead of ${foo}, it will not be resolved but treated as a literal string.

  • Accessing an undefined variable will not throw an error. Instead, if the variable name was bar, the value will be set to ***unknown variable bar***

  • Variables are not case sensitive. This means that you can use any of the following variants, ${variablename}, ${VariableName} or ${VARIABLENAME} and obtain the same value in all cases.

4.2. Modifier Suffixes

When accessing a variable, some operations can be specified through the usage of special suffixes:

  • ${installdir.dos}: If the variable contains a path, this modifier returns the DOS-style name for it. This will only take effect if the file exists and the platform is Windows. This is particularly useful when the value of the variable may contain spaces and you need to pass it as an argument to a program. Using the .dos suffix will remove the need of quoting the path as spaces will be removed. Take into account that using .dos over a path with forward slashes won’t convert them to backslashes.

  • ${installdir.unix}: If the variable contains a path, it will be converted to a Unix-style path and all of the backslashes will be translated into forward slashes. This will only take effect if the platform is Windows.

  • ${myPassword.password}: The .password suffix is used to mark a variable as a password to be hidden in the logs. This way, you can use a password as an argument in a <runProgram> action and log the execution without showing the plain text password. For example, the following action:

     <setInstallerVariable name="pass" value="myhiddenpassword!"/>
     <runProgram>
         <program>mysql</program>
         <programArguments>-u root --password=${pass.password}</programArguments>
     </runProgram>

will be logged as:

Executing mysql -u root --password=****
Script exit code: 0

Please note this suffix is only considered when resolving variables that will be used when writing to the installation log or in the error messages thrown by the <runProgram> and <setInstallerVariableFromScriptOutput> actions. For example, <logMessage> will interpret the suffix when logging its information but <writeFile> will ignore it.

  • ${myVariable.escape_backslashes}: This will escape all of the backslashes in the text stored in the variable. It is especially useful for substitution of values in Java property files.

  • ${installdir.dos.unix.escape_backslashes}: The modifiers can be combined.

The below table summarizes all the suffixes:

Original value

Modifier

Resolved value

alongfilename.txt

${installdir.dos}

ALONGF~1.TXT

c:\Program Files\myFile.exe

${installdir.unix}

c:/Program Files/myFile.exe

c:\Program Files\myFile.exe

${myVariable.escape_backslashes}

c:\\Program Files\\myFile.exe

c:\Program Files\myLongFile.exe

${installdir.dos.unix}

C:/PROGRA~1/MYLONG~1.EXE

Note
Convert forward slashes to backslashes

InstallBuilder does not have a modifier suffix to convert forward slashes to backslashes the same way as the .unix suffix does. To achieve the same result you just have to use a <setInstallerVariableFromRegEx> action:

 <setInstallerVariableFromRegEx>
    <name>backslash_path</name>
    <pattern>/</pattern>
    <substitution>\</substitution>
    <text>${forwardslash_path}</text>
 </setInstallerVariableFromRegEx>

The above will store the backslash-version of the Unix-like ${forwardslash_path} in the backslash_path variable.

4.3. Accessing Environment Variables

It is possible to access any environment variable using the ${env(varname)} construct, where varname is the name of an environment variable. For example, on Windows you can refer to the system drive with ${env(SYSTEMDRIVE)} and, on Linux, Mac OS X and other Unix systems to the user home directory with ${env(HOME)}

To get a list of the environment variables on your system that will be available to the installer you can execute:

  • On Windows Systems: Open a command window and execute: set

  • On Unix Systems: Open a console and execute: env

Both commands will print a list of the defined environment variables. However, you must take into account that some of these variables could vary from one machine to another.

4.4. Advanced syntax

Almost all of the elements of an InstallBuilder project can be accessed and modified as variables. This makes InstallBuilder a very versatile tool because it allows installers to customize themselves at runtime, based on the environment or on end user feedback. The three basic elements which can be accessed are:

4.4.1. Project properties

All of the project properties such as <version>, <shortName>, <installerFilename> and so on, can be referenced using the notation ${project.property}. For example, ${project.shortName} for the <shortName>. Similarly to regular variables, you can use any capitalization when referencing an element. Using ${PrOjEct.InstallerFilename} is equivalent to using ${project.installerFilename}.

The below example changes the <installationType> at runtime to perform an upgrade if the previous installed version, stored in an environment variable, is lower than the current one:

<project>
   ...
   <shortName>myProduct</shortName>
   <installationType>normal</installationType>
   ...
   <initializationActionList>
     <setInstallerVariable>
       <name>project.installationType</name>
       <value>upgrade</value>
       <ruleList>
         <!-- Check that the env variable exists -->
         <compareText>
            <text>${env(MYPRODUCT_VERSION)}</text>
            <logic>does_not_equal</logic>
            <value></value>
         </compareText>
         <!-- Compare the versions -->
         <compareVersions>
            <version1>${project.version}</version1>
            <logic>greater</logic>
            <version2>${env(MYPRODUCT_VERSION)}</version2>
         </compareVersions>
       </ruleList>
     </setInstallerVariable>
   </initializationActionList>
   ...
</project>

You can refer to the Project Properties appendix for the complete list of properties.

4.4.2. Components

Using this notation you can also modify component settings:

  • ${project.component(default).selected}

  • ${project.component(mysql).show}

This allows, for example, disabling components at runtime when the user does not provide a license key:

<stringParameter>
  <name>licenseKey</name>
  <description>Please provide a license key. If you leave the field empty
  you just will be able to test the basic functionality</description>
  <insertBefore>components</insertBefore>
  <postShowPageActionList>
    <actionGroup>
      <actionList>
        <setInstallerVariable>
          <name>project.component(premiumComponent).selected</name>
          <value>0</value>
        </setInstallerVariable>
        <setInstallerVariable>
          <name>project.component(premiumComponent).canBeEdited</name>
          <value>0</value>
        </setInstallerVariable>
      </actionList>
      <ruleList>
        <compareText>
          <text>${licenseKey}</text>
          <logic>equals</logic>
          <value></value>
        </compareText>
      </ruleList>
    </actionGroup>
  </postShowPageActionList>
</stringParameter>

You can refer to the Components appendix for the complete list of properties.

4.4.3. Parameters

Using the advanced syntax on parameters will allow you to modify not only their values but their entire set of properties such as <description>, <explanation> and the especially useful <ask>. The basic usage is:

${project.parameter(nameOfTheParameter).propertyName}

For example:

  • ${project.parameter(installdir).value}

  • ${project.parameter(tomcat).description}

  • ${project.parameter(mySQL).default}

If the parameter to access is a child of a <parameterGroup>, the parent must also be specified. For example, the port parameter in the below code:

<project>
  ...
  <parameterList>
    <parameterGroup>
      <name>mysqlConfiguration</name>
      <parameterList>
        <stringParameter name="port" description="MySQL port" value="3306"/>
        <passwordParameter name="password" description="MySQL root password" value=""/>
        ...
      </parameterList>
    </parameterGroup>
  </parameterList>
  ...
</project>

Can be accessed using:

${project.parameter(mysqlConfiguration).parameter(port).value}

If the parameters are also included inside a component, instead of directly under the <project> <parameterList>, it must be also specified. For example, reusing the above example:

<project>
  ...
  <componentList>
    <component>
      <name>mySQL</name>
      <parameterList>
        <parameterGroup>
          <name>mysqlConfiguration</name>
          <parameterList>
            <stringParameter name="port" description="MySQL port" value="3306"/>
            <passwordParameter name="password" description="MySQL root password" value=""/>
            ...
          </parameterList>
        </parameterGroup>
      </parameterList>
    </component>
  </componentList>
  ...
</project>

The parameter should now be accessed using:

${project.component(mysql).parameter(mysqlConfiguration).parameter(port).value}

You can use this functionality to disable pages or parameters at runtime based on the user input:

<project>
  ...
  <componentList>
   <component>
     <name>mySQL</name>
     <parameterList>
       <booleanParameter>
         <name>enableAdvanced</name>
         <description>Do you want to enable the advanced configuration?</description>
         <postShowPageActionList>
           <!-- Enable the page, which is disabled by default -->
           <setInstallerVariable>
             <name>project.component(mySQL).parameter(mysqlAdvanced).ask</name>
             <value>1</value>
             <ruleList>
                <isTrue value="${project.component(mySQL).parameter(enableAdvanced).value}"/>
             </ruleList>
           </setInstallerVariable>
         </postShowPageActionList>
       </booleanParameter>
       <parameterGroup>
          <name>mysqlAdvanced</name>
          <parameterList>
             <stringParameter name="mysqlPort" description="MySQL port" value="3306"/>
             <passwordParameter name="mysqlPassword" description="MySQL root password" value=""/>
             ...
          </parameterList>
       </parameterGroup>
     </parameterList>
   </component>
  </componentList>
  ...
</project>

Parameters are also handy when you want to preserve variables defined at build time. Accessing a variable defined in the <preBuildActionList> at runtime will result in an ***unknown variable varName*** error. To workaround this issue, you could use a hidden parameter (setting ask="0"), that won’t be displayed in the help menu nor the installer pages. For example, to pass a random generated key for each of the built installers you could use the below code:

<project>
  ...
  <parameterList>
    ...
    <stringParameter name="build_identifier" value="" ask="0"/>
    ...
  </parameterList>
  <preBuildActionList>
     <!-- Create random identifier for the build -->
     <generateRandomValue>
       <variable>build_identifier</variable>
     </generateRandomValue>
     <!-- Date of the build -->
     <createTimeStamp>
        <variable>timestamp</variable>
     </createTimeStamp>
     <!-- Register the build information in a local file -->
     <addTextToFile>
        <file>${build_project_directory}/builds</file>
        <text>${build_identifier} - Product Version: ${project.version} - IB Version: ${installer_builder_version} - Built On: ${timestamp}</text>
     </addTextToFile>
  </preBuildActionList>
  ...
</project>

As you are using a hidden parameter, the ${build_identifier} will be available at runtime and you could, for example, send it to your server using an <httpPost> action to register the installations for each release:

  <postInstallationActionList>
     ...
     <httpPost url="http://www.example.com/register.php" filename="${installdir}/activationUrl">
        <queryParameterList>
           <queryParameter name="build_identifier" value="${build_identifier}"/>
           <queryParameter name="version" value="${project.version}"/>
        </queryParameterList>
     </httpPost>
  </postInstallationActionList>
Note
Accessing a parameter as a regular variable

If you try to access a parameter as if it were a regular variable, it will give you its value. That is, using ${installdir} or ${project.parameter(installdir).value} will return the same result.

The advantage of using the long notation is that it provides a very descriptive path to the element you are modifying. For example, if you are working with a very big project that is maintained by multiple developers and divided into multiple files using the <include> directive, locating where the below values are located could be troublesome (they could be parameters or regular variables, located in any of the included files or the main project):

   <throwError text="You have selected strict password checking and your password is too short" >
     <ruleList>
       <isTrue value="${enableStrictChecking}"/>
       <compareTextLength>
         <text>${password}</text>
         <logic>less</logic>
         <length>${minLength}</length>
       </compareTextLength>
     </ruleList>
   </throwError>

Where using the long location will point you directly to where they are defined (assuming the included files are named according to the component names, for example):

   <throwError text="You have selected strict password checking and your password is too short" >
     <ruleList>
       <isTrue value="${project.component(settings).parameter(basicConfiguration).parameter(enableStrictChecking).value}"/>
       <compareTextLength>
         <text>${password}</text>
         <logic>less</logic>
         <length>${project.component(settings).parameter(defaultPasswordSettings).parameter(minLength).value}</length>
       </compareTextLength>
     </ruleList>
   </throwError>

In addition to the above-mentioned elements, any other tag in the XML project with a unique identifier can be referenced. For example, is possible to reference a folder in a component to get its destination:

`<showInfo text="${project.component(mysql).folder(mysqlConfig).destination}"/>`

But not a file in its <distributionFileList> because files do not have a unique name.

4.5. Accessing Language Strings

You can also access language strings, either built-in or user-defined (check the Languages section for more details), using the special notation ${msg(stringKey)}. It will be resolved to the localized string identified by the key stringKey in the current installation language:

   <showInfo text="${msg(hello.world)}"/>

If you have defined the hello.world localized string in the <customLanguageFileList>, depending on the installation language you will get results such as Hello world!, Hola Mundo! or Hallo Welt.

4.6. Escaping Variables

In some cases, for example when modifying shell scripts programmatically, you may need a literal ${foo} instead of the contents of the foo variable (which may result in an ***unknown variable foo***). For these cases, InstallBuilder implements a special notation to specify that you want the text treated literally, without trying to be resolved: ${'${variableName}'}.

For example, ${'${foo}'} will be resolved to: ${foo}. More complex text can be escaped as shown in the snippet below:

     <writeFile>
       <path>~/.bashrc</path>
        <text>${'
PATH=${PATH}:/some/path
Foo=${bar}
'}</text>
     </writeFile>

It will write:

PATH=${PATH}:/some/path
Foo=${bar}

As shown in the example, it accepts line breaks in the text to escape. The only limitation is that it cannot contain the characters '} in the text to escape or it will be interpreted as the end of the escaped reference.

4.7. Nested Variables

Nested variables are also allowed. They will be evaluated from the most inner reference:

     <showInfo>
       <text>${text_${foo-${i}}_${bar}}</text>
     </showInfo>

This feature is especially useful when iterating using a <foreach> action. For example, if you have a list of component names and you want to create a list with those that are selected:

<setInstallerVariable name="selectedComponents" value=""/>
<foreach variables="component" values="componentA componentB componentC componentD">
   <actionList>
      <setInstallerVariable name="slectedComponents" value="${selectedComponents} ${component}" >
         <ruleList>
            <isTrue value="${project.component(${component}).selected"/>
         </ruleList>
      </setInstallerVariable>
  </actionList>
</foreach>

4.8. Built-in variables

InstallBuilder also provides a list of built-in variables containing information about the installer or the environment in which it is executed:

Java
  • java_autodetected: Whether or not a valid Java was autodetected

    Possible values:

    0, 1

  • java_executable: Location of the autodetected Java executable

    Example values:

    /usr/bin/java, c:/Program Files/Java/jre1.6.0_10/bin/java.exe

  • java_vendor: Autodetected Java vendor

    Possible values:

    Any, IBM, Sun

  • java_version: Autodetected Java version

    Example values:

    1.6.0, 1.5.0

  • java_version_full: Autodetected Java full version

    Example values:

    1.6.0_07, 1.5.0_11

  • java_version_major: Autodetected Java major version

    Example values:

    1.6, 1.5

  • javaw_executable: Autodetected javaw executable path

    Example values:

    /usr/bin/java, c:/Program Files/Java/jre1.6.0_10/bin/java.exe

  • javaws_executable: Location of the autodetected Java Web Start executable

    Example values:

    /usr/bin/javaws, c:/Program Files/Java/jre1.6.0_10/bin/javaws.exe

User Interface
  • installer_interactivity: The level of interactivity of the installation mode

    Possible values:

    none, normal, minimalWithDialogs, minimal

  • installer_ui: The mode in which the installer is run

    Possible values:

    unattended, gui, text

  • installer_ui_detail: The detailed mode in which the installer is run

    Possible values:

    unattended, xwindow, qt, text, osx, gtk, win32

.NET Framework
  • dotnet_autodetected: Whether or not a valid .NET framework was autodetected

    Possible values:

    0, 1

  • dotnet_framework_type: .NET framework type

    Possible values:

    , full, client

  • dotnet_version: .NET framework version

    Example values:

    2.0, 3.5, 4.0

Installer
  • installation_aborted_by_user: Whether or not installation was manually aborted by user

    Possible values:

    0, 1

  • installation_finished: Whether or not the installation finished successfully

    Possible values:

    0, 1

  • installation_guid: Unique installation ID

    Example values:

    47af77eb-9a55-484c-5093-9337963ef106

  • installation_language_code: Language code of the installation

    Possible values:

    es, sv, ro, et, ko, cy, pt, it, da, tr, sk, va, sl, ru, pt_BR, fr, bg, de, el, zh_CN, hr, es_AR, nl, ja, en, ar, zh_TW, sq, pl, ca, no, hu, he, cs, fi

  • installer_builder_timestamp: Timestamp of the InstallBuilder used to build the installer

    Example values:

    201001220702

  • installer_builder_version: Version of InstallBuilder used to build the installer

    Example values:

    6.2.7

  • installer_command_line_arguments: Command line arguments as passed to installer

    Example values:

    --mode gtk, --installdir /opt/app-1.0

  • installer_exit_code: Installer Exit Code value. It is equal 0 by default and set to 0 if there was an error executing an action.

  • installer_installation_log: The location of the installer log

    Example values:

    /tmp/bitrock_install.log, C:\Documents and Settings\user\Local Settings\Temp

  • installer_is_root_install: Whether or not the current user has root privileges

    Possible values:

    0, 1

  • installer_package_format: Type of installer

    Possible values:

    executable

  • program_exit_code: Exit code from program; set by runProgram and setInstallerVariableFromScriptOutput actions

    Example values:

    0, 1

  • program_stderr: Program’s error output; set by runProgram and setInstallerVariableFromScriptOutput actions

    Example values:
  • program_stdout: Program’s output; set by runProgram and setInstallerVariableFromScriptOutput actions

    Example values:
  • required_diskspace: Required disk space to install the application in Kilobytes

    Example values:

    10000, 25000

Windows Folders
  • windows_folder_program_files: Directory for program files

    Example values:

    C:\Program Files

  • windows_folder_program_files_common: Directory for components shared across applications

    Example values:

    C:\Program Files\Common Files

  • windows_folder_system: Windows system directory

    Example values:

    C:\Windows\system32

  • windows_folder_systemroot: Windows root directory

    Example values:

    C:\Windows

  • windows_folder_windows: Windows root directory

    Example values:

    C:\Windows

Windows Folders - System Scope
  • windows_folder_common_admintools: Directory that stores administrator tools for all users

    Example values:

    C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Administrative Tools

  • windows_folder_common_appdata: Directory that stores common application-specific data

    Example values:

    C:\ProgramData

  • windows_folder_common_desktopdirectory: Directory that stores common desktop files

    Example values:

    C:\Users\Public\Desktop

  • windows_folder_common_documents: Directory that stores common document files

    Example values:

    C:\Users\Public\Documents

  • windows_folder_common_favorites: Directory that stores common favorite items

    Example values:

    C:\Users\Administrator\Favorites

  • windows_folder_common_music: Directory that stores common music files

    Example values:

    C:\Users\Public\Music

  • windows_folder_common_pictures: Directory that stores common picture files

    Example values:

    C:\Users\Public\Pictures

  • windows_folder_common_programs: Directory that stores common program groups in start menu

    Example values:

    C:\ProgramData\Microsoft\Windows\Start Menu\Programs

  • windows_folder_common_startmenu: Directory that stores common start menu items

    Example values:

    C:\ProgramData\Microsoft\Windows\Start Menu

  • windows_folder_common_startup: Directory that stores common Startup program group

    Example values:

    C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup

  • windows_folder_common_templates: Directory that stores common templates

    Example values:

    C:\ProgramData\Microsoft\Windows\Templates

  • windows_folder_common_video: Directory that stores common video files

    Example values:

    C:\Users\Public\Videos

Cross-platform Folders
  • installdir: The installation directory

    Example values:

    /home/user/programx, C:\Program Files\programx

  • installer_directory: The directory location of the installer binary

    Example values:

    /home/user/example, C:\example

  • installer_pathname: The full path of the installer binary

    Example values:

    /home/user/example/installer.bin, C:\example\installer.exe

  • platform_install_prefix: The platform specific default installation path

    Example values:

    /home/user, C:\Program Files, /Applications

  • system_temp_directory: Path to the system’s temporary directory

    Example values:

    /tmp, C:\Documents and Settings\Username\Local Settings\Temp

  • user_home_directory: Path to the home directory of the user who is running the installer

    Example values:

    /home/username, C:\Documents and Settings\Username

Build-time Variables
  • build_project_directory: Directory containing the XML project used to generate the installer.

    Example values:

    /home/username/installbuilder-7.0.0/projects, C:\Program Files\Bitrock InstallBuilder for Windows 7.0.0\projects

  • installbuilder_install_root: Installation directory of InstallBuilder. This variable is available only at build time, as it does not make sense to access this information at runtime

    Example values:

    /home/username/installbuilder-7.0.0, C:\Program Files\Bitrock InstallBuilder for Windows 7.0.0

  • installbuilder_ui: The mode in which the builder is run

    Possible values:

    gui, text

Windows Folders - User Scope
  • windows_folder_admintools: Directory that stores administrator tools for individual user

    Example values:

    C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Administrative Tools

  • windows_folder_appdata: Directory that stores user application-specific data

    Example values:

    C:\Users\Administrator\AppData\Roaming

  • windows_folder_cookies: Directory that stores user cookies

    Example values:

    C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Cookies

  • windows_folder_desktopdirectory: Directory that stores user desktop files

    Example values:

    C:\Users\Administrator\Desktop

  • windows_folder_favorites: Directory that stores user favorite items

    Example values:

    C:\Users\Administrator\Favorites

  • windows_folder_history: Directory that stores user Internet history items

    Example values:

    C:\Users\Administrator\AppData\Local\Microsoft\Windows\History

  • windows_folder_internet_cache: Directory that stores user temporary internet files

    Example values:

    C:\Users\Administrator\AppData\Local\Microsoft\Windows\Temporary Internet Files

  • windows_folder_local_appdata: Directory that stores user local (non-roaming) repository for application-specific data

    Example values:

    C:\Users\Administrator\AppData\Local

  • windows_folder_mymusic: Directory that stores user music files

    Example values:

    C:\Users\Administrator\Music

  • windows_folder_mypictures: Directory that stores user picture files

    Example values:

    C:\Users\Administrator\Pictures

  • windows_folder_myvideo: Directory that stores user video files

    Example values:

    C:\Users\Administrator\Videos

  • windows_folder_nethood: Directory that stores user network shortcuts

    Example values:

    C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Network Shortcuts

  • windows_folder_personal: Directory that stores user document files

    Example values:

    C:\Users\Administrator\Documents

  • windows_folder_printhood: Directory that stores printer shortcuts

    Example values:

    C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Printer Shortcuts

  • windows_folder_profile: Directory that stores user profile

    Example values:

    C:\Users\Administrator

  • windows_folder_programs: Directory that stores user program groups in start menu

    Example values:

    C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Programs

  • windows_folder_recent: Directory that stores shortcuts to user’s recently used documents

    Example values:

    C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Recent

  • windows_folder_sendto: Directory that stores user Send To menu items

    Example values:

    C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\SendTo

  • windows_folder_startmenu: Directory that stores user start menu items

    Example values:

    C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu

  • windows_folder_startup: Directory that stores user Startup program group

    Example values:

    C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup

  • windows_folder_templates: Directory that stores user templates

    Example values:

    C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Templates

Linux Specific
  • linux_distribution: Type of Linux distribution

    Possible values:

    gentoo, suse, redhat, redflag, slackware, fedora, arch, mandrake, debian

  • linux_distribution_codename: Linux distribution code name (based on Linux Standard Base tool: lsb_release)

  • linux_distribution_description: Linux distribution description (based on Linux Standard Base tool: lsb_release)

    Example values:

    Debian, GNU/Linux

  • linux_distribution_fullname: Linux distribution fullname

    Possible values:

    Suse, Scientific Linux, Fedora, Core, Flag, openSUSE, Red, Mandrake, Red Hat Linux, Red Hat Enterprise Linux, Debian, Gentoo, CentOS, SME Server Linux, Slackware, Arch

  • linux_distribution_id: Linux distribution distributor’s ID (based on Linux Standard Base tool: lsb_release)

    Example values:

    Debian

  • linux_distribution_release: Linux distribution release number(based on Linux Standard Base tool: lsb_release)

    Example values:

    3.1

  • linux_distribution_shortname: Linux distribution shortname

    Possible values:

    gentoo, suse, redflag, slackware, fedora, arch, rh, mandrake, debian, rhel

  • linux_distribution_version: Linux distribution mayor version

    Example values:

    5.0

OSX Specific
  • osx_major_version: OSX major version number

    Example values:

    10.3, 10.5

  • osx_version: OSX version number

    Example values:

    10.3.9, 10.5.7

Windows Specific
  • windows_os_family: Type of Windows OS

    Possible values:

    Windows NT, Windows 95

  • windows_os_family_shortname: Windows OS family shortname

    Possible values:

    winnt, win9x

  • windows_os_flavor: Flavor of Windows OS

    Possible values:

    Home Premium, Enterprise, Home, Standard, Home Basic, Ultimate, Server, Web Edition, Data Center, Business, Workstation, Advanced Server, Professional, Starter

  • windows_os_name: Windows OS name

    Possible values:

    Windows 2003, Windows 98, Windows 2008 R2, Windows 2008, Windows 2000, Windows 95, Windows Vista, Windows 7, Windows XP, Windows 7 WSLK

  • windows_os_service_pack: Windows OS Service Pack version number

    Example values:

    1, 2, 3

  • windows_os_uac_enabled: Whether or not UAC is enabled

    Possible values:

    0, 1

  • windows_os_version_number: Windows OS version number

    Possible values:

    6.0, 5.1, 7.0, 6.1, 5.2, 4.0, 5.0, 4.1

System Configuration
  • machine_cpu_count: Number of CPUs in the machine

    Example values:

    1, 2

  • machine_cpu_speed: The machine’s CPU speed in MHZ

    Example values:

    1500

  • machine_fqdn: The machine’s fully qualified domain name

    Example values:

    bitrock-desktop.mydomain.com

  • machine_hostname: The machine’s hostname

    Example values:

    example.com

  • machine_ipaddr: The machine’s IP address

    Example values:

    10.0.0.2

  • machine_total_memory: The machine’s total physical memory in MB

    Example values:

    512

  • platform_exec_suffix: The platform specific binary suffix

    Possible values:

    app, run, exe

  • platform_has_smp: Whether or not the machine has multiple processors

    Possible values:

    0, 1

  • platform_name: At build-time, it contains the target build platform. At runtime, the platform in which the installer is running

    Possible values:

    linux, osx, windows

  • platform_path_separator: The platform specific path separator

    Possible values:

    \, /

  • system_locale: Current system locale

    Possible values:

    es, sv, ro, et, ko, cy, pt, it, da, tr, sk, va, sl, ru, pt_BR, fr, bg, de, el, zh_CN, hr, es_AR, nl, ja, en, ar, zh_TW, sq, pl, ca, no, hu, he, cs, fi

  • system_username: Name of the user who is running the installer

    Example values:

    root, Administrator, guest

Installer Page Order Control
  • back_page: The previous page to show

    Example values:

    installdir, welcome, installation, installationFinished

  • next_page: The next page to show

    Example values:

    installdir, welcome, installation, installationFinished

5. Components

Depending on the complexity of your software, you may need to split your project into several components. Components are a bundle of folders and associated installation logic.

They are able to execute actions (include Action Lists), copy files and prompt the user for data (display Parameters), as the project does:

<component>
    <name>component</name>
    <description>component</description>
    <detailedDescription>This is a component</detailedDescription>
    <initializationActionList>
        <setInstallerVariable name="my_variable" value="1" />
    </initializationActionList>
    <parameterList>
        <booleanParameter>
            <name>boolean_question</name>
            <title>Boolean Question</title>
            <description>Please answer yes or no</description>
        </booleanParameter>
    </parameterList>
    <folderList>
        <folder>
            <description>Program Files</description>
            <destination>${installdir}</destination>
            <name>programfiles</name>
            <platforms>all</platforms>
            <distributionFileList>
                <distributionDirectory origin="program" />
            </distributionFileList>
        </folder>
    </folderList>
</component>

The ability to enable / disable components at build time and runtime allows your installer to provide as many setup combinations as you need.

The basic properties you should configure when adding a component are:

  • <name>: Name of the Component. This name must be unique and just contain alphanumeric characters and underscores.

  • <description>: Description of the Component. This description will be included in the list of the visible components presented to the user.

  • <detailedDescription>: A detailed description of the component. This detailed description will be displayed when clicking in the component description in the component selection page.

  • <selected>: Whether or not the component is selected. If the component is not selected, its action lists won’t be executed and its folders won’t be unpacked.

  • <show>: Whether or not the component is visible in the component selection page.

  • <canBeEdited>: Whether or not the component can be edited in the component selection page.

  • <requiredSize>: Required disk space in the target system. If 0, then it will automatically be calculated based on the size of the packed files. The sum of the sizes of all of the installed components can be later accessed through the built-in variable ${required_diskspace}.

Components are defined in the project <componentList> and presented to the end user as in the Figure 23:

Component Selection Page
Figure 23: Component Selection Page

As mentioned above, depending on the value of <show>, the component will be visible or not, and if so, the <canBeEdited> property will decide if the user will be able to select and deselect it.

The example below illustrates some of the possible combinations when including components:

<project>
    ...
    <!-- Shows the component selection page -->
    <allowComponentSelection>1</allowComponentSelection>
    ...
    <componentList>
        <!-- Main base component, it must be always
        installed. We hide it  -->
        <component>
            ...
            <name>main</name>
            <selected>1</selected>
            <show>0</show>
            ...
        </component>
        ...
        <!-- Important required component. We show it
        in the component selection but made it mandatory
        to install -->
        <component>
            ...
            <name>core</name>
            <description>Core product</description>
            <detailedDescription>This is the base of the application.</detailedDescription>
            <selected>1</selected>
            <show>1</show>
            <canBeEdited>0</canBeEdited>
            ...
        </component>
        ...
        <!-- Optional Useful Component. We allow deselecting it but we suggest it
        by default setting show=1 -->
        <component>
            ...
            <name>docs</name>
            <description>Documentation</description>
            <detailedDescription>Documentation of the product</detailedDescription>
            <selected>1</selected>
            <show>1</show>
            <canBeEdited>1</canBeEdited>
            ...
        </component>

        <!-- Additional Optional Component. It is not very important so
        we do not include it by default (show=0)  -->
        <component>
            ...
            <name>extra</name>
            <description>Extra files</description>
            <detailedDescription>Extra files including images
            and translation files</detailedDescription>
            <selected>0</selected>
            <show>1</show>
            <canBeEdited>1</canBeEdited>
            ...
        </component>
    </componentList>
    ...
</project>

Please note that the code also enables <allowComponentSelection>1</allowComponentSelection>. This setting makes the component selection page (which is hidden by default) visible to the end user.

5.1. Enabling and disabling components

The easiest way of configuring if a component will be selected or not is by modifying its <selected> property:

<componentList>
   <!-- This component is selected -->
   <component>
     ...
     <name>component1</name>
     ...
     <selected>1</selected>
     ...
   </component>
   <!-- This component is not selected -->
   <component>
     ...
     <name>component2</name>
     ...
     <selected>0</selected>
     ...
   </component>
</componentList>

However, in most of the cases you will need to decide whether to select or not components at runtime, based on certain conditions. For this purpose, InstallBuilder includes a <componentSelection> action. For example, if you detect and existing installation of your product, you may want to deselect your core component and select the update component:

<project>
  ...
  <componentList>
    <component>
      <name>core</name>
      ...
      <selected>1</selected>
      ...
    </component>
    <component>
      <name>update</name>
      ...
      <selected>0</selected>
      ...
    </component>
  </componentList>
  <readyToInstallActionList>
     <componentSelection>
        <deselect>core</deselect>
        <select>update</select>
        <ruleList>
           <fileExists path="${installdir}/wellKnown/file"/>
        </ruleList>
     </componentSelection>
  </readyToInstallActionList>
  ...
</project>

The <componentSelection> action also accepts multiple components to select or deselect, separated by commas, in its <deselect> and <select> tags. This way you can change the behavior of the installer with a single action.

The code below explains how to prompt the user to select between a minimal (core components), standard (core and useful components) and full installation (also include documentation and videos):

<project>
  ...
  <allowComponentSelection>0</allowComponentSelection>
  ...
  <componentList>
    <component>
      <name>core</name>
      ...
    </component>
    <component>
      <name>xmlEditor</name>
      ...
    </component>
    <component>
      <name>debugger</name>
      ...
    </component>
    <component>
      <name>documentation</name>
      ...
    </component>
    <component>
      <name>videos</name>
      ...
    </component>
  </componentList>
  ...
  <parameterList>
     <choiceParameter>
        <name>installationMode</name>
        <ask>1</ask>
        <default>normal</default>
        <description>Please select the installation mode</description>
        <title>Installation Mode</title>
        <optionList>
           <option>
             <value>minimal</value>
             <text>Minimal</text>
           </option>
           <option>
             <value>standard</value>
             <text>Standard</text>
           </option>
           <option>
             <value>full</value>
             <text>Full</text>
           </option>
        </optionList>
        <postShowPageActionList>
           <componentSelection>
              <deselect>xmlEditor,debugger,documentation,videos</deselect>
              <select>core</select>
              <ruleList>
                 <compareText>
                   <text>${installationMode}</text>
                   <logic>equals</logic>
                   <value>minimal</value>
                 </compareText>
              </ruleList>
           </componentSelection>
           <componentSelection>
              <deselect>documentation,videos</deselect>
              <select>core,xmlEditor,debugger</select>
              <ruleList>
                 <compareText>
                   <text>${installationMode}</text>
                   <logic>equals</logic>
                   <value>standard</value>
                 </compareText>
              </ruleList>
           </componentSelection>
           <componentSelection>
              <deselect></deselect>
              <select>core,xmlEditor,debugger,documentation,videos</select>
              <ruleList>
                 <compareText>
                   <text>${installationMode}</text>
                   <logic>equals</logic>
                   <value>full</value>
                 </compareText>
              </ruleList>
           </componentSelection>
        </postShowPageActionList>
     </choiceParameter>
  </parameterList>
  ...
</project>

You can also check the state of a component using the <componentTest> rule:

<throwError>
  <text>You cannot install 'Component A' and 'Component B' at the same time!</text>
  <ruleList>
     <componentTest name="componentA" logic="selected"/>
     <componentTest name="componentB" logic="selected"/>
  </ruleList>
</throwError>

Another way of selecting or deselecting a component is to directly modify the <selected> property using the <setInstallerVariable> action as explained in the Advanced Syntax section:

  <setInstallerVariable name="project.component(core).selected" value="0"/>

The same way, you can check if a component is selected (or any other of its properties):

<directoryParameter>
   <name>installdir</name>
   <validationActionList>
      <actionGroup>
         <actionList>
            <getFreeDiskSpace path="${installdir}" units="KB" variable="diskSpace"/>
            <throwError>
              <text>You don't have enough disk space to install
              ${project.component(bigComponent).description}</text>
              <ruleList>
                <compareValues>
                  <value1>${project.component(bigComponent).requiredSize}</value1>
                  <logic>greater</logic>
                  <value2>${diskSpace}</value2>
                </compareValues>
              </ruleList>
            </throwError>
         </actionList>
         <ruleList>
           <isTrue value="${project.component(bigComponent).selected}"/>
         </ruleList>
      </actionGroup>
   </validationActionList>
</directoryParameter>

Finally, visible and editable components can also be selected and deselected using the command line:

$> /path/to/installer --disable-components windowsdata,unixdata --enable-components osxdata

Where --disable-components and --enable-components accept a comma-separated list of components. Only visible components (<show>1</show>) will be displayed in the help menu and only those which are also editable (<canBeEdited>1</canBeEdited>) will be configurable using these flags. For example, if your project has the component list below:

 <componentList>
    <!-- Main base component, it must be always
    installed. We hide it  -->
    <component>
       ...
       <name>main</name>
       <selected>1</selected>
       <show>0</show>
       ...
    </component>
    ...
    <!-- Important required component. We show it
    in the component selection but made it mandatory
    to install -->
    <component>
       ...
       <name>core</name>
       <description>Core product</description>
       <selected>1</selected>
       <show>1</show>
       <canBeEdited>0</canBeEdited>
       ...
    </component>
    ...
    <!-- Optional Useful Component. We allow deselecting it but we suggest it
    by default setting show=1 -->
    <component>
       ...
       <name>docs</name>
       <selected>1</selected>
       <show>1</show>
       <canBeEdited>1</canBeEdited>
       ...
    </component>
    <!-- Additional Optional Component. It is not very important so
    we do not include it by default (show=0)  -->
    <component>
       ...
       <name>extra</name>
       <selected>0</selected>
       <show>1</show>
       <canBeEdited>1</canBeEdited>
       ...
    </component>
 </componentList>

The output in the help menu will be:

 --enable-components <enable-components> Comma-separated list of components
                                Default: core,docs
                                Allowed: docs extra

 --disable-components <disable-components> Comma-separated list of components
                                Default: extra
                                Allowed: docs extra

In this output, main is not mentioned, as it was configured as hidden, and just docs and extra are allowed values, as core was configured as a non-editable component and always selected.

These command line options are only available if <allowComponentSelection> is enabled.

Note
Only the hardcoded state of the components is considered when displaying the help menu.

As the help menu is completely independent from regular action lists, even if you are changing the components properties in the <initializationActionList> using a <setInstallerVariable> action, the changes won’t be visible when displaying the help. For example:

 <componentList>
    <!-- Main base component, it must be always
    installed. We hide it  -->
    <component>
       ...
       <name>A</name>
       <selected>1</selected>
       <show>0</show>
       ...
    </component>
    <component>
       ...
       <name>B</name>
       <selected>1</selected>
       <show>0</show>
       ...
    </component>
    <component>
       ...
       <name>C</name>
       <selected>1</selected>
       <show>0</show>
       ...
    </component>
 </componentList>
 <initializationActionList>
   <setInstallerVariable name="component(A).show" value="1"/>
   <setInstallerVariable name="component(B).show" value="1"/>
   <setInstallerVariable name="component(C).show" value="1"/>
 </initializationActionList>

Will result in an empty list of components in the help menu:

 --enable-components <enable-components> Comma-separated list of components
                                Default:

 --disable-components <disable-components> Comma-separated list of components
                                Default:

But all of them will be visible and editable in the graphical component selection.

Note
The <selected> property cannot contain variables

The component <selected> tag cannot contain variables. The below component will always be deselected, regardless of the value of the variable:

<project>
  ...
  <componentList>
    <component>
       ...
       <name>documentation</name>
       ...
       <!-- The variable won't be resolved, so it will
       be considered false -->
       <selected>${installDocumentation}</selected>
       ...
    </component>
  </componentList>
  ...
</project>

If you need to bind a boolean variable to the <selected> tag, you should modify the property using a <setInstallerVariable> instead:

<booleanParameter>
    <name>installDocumentation</name>
    <title>Documentation</title>
    <description>Would you like to install the documentation files?</description>
    <postShowPageActionList>
       <setInstallerVariable>
          <name>project.component(documentation).selected</name>
          <value>${installDocumentation}</value>
       </setInstallerVariable>
    </postShowPageActionList>
</booleanParameter>

5.2. Component Action Lists

Components can include all of the Action Lists available for the main project with the exception of the <preShowHelpActionList> and the <finalPageActionList.

In addition, components include a few new action lists:

5.2.1. Component Selection Validation Actions

The <componentSelectionValidationActionList> is executed right after clicking Next in the component selection page and allows checking if the provided component configuration is valid. It works the same way as the <validationActionList>; if an error is thrown inside it, instead of aborting the installation, the error message is displayed and the page redrawn.

This is really useful when implementing dependencies between components:

<project>
    ...
    <allowComponentSelection>1</allowComponentSelection>
    ...
    <componentList>
      <component>
        ...
        <name>A</name>
        ...
      </component>
      <component>
        ...
        <name>B</name>
        ...
      </component>
      <component>
        <name>C</name>
        <description>Component C</description>
        <detailedDescription>This component depends on 'A' and 'B'</detailedDescription>
        ...
        <componentSelectionValidationActionList>
          <throwError>
            <text>Component 'C' cannot be installed if you have not selected both 'A' and 'B'.</text>
            <ruleList>
              <isFalse value="${component(A).selected}"/>
              <isFalse value="${component(B).selected}" />
            </ruleList>
          </throwError>
        </componentSelectionValidationActionList>
        ...
      </component>
      ...
    </componentList>
    ...
</project>

The <componentSelectionValidationActionList> is only executed when the component selection page is displayed and the component defining the validation is selected (regardless of whether or not it is visible). This could be an issue if, for example, you need to validate that at least one of two optional components are selected and if the user deselects them, none of the validations will be executed. In these cases, you can use a hidden component, just used to validate the others:

How to establish dependencies between components

<project>
    ...
    <allowComponentSelection>1</allowComponentSelection>
    ...
    <componentList>
      <component>
        ...
        <name>A</name>
        ...
      </component>
      <component>
        ...
        <name>B</name>
        ...
      </component>
      <component>
        <name>validatorComponent</name>
        <selected>1</selected>
        <show>0</show>
        ...
        <componentSelectionValidationActionList>
          <throwError>
            <text>You have to select at least one component.</text>
            <ruleList>
              <isFalse value="${component(A).selected}"/>
              <isFalse value="${component(B).selected}" />
            </ruleList>
          </throwError>
        </componentSelectionValidationActionList>
        ...
      </component>
      ...
    </componentList>
    ...
</project>

5.2.2. On Download Error Actions

If the component was marked as <downloadable> and the installer was built accordingly (check the Downloadable components section for more details), the <onDownloadErrorActionList> allows providing a set of of actions to execute if the download process fails and the user decides to ignore it.

This allows properly recovering from the error, for example, deselecting other components that depend on it.

5.3. Adding files and directories

Components can also contain a list of <folder> elements, which are mainly used to define files to pack:

<component>
   ...
   <name>default</name>
   ...
   <folderList>
     <!-- The installation directory -->
     <folder>
        <name>programfiles</name>
        <description>Program Files</description>
        <destination>${installdir}</destination>
        <platforms>all</platforms>
        <distributionFileList>
          <distributionFile>
            <origin>/path/to/file.txt</origin>
          </distributionFile>
          ...
          <distributionDirectory>
            <origin>/path/to/directory</origin>
          </distributionDirectory>
          ...
        </distributionFileList>
     </folder>

     <!-- Configuration files that should be installed inside
     /etc, and for linux only -->
     <folder>
        <name>linuxconfigfiles</name>
        <description>Linux Configuration Files</description>
        <destination>/etc</destination>
        <platforms>linux</platforms>
        <distributionFileList>
           ...
        </distributionFileList>
     </folder>
   </folderList>
   ...
</component>

The next section explains in detail how to work with folders.

5.4. Adding shortcuts to the components

Each component has three shortcut lists which can be used to create shortcuts:

 <component>
   <name>default</name>
   ...
   <desktopShortcutList>
     <!-- Intended to launch an application -->
     <shortcut>
        <comment>Launch My Program</comment>
        <exec>${installdir}/bin/myprogram</exec>
        <icon></icon>
        <name>My Program</name>
        <path>${installdir}/bin</path>
        <platforms>all</platforms>
        <runInTerminal>0</runInTerminal>
        <windowsExec>${installdir}/bin/myprogram.exe</windowsExec>
        <windowsExecArgs></windowsExecArgs>
        <windowsIcon></windowsIcon>
        <windowsPath>${installdir}/bin</windowsPath>
     </shortcut>

     <!-- Intended to launch a web browser pointing to a specific url -->
     <linkShortcut>
        <comment>Launch a web browser pointing to My Program website</comment>
        <icon></icon>
        <name>Visit My Program website</name>
        <platforms>all</platforms>
        <runInTerminal>0</runInTerminal>
        <url>http://www.example.com/myprogram</url>
        <windowsIcon></windowsIcon>
     </linkShortcut>

     <!-- Intended to launch a viewer for a specific file -->
     <fileShortcut>
        <comment>Check the user guide</comment>
        <filePath>${installdir}/doc/userguide.pdf</filePath>
        <icon></icon>
        <name>My Program User Guide</name>
        <platforms>all</platforms>
        <runInTerminal>0</runInTerminal>
        <windowsIcon></windowsIcon>
     </fileShortcut>
     ...
   </desktopShortcutList>
   ...
 </component>

 <component>
   <name>default</name>
   ...
   <startMenuShortcutList>
     <!-- Intended to launch an application -->
     <startMenuShortcut>
        <comment>Launch My Program</comment>
        <exec>${installdir}/bin/myprogram</exec>
        <icon></icon>
        <name>My Program</name>
        <path>${installdir}/bin</path>
        <platforms>all</platforms>
        <runInTerminal>0</runInTerminal>
        <windowsExec>${installdir}/bin/myprogram.exe</windowsExec>
        <windowsExecArgs></windowsExecArgs>
        <windowsIcon></windowsIcon>
        <windowsPath>${installdir}/bin</windowsPath>
     </startMenuShortcut>

     <!-- Intended to launch a web browser pointing to a specific url -->
     <startMenuLinkShortcut>
        <comment>Launch a web browser pointing to My Program website</comment>
        <icon></icon>
        <name>Visit My Program website</name>
        <platforms>all</platforms>
        <runInTerminal>0</runInTerminal>
        <url>http://www.example.com/myprogram</url>
        <windowsIcon></windowsIcon>
     </startMenuLinkShortcut>

     <!-- Intended to launch a viewer for a specific file -->
     <startMenuFileShortcut>
        <comment>Check the user guide</comment>
        <filePath>${installdir}/doc/userguide.pdf</filePath>
        <icon></icon>
        <name>My Program User Guide</name>
        <platforms>all</platforms>
        <runInTerminal>0</runInTerminal>
        <windowsIcon></windowsIcon>
     </startMenuFileShortcut>
     ...
   </startMenuShortcutList>
   ...
 </component>

 <component>
   <name>default</name>
   ...
   <quickLaunchShortcutList>
     <!-- Intended to launch an application -->
     <quickLaunchShortcut>
        <comment>Launch My Program</comment>
        <exec>${installdir}/bin/myprogram</exec>
        <icon></icon>
        <name>My Program</name>
        <path>${installdir}/bin</path>
        <platforms>all</platforms>
        <runInTerminal>0</runInTerminal>
        <windowsExec>${installdir}/bin/myprogram.exe</windowsExec>
        <windowsExecArgs></windowsExecArgs>
        <windowsIcon></windowsIcon>
        <windowsPath>${installdir}/bin</windowsPath>
     </quickLaunchShortcut>

     <!-- Intended to launch a web browser pointing to a specific url -->
     <quickLaunchLinkShortcut>
        <comment>Launch a web browser pointing to My Program website</comment>
        <icon></icon>
        <name>Visit My Program website</name>
        <platforms>all</platforms>
        <runInTerminal>0</runInTerminal>
        <url>http://www.example.com/myprogram</url>
        <windowsIcon></windowsIcon>
     </quickLaunchLinkShortcut>

     <!-- Intended to launch a viewer for a specific file -->
     <quickLaunchFileShortcut>
        <comment>Check the user guide</comment>
        <filePath>${installdir}/doc/userguide.pdf</filePath>
        <icon></icon>
        <name>My Program User Guide</name>
        <platforms>all</platforms>
        <runInTerminal>0</runInTerminal>
        <windowsIcon></windowsIcon>
     </quickLaunchFileShortcut>
     ...
   </quickLaunchShortcutList>
   ...
 </component>

5.5. Adding components from external files

Components can also be extracted to a different file, making them usable as modules between different projects. These external files can be later inserted in the <componentList> using the <include> directive as seen in the code below:

<componentList>
    <include file="my_external_component.xml" />
</componentList>

Of course, you can mix external and internal components in the project file

<componentList>
    <component>
        <name>internal</name>
    </component>
    <include file="my_external_component.xml" />
</componentList>

In fact, the <include> directive can be used to include any external piece of XML code in any place of the project if some conditions are met:

  • The parent XML node is a <*List> tag: <actionList>, <parameterList>, <ruleList>

  • The inserted code is valid in the insertion point. For example, trying to include a file containing a <showInfo> action in a <ruleList> will fail.

  • The inserted XML code is grouped in a single element. For example, inserting a code containing two <runProgram> actions will fail but inserting an <actionGroup> with multiple actions on it will work.

<project>
    <shortName>sample</shortName>
    <fullName>Sample Project</fullName>
    <version>1.0</version>
    <enableRollback>1</enableRollback>
    <enableTimestamp>1</enableTimestamp>
    <componentList>
        <!-- component.xml contains a component -->
        <include file="path/to/component.xml"/>
        <component>
            <name>default</name>
            <description>Default Component</description>
            <canBeEdited>1</canBeEdited>
            <selected>1</selected>
            <show>1</show>
            <folderList>
              <!-- folder.xml contains a folder -->
              <include file="path/to/folder.xml"/>
            </folderList>
        </component>
    </componentList>
    <parameterList>
        <!-- installdir.xml contains a directory parameter -->
        <include file="path/to/installdir.xml"/>
        <booleanParameter>
            <name>boolean_question</name>
            <title>Boolean Question</title>
            <description>Please answer yes or no</description>
            <validationActionList>
               <!-- validationActions.xml contains an actionGroup -->
               <include file="path/to/validationActions.xml"/>
               <throwError text="You must click yes!" >
                  <ruleList>
                     <!-- isTrue.xml contains a set of rules in a ruleGroup -->
                     <include file="path/to/isTrue.xml"/>
                  </ruleList>
               </throwError>
            </validationActionList>
        </booleanParameter>
       ...
    </parameterList>
    ...
</project>

It is not possible to configure whether or not an <include> should be inserted. The <include> directives are evaluated when loading the project so they cannot contain variables or rules.

5.6. Excluding components at build time

Although a component can be disabled and hidden at runtime by modifying its <selected> and <show> properties, sometimes it is desirable to do not bundle them at all. In these situations, you can use the <shouldPackRuleList>. This set of rules is evaluated at build time and will decide whether or not the component containing them will be packed. For example, to just pack a component when building for OS X:

   <component>
       <name>osxComponent</name>
       <description>OS X Component</description>
       <canBeEdited>1</canBeEdited>
       <selected>1</selected>
       <show>1</show>
       ...
       <shouldPackRuleEvaluationLogic>and</shouldPackRuleEvaluationLogic>
       <shouldPackRuleList>
           <compareText>
               <logic>equals</logic>
               <text>${platform_name}</text>
               <value>osx</value>
           </compareText>
       </shouldPackRuleList>
   </component>

Please note the usage of the built-in variable ${platform_name}, which contains the build target at build time. In this case, using a <platformTest> will not work because it would evaluate the platform in which the builder is running and not the platform for which the installer is being built.

The same way as a <ruleList>, the <shouldPackRuleList> can contain <ruleGroup> rules to create complex conditions. You can also configure its rule evaluation logic using the <shouldPackRuleEvaluationLogic> property.

5.7. Component Groups

A <componentGroup> is a special type of <component> that can contains other components in its <componentList>:

<project>
    ...
    <componentList>

        <!-- componentGroup, a component with sub-components -->
        <componentGroup>
            <name>application1</name>
            <description>Application 1</description>
            ...
            <folderList>
                ...
            </folderList>
            <componentList>
                <component>
                    <name>feature1</name>
                    <description>Optional feature 1</description>
                    <folderList>
                        ...
                    </folderList>
                </component>
                <component>
                    <name>feature2</name>
                    <description>Optional feature 2</description>
                    <folderList>
                        ...
                    </folderList>
                </component>

                <!-- embedding a group inside a group -->
                <componentGroup>
                    <name>feature3</name>
                    <description>Optional feature 3</description>
                    <componentList>
                        <component>
                            <name>feature4</name>
                            <description>Optional feature 4</description>
                            <folderList>
                                ...
                            </folderList>
                        </component>
                    </componentList>
                    <folderList>
                        ...
                    </folderList>
                </componentGroup>
            </componentList>
        </componentGroup>

        <component>
            <name>application2</name>
            <description>Application 2</description>
            <folderList>
                ...
            </folderList>
        </component>

        <!-- component group that is always selected and cannot be edited -->
        <componentGroup>
            <name>application3</name>
            <description>Application 3</description>
            <selected>1</selected>
            <canBeEdited>0</canBeEdited>
            <folderList>
                ...
            </folderList>
            <componentList>
                <component>
                    <name>feature5</name>
                    <description>Optional feature 5</description>
                    <folderList>
                        ...
                    </folderList>
                </component>
            </componentList>
        </componentGroup>
    </componentList>
    ...
</project>

Component groups are displayed as a tree in the component selection page, where the user may choose to install any subset of its sub-components.

The following image shows the component selection screen for the example above:

Component selection screen
Figure 24: Component selection screen

As with a regular component, a component group can include its own files (in its <folderList>) and actions.

Component groups may also be nested, creating multiple levels. This can be done by embedding a <componentGroup> in the <componentList> of another <componentGroup>. The feature4 component is an example of this - it is inside the feature3 <componentGroup>, which is a sub-component of application1.

A child component will be installed only if it is selected and all of its parent component groups are selected as well. For example, if application1 is not selected, then regardless of whether or not feature1 was previously selected, it will not be installed. In the GUI component selection, this behavior is represented by visually deselecting all of the child components when deselecting a parent. For example, the following shows that when application1 is deselected, all of its child components are automatically deselected and cannot be edited:

Component selection screen
Figure 25: Component selection screen

Selecting a child component for installation requires enabling its parent components. In the example, in order to install feature1, the user first has to select application1 by clicking on the checkbox next to it. This will allow editing of the children of application1. Similarly, to enable feature4, the user needs to select both the application1 and feature3 component groups.

Specifying which components to enable from the command line differs in behavior. Whenever the user specifies --enable-components, all parents of specified components are also automatically selected. For example, if the user specifies that feature4 should be enabled, feature3 and application1 are automatically selected.

5.7.1. Installing in text mode

When running an installer in text mode, sub-components can only be chosen if a parent has been chosen. For example:

 $> /path/to/installer --mode text

...

Select the components you want to install; clear the components you do not want
to install. Click Next when you are ready to continue.

Application 1 [Y/n] :y

Application 1 - Optional feature 1 [Y/n] :y

Application 1 - Optional feature 2 [Y/n] :y

Application 1 - Optional feature 3 [Y/n] :n

Application 2 [Y/n] :y

Application 3 : Y (Cannot be edited)

Application 3 - Optional feature 5 [Y/n] :n

...

Please note that the user was not asked about feature4 since the feature3 component group was not selected.

As a regular parameter group, a <componentGroup> with its <show> property set to false won’t be visible, hidden its child as well.

If a <componentGroup> has its <canBeEdited> set to false but is selected by default, its sub-components can be still edited (if they individually allow it). However, in the case of a deselected component group that cannot be edited, their child won’t allow any user interaction, regardless of their individual configurations.

5.8. Downloadable components

InstallBuilder provides the ability to configure some or all of the available components to be separate, downloadable content instead of being embedded in the installer. This means that elements of the application that are not always used can be made downloadable to decrease an installer’s size.

Each downloadable component is built as a separate file for each platform. After building a project, its components should be copied to a web server or file hosting service so that users can download it.

5.8.1. How to create downloadable components

Any existing or new project can be configured to have its components downloadable as separate files.

To do so, enable the <downloadable> tag for any <component> in the project that should be made downloadable.

In addition, the <componentsUrl> should be a URL that points to the directory where all files are to be placed.

For example, the following is a complete project, including the URL where the components will be copied:

<project>
  <shortName>downloadabledemo</shortName>
  <version>1.0</version>
  <componentsUrl>http://example.com/installer/components/</componentsUrl>
  ...
  <componentList>
    <!-- component that should be embedded in the installer -->
    <component>
      <name>core</name>
      <description>Core features</description>
      ...
    </component>

    <!-- another component that should be embedded in the installer, specified explicitly -->
    <component>
      <name>osintegration</name>
      <downloadable>0</downloadable>
      <description>Integration with operating system</description>
      ...
    </component>

    <!-- another component that should be built as downloadable component -->
    <component>
      <name>optional</name>
      <downloadable>1</downloadable>
      <description>Optional content</description>
      ...
    </component>

  </componentList>
  ...
</project>

In order to build the project with downloadable components enabled, the --downloadable-components flag should be passed to the CLI.

 $> path/to/bin/builder build project.xml linux --downloadable-components

When using the GUI, the downloadable components checkbox should be enabled in the Build section before building the project.

After building the project for Linux, an additional directory downloadabledemo-1.0-components will be created with an optional-1.0-linux.pak file inside. When a project contains more components or is built for other platforms, additional files will be created in this directory.

After building the project, all contents of this directory should be uploaded to a web server so that they are available at <componentsUrl>. For the example above, the full URL should be http://example.com/installer/components/optional-1.0-linux.pak.

Some components may be available under different URLs. In this case, it is possible to specify the location using the <url> tag. The example below shows how optional content can be placed at a different URL:

<project>
  ...
  <componentList>
    <!-- another component that should be built as downloadable component -->
    <component>
      <name>optional3rdparty</name>
      <downloadable>1</downloadable>
      <description>Optional content, provided by other vendor</description>
      <url>http://example.net/downloads/optional3rdparty-1.0-${platform_name}.pak</url>
      ...
    </component>
  </componentList>
  ...
</project>

The component above will be downloaded from a different website using different platform names.

It is also possible to configure the directory for outputting the components using the <componentsDirectory> tag. This can be specified relatively. In this case it is relative to <outputDirectory>.

For example, to copy all component files into the same directory as <outputDirectory>, do the following:

<project>
  <componentsDirectory>.</componentsDirectory>
  ...
</project>

5.8.2. Running the installers with downloadable components

The behavior for installers with one or more downloadable components is the same as it is with regular installers.

The component selection page shows the downloadable file size for each component available for download:

Component selection with downloadable component
Figure 26: Component selection with downloadable component

If a user does not select any downloadable component, the installer does not perform any download or show any additional information related to downloading components.

If a user does want to install a downloadable component, after the Ready To Install page is shown, the user is presented with a proxy configuration page:

Proxy server configuration
Figure 27: Proxy server configuration

After the user configures or skips the proxy server configuration, the installer starts downloading the specified components:

Download progress
Figure 28: Download progress

If no error occurs, the installation proceeds when all components are downloaded and no user interaction is required.

In the event of an error, the user is prompted with three options:

Download error
Figure 29: Download error
  • Retry - retry the download

  • Ignore - do not attempt to download the current component and proceed without installing it

  • Abort - abort installation

5.8.3. Handling errors

In the event of download errors, the user is able to ignore the fact that a component could not be downloaded and proceed with the installation. It is possible to define actions that should be run when a component failed to download and the user chose to ignore it. For example:

<project>
  <shortName>downloadabledemo</shortName>
  <version>1.0</version>
  <componentsUrl>http://example.com/installer/components/</componentsUrl>
  ...
  <componentList>
    <component>
      <name>php</name>
      <downloadable>1</downloadable>
      <description>PHP module for Apache</description>
      <onDownloadErrorActionList>
        <throwError>
          <text>PHP module is required for phpMyAdmin. Aborting installation</text>
          <ruleList>
            <isTrue>
              <value>${project.component(phpmyadmin).selected}</value>
            </isTrue>
          </ruleList>
        </throwError>
      </onDownloadErrorActionList>
    </component>

  </componentList>
  ...
</project>

In this case, if the PHP module is not downloaded and another component depends on it, the installation will abort.

5.8.4. Text mode and unattended installers

Text mode installers provide the same support for downloadable components as GUI installers. After all parameters have been specified and at least one component needs to be downloaded, the user is prompted with a proxy configuration question. The user may choose to skip proxy configuration or specify it.

Next, downloading begins and the overall progress of installation is shown (this is the same feedback provided in the form of a progress meter for GUI installations).

Unattended installers also provide support for downloadable components. Components are downloaded and installation occurs automatically.

If unattendedmodeui is specified as minimalWithDialogs, progress for downloads is shown only as the overall download progress.

Download in unattended mode UI
Figure 30: Download in unattended mode UI

Similar to GUI installers, when all components are downloaded, the installation proceeds.

5.9. Adding or removing components to existing installations

InstallBuilder 8 offers the ability to install and uninstall individual components without reinstalling or uninstalling the entire application.

This functionality is disabled by default. In order to enable it, enable <allowAddRemoveComponents>.

5.9.1. Storing installation information

InstallBuilder stores the location of all applications inside of the application directory. When performing an installation, the user specifies the directory where the application should be installed. If <allowAddRemoveComponents> is enabled, a check is made to see if a previous installation exists in specified directory before the component selection page is shown.

If it contains information about a previous installation, it is used by the installer. This information will consist of currently installed components and optionally for storing previous values for parameters that allow it.

It also contains information about the currently installed version. If the versions do not match, information about the currently selected components and values for parameters that allow it is used. However, all components are reinstalled in such a case.

5.9.2. Installing additional components

If <allowAddRemoveComponents> is enabled, the installer will automatically detect whenever a valid installation of the application is present in the installation directory.

Components previously installed will always be selected and the user will not be able to uninstall components using the installer. The user may choose to install additional components.

Whenever any change is made, all actions for newly selected components are run. However, actions for components previously installed are not run. This prevents actions that set up default values from overriding settings that user has already modified.

After a successful installation, the uninstaller and all related information will be updated to reflect that the user has installed additional components.

5.9.3. Uninstalling components

If <allowAddRemoveComponents> is enabled, running the uninstaller will show an additional choice page with the following options:

  • Entire application - removes the entire application and all files installed by the application

  • Individual components - removes individual components while leaving the rest of the application intact.

When a user selects the Entire application option, the behavior is the same as when <allowAddRemoveComponents> is disabled.

When a user selects Individual components, a component selection page will be shown. All components not currently installed will not be shown in the component selection tree. Components that have their <canBeEdited> disabled will not be editable.

When a user selects a component group, the component and all of its sub-components will be removed. For example if a user selects application1, this causes feature1, feature2, feature3 and feature4 to be uninstalled:

Selecting components to uninstall
Figure 31: Selecting components to uninstall

Selecting a component group to be uninstalled also causes all of its child components to be uninstalled. Those components are shown as selected and cannot be edited. For example the following shows that the component application1 will be uninstalled, which will also cause all of its child components to be uninstalled:

Selecting components to uninstall
Figure 32: Selecting components to uninstall

If a parent is deselected, the selection of its children is reverted - if a child component was previously explicitly selected before selecting the parent, it will remain selected. Otherwise the child component will be deselected.

When a user selects all of the components, the installer will behave as if the Entire application option was chosen. Otherwise, selected components will be removed and pre- and post- uninstallation actions for these components will be run. Remaining components will remain installed and no actions for these components will be run.

After successful uninstallation, the uninstaller and all related information will be updated to reflect that the user has uninstalled some of the components.

When the Entire application option is chosen or the user selects all components in the component tree, the entire application is uninstalled along with uninstaller itself. This also triggers pre- and post- uninstallation actions for the project to be run.

6. Working with Files and Folders

The installation resources (files and directories) are grouped into <folder> elements.

<project>
    ...
    <componentList>
       <component>
          <name>myComponent</name>
          ...
          <folderList>
              <folder>
                 <name>documents</name>
                 <destination>${installdir}/docs</destination>
                 <platforms>linux windows</platforms>
                 <distributionFileList>
                     <distributionDirectory origin="/home/johndoe/docs"/>
                     <distributionFile origin="/home/johndoe/README"/>
                 </distributionFileList>
                 <shortcutList>
                     ...
                     <shortcut/>
                     ...
                 </shortcutList>
                 <actionList>
                     <addTextToFile file="${installdir}/docs/README" text="some text"/>
                 </actionList>
              </folder>
          </folderList>
       </component>
    </componentList>
</project>

The most important tags in a folder element are:

<folder>
   ...
   <distributionFileList>
       <distributionFile>
          <origin>${build_project_directory}/license.txt</origin>
       </distributionFile>
       <distributionDirectory allowWildcards="1">
          <origin>${build_project_directory}/readmeFiles/*.txt</origin>
          <includeFiles>*/README-*.txt</includeFiles>
          <excludeFiles>*/README-template.txt</excludeFiles>
       </distributionDirectory>
   </distributionFileList>
</folder>
  • <platforms>: This tag defines a space-separated list of platforms for which the files will be packed. This is evaluated at build time and matched against the specified build target. It allows a single project to define a multiplatform installer. The special platform identifier all can be used and represents all platforms. The full list of supported values in the tag is summarized in the table below:

Supported Platforms

Platform Identifier

Platform Description

all

All Platforms

linux

Linux

linux-x64

Linux x86 64 bits

linux-ia64

Linux IA64

windows

Windows

osx

Mac OS X

solaris-sparc

Solaris Sparc

solaris-intel

Solaris Intel

linux-ppc

Linux PPC

linux-s390

Linux s390

freebsd

FreeBSD 5

freebsd4

FreeBSD 4

freebsd6

FreeBSD 6

freebsd6-x64

FreeBSD 6 64 bits

freebsd7

FreeBSD 7/8

freebsd7-x64

FreeBSD 7/8 64 bits

openbsd3

OpenBSD x86

hpux

HP-UX

aix

AIX, OS/400

irix-n32

IRIX

  • <destination>: The destination directory in which all the bundled files in the folder will be unpacked.

  • <shortcutList>: Along with the files, a folder can define a list of shortcuts to create. You can find a detailed reference in the shortcuts section.

  • <actionList>: Actions executed right after the files of the folder are unpacked.

6.1. Conditionally Packing a Folder

Although the <platforms> tag provides a built-in mechanism to avoid packing folders for different platforms, there are scenarios in which you need a more complex condition than just the target platform. This can be achieved using the <shouldPackRuleList>:

  <folder>
    <name>documents</name>
    <destination>${installdir}/docs</destination>
    <platforms>linux</platforms>
    <distributionFileList>
       <distributionDirectory origin="/home/johndoe/docs"/>
       <distributionFile origin="/home/johndoe/README"/>
    </distributionFileList>
    <shouldPackRuleEvaluationLogic>and</shouldPackRuleEvaluationLogic>
    <shouldPackRuleList>
       <fileExists path="/home/johndoe/docs"/>
       <fileExists path="/home/johndoe/README"/>
    </shouldPackRuleList>
  </folder>

The above folder will only be packed if the target platform is linux and the files exist. The evaluation logic of the rules can be modified through the <shouldPackRuleEvaluationLogic> property.

This is also helpful when you are developing the installer and do not need all of the files that will be included in the final version (that can greatly increase the build time) to be packed. For example, you could create an environment variable (DEMO_BUILD) to indicate to the builder you do not need an official build:

  <folder>
    <name>optionalFiles</name>
    <destination>${installdir}</destination>
    <platforms>linux</platforms>
    <distributionFileList>
       <distributionDirectory origin="videos"/>
       <distributionDirectory origin="images"/>
       <distributionDirectory origin="documentation"/>
    </distributionFileList>
    <shouldPackRuleList>
       <!-- Check if the variable is defined -->
       <compareText text="${env(DEMO_BUILD)}" logic="equals" value=""/>
    </shouldPackRuleList>
  </folder>

You can find a more complex example in the "Custom Build Targets" section.

Note
Do not confuse <shouldPackRuleList> with <ruleList>

Rules inside a <ruleList> are evaluated at runtime while rules within a <shouldPackRuleList> are evaluated at build time.

6.2. Conditionally Unpacking a Folder

By default, folders will be unpacked if they were packed (as described in the previous section) and if the <component> in which they are bundled was selected. However, you can add additional logic to discern if it should be unpacked by attaching rules to its <ruleList>:

  <folder>
    <name>documents</name>
    <destination>${installdir}/docs</destination>
    <platforms>windows</platforms>
    <distributionFileList>
       <distributionDirectory origin="/home/johndoe/docs"/>
       <distributionFile origin="/home/johndoe/README"/>
    </distributionFileList>
    <ruleEvaluationLogic>and</ruleEvaluationLogic>
    <ruleList>
       <platformTest type="windows-xp"/>
    </ruleList>
  </folder>

The above folder will be packed for any Windows target but will only be unpacked if the platform in which the installer is executing is Windows XP.

6.3. Filters

6.3.1. Basic Filters

InstallBuilder implements a basic filtering mechanism for folders. This functionality will allow you to pack the contents of a folder instead of including the folder itself and to apply filters to include or exclude specific files. For example, if you have a folder named "documentation" and you want to pack a subset of its contents and unpack it to ${installdir}/myDocs, you just need to use the snippet below:

<folder>
   <description>Documentation Files</description>
   <destination>${installdir}/myDocs</destination>
   <name>documentation</name>
   <platforms>all</platforms>
   <distributionFileList>
       <distributionDirectory allowWildcards="1">
          <origin>/some/path/to/documentation/*</origin>
          <includeFiles>*/project-1-*.txt</includeFiles>
          <excludeFiles>*/project-1-secret.txt</excludeFiles>
       </distributionDirectory>
   </distributionFileList>
</folder>

In the above example, all of the .txt files related to "project-1" will be packaged, with the exception of "project-1-secret.txt"

The following are the filtering-related tags that you can use:

  • <allowWildcards> : This tag determines the behavior of the filtering mechanism. If it is set to "0" (the default), there will not be any global pattern interpretation and patterns will be taken as literal strings. For example, if you define <origin>/some/path/to/documentation/*</origin>, the installer will look for a folder named "*" inside the /some/path/to/documentation/ directory. In addition, the includeFiles and excludeFiles tags will be ignored.

However, if allowWildcards is set to "1", the <origin> will be expanded and the installer will generate a list of matching files.

  • <includeFiles> : This tag allows you to select files over the matches produced by the <origin> tag when wildcards are enabled. The default value of the <includeFiles> tag is "*" so all the files matched by the <origin> tag will be packed.

  • <excludeFiles> : Once the list of files has been filtered with the <includeFiles> pattern, the <excludeFiles> filter will be applied over the result. The default value of this tag is empty so no filter is applied. This tag is ignored if wildcards are disabled. Only files directly returned by the evaluation of the <origin> pattern can be excluded, the builder won’t try to recursively exclude files at deeper hierarchy levels in the packed directories.

The pattern interpretation in the <origin>, <includeFiles> and <excludeFiles> does not follow the same rules. The <origin> pattern is expanded over the existing files, like a "dir c:\Program Files\*txt" on Windows or "ls ~/*txt" on Unix. Forward and backwards slashes are normalized according to the platform. However, the patterns in the <includeFiles> and <excludeFiles> tags follow a stricter format:

  • Forward slashes are used as path separators, which let us escape special characters using backslashes. For example, to match .txt files, you must use */*.txt files in both Windows and Unix systems.

  • The pattern is applied over the full path of the files and a string comparison is performed: <includeFiles>my.txt<includeFiles> will not work because it will compare "/some/path/to/my.txt" with "my.txt". */my.txt has to be used instead.

  • Multiple patterns can be included and must be separated by ; or \n characters:

   <distributionDirectory allowWildcards="1">
       <origin>/some/path/*</origin>
       <includeFiles>*/*.txt;*/*.jpg;*/*.bmp</includeFiles>
       <excludeFiles>*/*secret*.txt;*/myImage.bmp</excludeFiles>
    </distributionDirectory>

The special characters used in all of the patterns are listed below:

  • ? : Matches any single character.

  • * : Matches any sequence of zero or more characters.

  • [chars] : Matches any single character in chars. If chars contains a sequence of the form a-b then any character between a and b (inclusive) will match.

  • {a,b,...} : Matches any of the strings a, b, etc.

Note
Basic filters do not operate recursively

The basic filters mechanism is not intended to recursively skip packing files in the directory provided in the <origin> tag. Just the results returned by the evaluation of the <origin> pattern can be filtered. For example, if you are packing a directory images and want to exclude the file demo.png, the below won’t work:

<folder>
   ...
   <destination>${installdir}</destination>
   ...
   <distributionFileList>
       <distributionDirectory allowWildcards="1">
          <origin>images</origin>
          <excludeFiles>*/demo.png</excludeFiles>
       </distributionDirectory>
   </distributionFileList>
</folder>

The reason is that the <origin> pattern will only return images as matching file, which does not match the exclusion pattern */demo.png.

If demo.png is packed directly under images you could use:

<folder>
   ...
   <destination>${installdir}/images</destination>
   ...
   <distributionFileList>
       <distributionDirectory allowWildcards="1">
          <origin>images/*</origin>
          <excludeFiles>*/demo.png</excludeFiles>
       </distributionDirectory>
   </distributionFileList>
</folder>

In this case, evaluating <origin> will return all the contained images (sample-01.png, left-image.jpg, details.gif, demo.png, …), and the exclusion pattern will be able to match demo.png.

If you want to filter certain files at any level of the hierarchy in the packed directory, you should use the Advanced Filters instead, which operate recursively.

6.3.2. Advanced Filters

In addition to the basic filters, which allow providing a pattern to the <origin> tag while excluding some of the results returned, InstallBuilder also includes a more complex filtering mechanism that allows excluding files located at any level in the folder hierarchy of the <distributionDirectory>.

Note that you have to define filters that will decide if the file will be packed or not. Currently, just filters based on the file path are allowed: <fileNameFilter>. These are the basic tags in the <fileNameFilter>:

  • <pattern>: Pattern to match against the path of the file

  • <patternType>: Whether to use glob or regular expressions matching

  • <logic>: Whether or not the pattern must match to pass the filter.

These filters are grouped into the <onPackingFilterList>. If the file in consideration matches the expressed conditions in this list, it will be packed, if not, it will be skipped.

For example, if you want to pack a folder dist-files:

dist-files/
|-- bin
|   `-- productA
|       `-- data
|           |-- info.ini
|           `-- info.ini~
|-- docs
|   `-- reference
|       |-- README.tct~
|       |-- reference.html
|       |-- reference.html~
|       |-- reference.pdf
|       `-- reference.pdf~
`-- libraries
    |-- lib1.so
    |-- .#lib2.so
    `-- lib2.so

To exclude all of the temporary files (files ending in ~), you could use:

 <folder>
   <description>Program Files</description>
   <destination>${installdir}</destination>
   <name>programfiles</name>
   <platforms>all</platforms>
   <distributionFileList>
     <distributionDirectory>
       <origin>dist-files</origin>
       <onPackingFilterList>
          <fileNameFilter pattern="*~" logic="does_not_match" patternType="glob"/>
       </onPackingFilterList>
     </distributionDirectory>
   </distributionFileList>
 </folder>

After the installation, you will find the dist-files directory clean of temporary files:

sample-1.0
|-- dist-files
|   |-- bin
|   |   `-- productA
|   |       `-- data
|   |           `-- info.ini
|   |-- docs
|   |   `-- reference
|   |       |-- reference.html
|   |       `-- reference.pdf
|   `-- libraries
|       |-- lib1.so
|       |-- .#lib2.so
|       `-- lib2.so
|-- uninstall
`-- Uninstall Sample Project.desktop

If you also want to exclude files starting with .#, you just need to add another filter to the <onPackingFilterList>:

 <folder>
   <description>Program Files</description>
   <destination>${installdir}</destination>
   <name>programfiles</name>
   <platforms>all</platforms>
   <distributionFileList>
     <distributionDirectory>
       <origin>dist-files</origin>
       <filterEvaluationLogic>and</filterEvaluationLogic>
       <onPackingFilterList>
          <fileNameFilter pattern="*~" logic="does_not_match" patternType="glob"/>
          <fileNameFilter pattern="*/.#*" logic="does_not_match" patternType="glob"/>
       </onPackingFilterList>
     </distributionDirectory>
   </distributionFileList>
 </folder>

The default <filterEvaluationLogic> is and but you can also set it to or. A file will be packed if its full path in the build machine matches all the filters when using and logic or when matching any of them when using or.

For example, if you want to pack just .png and .jpg files, you could rewrite the code with or logic:

 <folder>
   <description>Program Files</description>
   <destination>${installdir}</destination>
   <name>programfiles</name>
   <platforms>all</platforms>
   <distributionFileList>
     <distributionDirectory>
       <origin>dist-files</origin>
       <filterEvaluationLogic>or</filterEvaluationLogic>
       <onPackingFilterList>
          <fileNameFilter pattern="*.png" logic="matches" patternType="glob"/>
          <fileNameFilter pattern="*.jpg" logic="matches" patternType="glob"/>
       </onPackingFilterList>
     </distributionDirectory>
   </distributionFileList>
 </folder>

The filters can also include more complex patterns if instead of using the glob <patternType> you set it to regexp. For example, you can exclude .txt files that start with a number and contain temp in their paths and .png files that start with three capital letters using a single filter:

 <folder>
   <description>Program Files</description>
   <destination>${installdir}</destination>
   <name>programfiles</name>
   <platforms>all</platforms>
   <distributionFileList>
     <distributionDirectory>
       <origin>dist-files</origin>
       <onPackingFilterList>
          <fileNameFilter pattern="/([A-Z]{3}[^/]*\.png|[0-9]+[^/]*temp[^/]*\.txt)$" logic="does_not_match" patternType="regexp"/>
       </onPackingFilterList>
     </distributionDirectory>
   </distributionFileList>
 </folder>

Both regexp and glob pattern types allow providing a semicolon-separated list of sub patterns. If any of the sub patterns in the list evaluates to true, the full pattern will also evaluate to true. For example, to pack all of the .png and .jpg files in a directory, you could use any of the below snippets:

 <folder>
   <destination>${installdir}</destination>
   <name>programfiles</name>
   <distributionFileList>
     <distributionDirectory>
       <origin>dist-files</origin>
       <onPackingFilterList>
          <fileNameFilter pattern="*.png;*.jpg" logic="matches" patternType="glob"/>
       </onPackingFilterList>
     </distributionDirectory>
   </distributionFileList>
 </folder>

 <folder>
   <description>Program Files</description>
   <destination>${installdir}</destination>
   <name>programfiles</name>
   <platforms>all</platforms>
   <distributionFileList>
     <distributionDirectory>
       <origin>dist-files</origin>
       <filterEvaluationLogic>or</filterEvaluationLogic>
       <onPackingFilterList>
          <fileNameFilter pattern="*.jpg" logic="matches" patternType="glob"/>
          <fileNameFilter pattern="*.png" logic="matches" patternType="glob"/>
       </onPackingFilterList>
     </distributionDirectory>
   </distributionFileList>
 </folder>

 <folder>
   <destination>${installdir}</destination>
   <name>programfiles</name>
   <distributionFileList>
     <distributionDirectory>
       <origin>dist-files</origin>
       <filterEvaluationLogic>and</filterEvaluationLogic>
       <onPackingFilterList>
          <fileNameFilter pattern=".*\.(png|jpg)$" logic="matches" patternType="regexp"/>
       </onPackingFilterList>
     </distributionDirectory>
   </distributionFileList>
 </folder>

Even more complex conditions can be expressed using a <filterGroup>. This special type of filter allows grouping a set of filters with a configurable <filterEvaluationLogic>. For example, you can exclude all of the .txt files except for those in the readme folder and exclude all of the .png and .jpg files that are not under the images folder:

 <folder>
   <description>Program Files</description>
   <destination>${installdir}</destination>
   <name>programfiles</name>
   <platforms>all</platforms>
   <distributionFileList>
     <distributionDirectory>
       <origin>dist-files</origin>
       <filterEvaluationLogic>and</filterEvaluationLogic>
       <onPackingFilterList>
          <!-- Include files that do not end in .txt or if they are located in the readme dir -->
          <filterGroup>
             <filterEvaluationLogic>or</filterEvaluationLogic>
             <onPackingFilterList>
               <fileNameFilter pattern="*.txt" logic="does_not_match" patternType="glob"/>
               <fileNameFilter pattern="*/readme/*" logic="matches" patternType="glob"/>
             </onPackingFilterList>
          </filterGroup>
          <!-- Include files that do not end in .png or .jpg or if they are located in the images dir -->
          <filterGroup>
             <filterEvaluationLogic>or</filterEvaluationLogic>
             <onPackingFilterList>
               <fileNameFilter pattern=".*\.png;.*\.jpg" logic="does_not_match" patternType="regexp"/>
               <fileNameFilter pattern="*/images/*" logic="matches" patternType="glob"/>
             </onPackingFilterList>
          </filterGroup>
       </onPackingFilterList>
     </distributionDirectory>
   </distributionFileList>
 </folder>

Filter groups can also be nested as needed.

Take into account that all of the files in the <distributionDirectory> will be matched against the filter, so using a lot of very complex files could slightly increase the build time (the performance at runtime will not be affected at all).

Note
The pattern is applied to the full path of the file

Because of the pattern is applied to the full path of the file to be packed, when trying to match files ending in an specific suffix, you should always prefix it with * (when using glob <patternType>) or .* (when using regexp <patternType>).

For example, specifying:

<fileNameFilter pattern="images/*.png" logic="matches" patternType="glob"/>

Wont work because it will be matched against the full path, for example: /home/bitrock/demo/files/images/foo.png

To make it independent to the location, it should be rewritten to:

<fileNameFilter pattern="*/images/*.png" logic="matches" patternType="glob"/>

Or

<fileNameFilter pattern="${build_project_directory}/files/images/*.png" logic="matches" patternType="glob"/>

6.4. Unix Permissions

InstallBuilder preserves the permissions of bundled files. It also includes two convenient tags: <defaultUnixGroup> and <defaultUnixOwner>. If a value is specified for those tags, the owner and group of the unpacked files will be modified at runtime:

<project>
   ...
   <defaultUnixGroup>wheel</defaultUnixGroup>
   <defaultUnixOwner>root</defaultUnixOwner>
   ...
</project>

Please take into account that the specified group and owner must exist in the target machine. If not, you can always create them before the installation phase:

<project>
   ...
   <defaultUnixGroup>coolUsers</defaultUnixGroup>
   <defaultUnixOwner>john</defaultUnixOwner>
   ...
   <readyToInstallActionList>
      <addUser username="john"/>
      <addGroup groupname="coolUsers"/>
   </readyToInstallActionList>
   ...
</project>

Despite the permissions being preserved, in some situations they must be fixed. The most convenient way of fixing them is to use the <actionList> of the folder containing the files and set the appropriate rights:

<folder>
   <description>Binary Files</description>
   <destination>${installdir}</destination>
   <name>executables</name>
   <platforms>all</platforms>
   <distributionFileList>
       <distributionDirectory>
          <origin>/some/path/executables</origin>
       </distributionDirectory>
   </distributionFileList>
   <actionList>
       <changePermissions permissions="0755" files="${installdir}/executables/*"/>
   </actionList>
</folder>

A common scenario in which permissions must be fixed is when you are building a Linux installer on Windows. In that case, you could either manually fix the permissions as explained in the latest snippet or define the default permissions:

<project>
   ...
   <defaultUnixFilePermission>644</defaultUnixFilePermission>
   <defaultUnixDirectoryPermission>755</defaultUnixDirectoryPermission>
   ...
</project>

Please take into account that, contrary to the owner and group tags, the default Unix permissions are only applied when building on Windows. This way, if the installer is created on Unix, the configured values will be ignored.

Note
Files packed on Windows lose their executable permissions

Windows does not understand Unix permissions, so Unix installers created on Windows will be unpacked without executable permissions and must be manually fixed. It is recommended that you use Unix machines to build the installers as they do not present any limitation.

When a symbolic link is specified as a <distributionFile>, InstallBuilder does not follow the link to pack its target. Depending on the build type, it will either pack the link (deb, rpm) or it will be registered and recreated at runtime.

6.6. Unpacking Before Installation Time

It is common to have a separate tool or program that must be bundled with and run from the installer but before the file copying phase of the installation process has completed. A common example would be a license validation program. Typically, all files bundled within an installer are unpacked and then any tools are run. In the case of a license validation tool, that is less than ideal because the user may end up waiting for the files to be unpacked only to find that the license is not valid. The user would then have to wait for the installation to be rolled back.

InstallBuilder provides you with actions to deal with these situations. The most important are <unpackFile> and <unpackDirectory>:

<unpackDirectory>
   <destination>${installdir}</destination>
   <component>tools</component>
   <folder>license</folder>
   <origin>management</origin>
</unpackDirectory>

<unpackFile>
   <destination>${system_temp_directory}</destination>
   <component>tools</component>
   <folder>license</folder>
   <origin>management/validator.exe</origin>
</unpackFile>

The <unpackDirectory> action is intended to unpack a directory and its contents while the <unpackFile> action operates over files. Trying to unpack the wrong type in those actions will generate an error at runtime.

The configuration options for these actions specify the folder and component bundling the files, the path relative to the packed element, and the destination directory to unpack them.

The structure in Figure 33 (also represented in XML code) should help you understand how to reference internal files:

Internal Files Structure
Figure 33: Internal Files Structure

<project>
  ...
  <componentList>
     <component>
       <name>componentA</name>
       <description>Component A</description>
       <folderList>
         <folder>
           <name>folder1</name>
           <description>Folder 1</description>
           <distributionFileList>
              <distributionDirectory>
                <!-- someDirectory contains: readme.txt,
                logo.jpg and directory1 -->
                <origin>/path/to/someDirectory</origin>
              </distributionDirectory>
              <distributionFile>
                <origin>/path/to/someFile</origin>
              </distributionFile>
              <distributionFile>
                <origin>/path/to/someOtherFile</origin>
              </distributionFile>
           </distributionFileList>
         </folder>
       </folderList>
     </component>
     <component>
       <name>componentB</name>
       <description>Component B</description>
       <folderList>
         <folder>
           <name>folder2</name>
           <description>Folder 2</description>
           <distributionFileList>
              <distributionDirectory>
                <!-- someDirectory contains: movie.avi and
                installer.exe -->
                <origin>/path/to/someOtherDirectory</origin>
              </distributionDirectory>
           </distributionFileList>
         </folder>
       </folderList>
     </component>
  </componentList>
  ...
</project>

To reference logo.jpg: