MSI compilation in greater detail

This page an extension of the general MSI page here and assumes that you have read that page first.

Building Windows Installer (MSI) files

MSI compilation in greater detail

This page an extension of the general MSI page here and assumes that you have read that page first.

Compiling a custom software installation MSI file

When a script is open in the Script Editor, clicking "Compile Script To MSI File" will start the wizard and show the screen below. The output MSI file is compiled from this script.

MSI creation properties

The installation name and version are the information shown in the Windows programs list in the control panel. The reason the version is not auto-generated is that you can use the version to actively re-install packages. If you increment the version and re-install, the "Major Upgrade" feature of Windows Installer is used and that means running the installation again will not fail, but automatically run the uninstaller of the old package and the installer of the new package. This is usable if you update a maintenance script and want to re-deploy it, because then you do not need to worry about whether the target machine already had the package in an older version or not.

Running the output Windows Installer file will show a welcome dialog (see below) and a complete dialog. When you install the packages through group policies or a management system, the installation will run in unattended mode and these dialogs will never be shown.

Windows Installer interface

A good reason to use the Windows Installer generation is to wrap installations that are not already in Windows Installer format, if you want to deploy through group policies or a management system. As mentioned earlier, if you need to re-package, give some thought to whether you are using the right strategy or not.

Assuming there is a need to re-package, let's assume you need your VPN software as an MSI and it comes with a different installer. You cannot just deploy it through group policies or a management system. Often snapshot technologies are used to convert a proprietary installer into Windows Installer format, but this is an approach that must be avoided at all costs - especially when it includes drivers, firewall rules and other low-level elements. It will never work on a hundred different machines, especially if they are not all the same operating system. You are bypassing the installation logic of the vendor with snapshots and it's impossible for any snapshot software to "discover" all the rules behind the installation logic.

If you know that you can just run "Setup.Exe /Quiet" or similar, it is frustrating to not be able to deploy it through group policies. But this is now possible with the MSI generator of FSH. Basically you can just put your setup.exe in a directory and create a script file in the same directory that just issues for example "Run Setup.Exe,/Quiet" and then clicking the MSI project button will generate an .MSI file. That's it, no additional steps needed.

Another scenario could be applications that are made in-house that you want to wrap. Let us try an example that can be reproduced without any third party installation files. Let us assume we wanted to use SmartDock, but we do not use FastTrack Logon for logon scripts, so we need another way to deploy it. We would then need to deploy the fsh.exe engine file, our license file and the SmartDock files and finally set SmartDock to run for everyone that logs on.

To accomplish this, we will create a new folder with a script file and a sub-folder named "Bin". In the bin folder we need a copy of 5 files, making our complete project directory structure look like this:
  • SmartDock Runtime.fsh (The installation script that we create next)
  • Bin\Fsh.Exe (Fsh engine)
  • Bin\Fsh.Lic (Your license key)
  • Bin\SmartDock.Exe
  • Bin\SmartDock.Fsh (The script that SmartDoc executes)
  • Bin\SmartDock.Xml (SmartDock configuration)
The main script that we called "SmartDoc Runtime.fsh" could look like the script below. When we select the "Compile Script To MSI File", this script must be open, as MSI packages are created based on the open script.

Set InstallDir=[ProgramFilesDir]\Acme Corporation\FastTrack Scripting Host

If MSIInstallContext Then

  CopyDir Bin,[Var InstallDir]

  Run [Var InstallDir]\Fsh.Exe,/Associate

  SetStartupItem SmartDock,[Var InstallDir]\SmartDock.Exe


  KillProcess SmartDock.Exe

  Run [Var InstallDir]\Fsh.Exe,/Unassociate

  DeleteDir [Var InstallDir]

  RemoveStartupItem SmartDock

End If

Observe how there is a check for a condition called "MSIInstallContext". You have to factor in that your package can be uninstalled. If you are thinking that it never will, remember upgrading will also trigger uninstall with the old package script and install with the new script. If you do not "react" to uninstallation and just include an installation part, effectively your script will also runs the installation, when asked to uninstall.

As is also the case with project exe files, the location of the additional files, which are unpacked to a temporary installation directory before execution, cannot be known up front and will vary from client to client. Therefore all references to files and folders must be relative, as it is also the case with the bin folder in the example script.

Now we need to compile the script and the additional files in the "Bin" folder. Click the "Compile to MSI" menu item or press F12:

Creating MSI file from project

This will pop up the MSI wizard to generate the MSI file. Fill in the basic properties on the first page and make sure the "Include additional files from my project folder inside the MSI file" is checked. The second page in the wizard will allow you to select the files to include, as shown below. Observe that when selecting project generation, all files in the script folder and all sub-folders are included with the option to un-check files to exclude.

MSI generation project properties

Now that we have a single MSI file, we can deploy with for example Microsoft System Center. As not everyone has Microsoft System Center, in this case we will just deploy our MSI through regular Group Policy deployment:

Group policy for software installations

When we log on to a computer that is under the control of the above group policy, the MSI file is installed on system startup as shown below with a Windows XP client.

Installing software through group policies

And if we chose to remove the MSI file from the Group Policy, the uninstaller runs as shown below on the same Windows XP client.

Uninstalling software through group policies

TeamViewer example

A common example of re-packaging is TeamViewer. You can download a single TeamViewer.exe that will install the software and then start it. If you run the installation package, you will find two files are unpacked in the temp folder. If you copy the TeamViewer_.exe file from the temp folder, it can be run using /S to install silently. But it will still start the program after installation. The script below will install the software and kill the process after installation. Put the TeamViewer_.exe in the same directory as the script and compile into an MSI project, and you have a fully unattended MSI version of the TeamViewer installation - without using snapshots.

Run TeamViewer_.Exe,/S

KillProcess TeamViewer.Exe

When to use MSI files for installations

Using scheduled tasks inside MSI files serves a specific purpose. These are not for installation of a specific piece of software, but may be a controller for other installations. The MSI is in this case merely a container for distributing the scheduled task. But speaking of MSI packages for installation of specific software, the most important thing to think about is, do you actually need them to be in MSI format at all, if they ship with something else. If you know the unattended switches, doing MSI repackaging only makes sense to address a technical limitation.

Generally speaking, there are two very different scenarios. For servers it natural to deploy software packages or scheduled task controller scripts through group policies, as no one logs on to these machines. If you chose the scheduled task option (see the server farm deployment example), there is no reason to not just use the native installer. If you for example want TeamViewer on a number of servers, it does not make sense to repackage it. Why not just go "Run TeamViewer_.exe,/S" in a script (see example further down)? If you're repackaging something so low-level as TeamViewer using a snapshot, it is downright dangerous to the target server and you could effectively destroy things like registry driver chains, worst case resulting in a server that can no longer boot. If you have to distribute non-MSI based software for servers, consider either the server farm deployment example or repackaging a native installer without using snapshots (see further down).

For workstations, it is a little more complicated. The optimal way to handle installations is not to just add MSI installations to your group policies, as there is no control over the distribution process. Even if you have only say 100 computers and your installation package is large, it is already undesirable to just let all computers install at the same time with group policies. In such a case you would need to factor in things like network peak hours, simultaneous installs and maybe even computer types and other conditions. And when you have more than a couple of installation packages, group policy installations become unscalable, because you would not have a policy for each group of computers that need a certain installation package. Group policy installations are in general usable only for servers or small packages that all computers or users must have.

In such a scenario, it is recommended that you run your workstation installations through your logon script, startup script or a scheduled task controller script contained inside an MSI (see further down), where your actual installation files in all these scenarios are on a network share and you can control which computers get which software, for example by using computer domain groups. In such a setup, it is not required to use MSI packages, as long as you know the unattended switches for your setup files. Please consult the installations page for general information on scripting installations. Once you control the launch of the actual installer from your own script, you can make a simple simultaneous counter to avoid flooding or you can use the scheduled task option to spread the load automatically.

A tip to get software distributed to offline computers: You can generate a self-contained exe file that includes installation files and your credentials to allow the installation to be performed. Please consult the exe files page for more information on generating exe files.

Scheduled task inside an MSI package

As explained earlier, you can embed a scheduled task inside the MSI file, as shown below.

Scheduled task contained inside an MSI package page 1

Selecting "Compile script into a Scheduled Task inside an MSI package" in the "Installation type" dropdown list inserts two more pages into the wizard flow upon clicking "Next". The first one configures the scheduled task, as shown below, and the second one is for optional overrule of credentials.

Scheduled task contained inside an MSI package page 2

Your script does not get executed, when you install the MSI package with the scheduled task option. Instead the MSI installation process installs a scheduled task, which runs your script or project as a single compiled executable. When a computer installs the output MSI for example through group policies, the default trigger is a random time between the random start and end times once a day. The default is between 10am and 3pm, because if you use it for workstations and you have thousands of computers, no computer gets the task triggered at typical logon hours and all computers' trigger times are spread over these 5 hours. This is ideal to make sure that there is no network congestion while for example installing an updated Microsoft Office. For servers it would be natural to change the random start hours to for example between 2am and 5am. If we pull down the "Trigger" dropdown list there are more trigger types:

Scheduled task trigger types inside an MSI package page

The most common trigger is the daily trigger, but you can select another one, if needed. Note that if you are considering the "Every number of minutes" trigger, in most cases a Windows Service compilation is better. The choice between one over the other would typically depend on, if you need a fixed break between execution of a fixed time between triggering, in case the script task takes more than a few seconds.

For a script of this type to be flexible, it would be a good idea to not let the scheduled task contain the installation logic (like determining if an installation must happen or not), but instead simply include a script on the network. So the script inside the MSI may even look as simple as this:

Include \\AcmeServer\Install$\InstallationLogic.fsh

Assuming the task is installed with domain credentials, this will basically just run another script off the network, which avoids the need to update the scheduled task frequently, because it contains no logic itself.

Another example is a maintenance task that has to happen daily. The maintenance task could cleanup temporary files, verify free disk space or check that no unauthorized user is a member of the local administrators group and send an email to the administrator or log an online event, in the event any of these conditions are not met.

A third example is that if you have a large number of computers, you may have concerns uploading inventory information from computers within the logon hours. In this case, you could create a script containing only the inventory command, as shown below and compile that into an MSI scheduled task.


It has to be pointed out that the bandwidth consumed for inventory upload is marginal, even with a large number of machines. If this package is then deployed to a thousand computers, statistically only 200 computers would actually run the script per hour and never outside the 10am to 3pm non-peak window. As no information is typically changed from one run to the next, the uploaded information per minute becomes marginal.

Scheduled tasks for servers

Note that random start and stop hours can be set through the random start and end input fields on the generation screen. If you prefer another interval other than the default 10am to 3pm, you can set different start and stop time. This would be relevant, if you wanted to distribute a server-only maintenance script through GPO to handle backups, reboots and other maintenance tasks. Setting both values to the same value sets a fixed time.

Note that there are no options to use a scheduled task trigger other than a daily trigger. This is because you can insert logic to exit at the start of the script on certain days or other conditions. If you want to run a script multiple times a day, you can create a loop using SleepUntil and exit after the last execution of the day.

Refer to the Deploying applications to server farms as an example of using scheduled tasks inside MSi files for servers.

Command line compilation

It is possible to compile scripts from command line. A tool called Build.Exe is located in the installation directory of FastTrack Automation Studio, which can be called to compile script files into exe and MSI files without using the script editor. Start Build.exe without parameters to see a complete list of parameters. For example to compile a script into MSI, the typical syntax is:
Build.Exe /Quiet /ScriptFile <Input Script File> /MSIFile <Output MSI File> /MSITitle <Installation Name> /MSIVersion <Installation Version>
Remember to quote parameters that have spaces, which would typically be the case for the installation name. If you want to create the MSI as a scheduled task, include the /MsiScheduledTask switch. If the /Quiet switch is specified, the successful conversion message will not be shown. In case of an error, an error message will always be displayed.

MSI Compilation summary

Watch Senior Technical Writer Steve Dodson from Binary Research International walk you through the basics of the material presented on this page.

Rating: 5 out of 5

"Use this as a replacement for VBScript and PowerShell"

"It's easy to include attractive GUI elements in FastTrack scripts, beyond the basic dialog boxes and text input that VBScript offers ... Another powerful feature is the ability to distribute scripts as Windows Installer (.msi) or standard .exe files. Although interesting in its own right, this ability results in a much more intriguing capability: to repackage -- or wrap -- software installers as .msi files without using snapshots. If you've ever created an .msi installer file from before-and-after system snapshots, for use with a software distribution system such as Group Policy or SCCM, then you know how hit-and-miss the results can be."

Read full review

Rating: 8 out of 10

"Faster than the rest"

"We found the FastTrack syntax to be more transparent and easier to learn than Microsoft's PowerShell – the editor in particular provided good support in this regard. the Script Editor offers a large number of options from the command set through to simple output of graphical elements, which cannot be achieved at all with PowerShell or other solutions or only with a significantly greater level of effort."

"Anyone wanting to tackle the many hurdles in everyday admin and especially anyone for whom logon scripts and client automation is a priority will benefit from the variety of functions offered by FastTrack."

Review in English      Review in German