dotNetInstaller - Setup Bootstrapper for .NET Application

With this tool the developer can define the application prerequisites and install the correct version of these components in the correct order based on the user operating system type and language, allow the user to download these components from the web or install these components directly.

Introduction

This application doesn't replace tool like InstallShield, Wise or Visual Studio Setup and Deployment Project; my goal is to create an application to help the users to installing the correct prerequisites components. Today applications often need to install several components to work properly: Windows Service Pack, Internet Explorer, MDAC, .NET Framework etc. With this tool the developer can define the application prerequisites and install the correct version of these components in the correct order based on the user operating system type and language, allow the user to download these components from the web or install these components directly from his media (usually a CDROM).

The editor: InstallerEditor.exe

You can create two type of configuration file with the editor:

Standalone Configuration: A configuration that runs the components setups from a specified path, usually a relative path of the dotNetInstaller.exe file. Select this configuration if you want to distribute your application with a CDROM.

Web Configuration: A configuration that download and execute the required components from a specified web site. Select this configuration if you want to distribute the configuration over the web.

With the editor you can create these configurations files and then include these files in the dotNetInstaller resources. With this solution you can only distribute one exe file.

Another solution is to distribute in the same path of the dotNetInstaller.exe the configuration file using the name 'configuration.xml' and if you want you can also distribute a bitmap with the name 'banner.bmp'. dotNetInstaller first checks for this configuration file, if the file doesn't exist the application use the configuration embedded into the exe.

In the XML configuration file you can use some path variables in all command or path settings. Is recommended to use " symbol in all the command attributes that contains one or more space, in msi component the " symbol is not supported and if needed the application add this symbol automatically. Is recommended to use #APPPATH variable in all the attributes with path value (like command, dialog_bitmap, package), this constant allows to write relative path string from the dotNetInstaller.exe folder otherwise all the path are relative to the system current directory.

If you configure the application to download the components, I recommend to download the components using the #TEMPPATH variable and the run the components from the same path.

For example if you want to launch a file ('My App.exe') in the same folder of dotNetInstaller.exe you can write in the command string: "#APPPATH\My App.exe"

In this release you cannot change the order of the components from the editor, if you need this feature you must change the XML manually.

Tutorials

How to create a Standalone Setup to install .NET Framework and your msi setup:

We create a CDROM with your MSI package, SupportFiles (like .NET Framework), configuration file configuration.xml) and a bitmap (banner.bmp). All these components are installed directly from the CDROM.

Create a folder that represents your final distribution CDROM, for example 'c:\MyRelease\' .

Copy under 'c:\MyRelease\' the directory 'SupportFiles' that you can find in the project .zip .

In the SupportFiles replace all the readme.txt files with the real components files that your installation need; for example replace the 'SupportFiles\dotNet\v1.1\English\dotnetfx.exe.readme.txt' with the real dotnetfx.exe file that you can download from microsoft web site.

Copy your msi package (that you can create with Visual Studio .NET, InstallShield or others installation tool) under the 'c:\MyRelease\'.

Copy dotNetInstaller.exe under 'c:\MyRelease\'.

Create a bitmap (banner.bmp 110x208 pixels) with the name 'c:\MyRelease\banner.bmp' with the logo of your application.

Execute the InstallerEditor.exe file.

Select the menu 'File'->'New...' and create a new file with the name 'c:\MyRelease\configuration.xml' .

Select from the menu 'Tools'->'Language for New Item' the user interface language that you want. (for now there are only English and Italian, but you can write your custom messages editing manually the properties.)

Right click on the 'Config File' node and select 'Add'->'Setup Configuration'

Select the just created 'install:' node and customize the properties 'dialog_caption', 'dialog_message' and 'installation_completed' with the name of your application.

Right click on the 'install:' node and select 'Add'->'Component Wizard...'

Select the just created node and customize the properties 'description', 'installmessage' and 'package' with the name of your setup and msi package name. In the package path I use #APPPATH variable that represents the dotNetInstaller.exe path.

Select the menu 'File'->'Save'.

Write all the contents of the 'c:\MyRelease\' directory on your CDROM. If you want you can also create a 'autorun.inf' file that execute dotNetInstaller.exe.

For others informations in the .zip you can find an example of a configuration.xml file configured to install these components for Windows 98, 98 SE, Millennium, NT4, 2000, XP, 2003:

Copy under 'http://www.mysite.com/MyRelease/' the directory 'SupportFiles' that you can find in the project .zip .

In the SupportFiles replace all the readme.txt files with the real components files that your installation need; for example replace the 'SupportFiles\dotNet\v1.1\English\dotnetfx.exe.readme.txt' with the real dotnetfx.exe file that you can download from microsoft web site.

Copy your msi package (that you can create with Visual Studio .NET, InstallShield or others installation tool) under the 'http://www.mysite.com/MyRelease/'.

Create the main configuration file

We create a configuration file that download and install the components from a web site (for .NET Framework and one MSI package).

Execute the InstallerEditor.exe file.

Select the menu 'File'->'New...' and create a new file with the name 'configuration.xml' .

Select from the menu 'Tools'->'Language for New Item' the user interface language that you want. (for now there are only English and Italian, but you can write your custom messages editing manually the properties.)

Right click on the 'Config File' node and select 'Add'->'Setup Configuration'

Select the just created 'install:' node and customize the properties 'dialog_caption', 'dialog_message' and 'installation_completed' with the name of your application.

Right click on the 'install:' node and select 'Add'->'Component Wizard...'

Select 'Microsoft .NET Framework 1.1', 'Downloaded from Internet', and replace 'http://www.myWebSite.com/MyApp/SupportFiles' with your web site for example 'http://www.mysite.com/MyRelease/SupportFiles' and click the OK button.

Right click on the 'install:' node and select 'Add'->'Msi Component'

Select the just created node and customize the properties 'description', 'installmessage' and 'package' with the name of your setup and msi package name. Replace the #APPPATH\mysetup.msi with #TEMPPATH\MyApplicationName\mysetup.msi, this is download destination of the package.

Right click on the msi component and select 'Add'->'Download Dialog'

Select the just created node 'Download Dialog' and customize the properties 'dialog_caption' and 'dialog_message' with the name of your application.

Right click on the 'Download Dialog' node and select 'Add'->'Download File'

Select the just created node under 'Download Dialog' and customize the properties 'componentname', 'destinationpath' (write for example '#TEMPPATH\MyApplicationName\', must be the same path of the 'package' property) and 'sourceurl' (write 'http://www.mysite.com/MyRelease/mysetup.msi') .

Select the menu 'File'->'Save', and copy this configuration.xml file under 'http://www.mysite.com/MyRelease/'.

Create the bootstrapper

We create an executable that download and execute the main configuration file from a web site, changing the dotNetInstaller resources with our custom xml and bitmap.

Create a bitmap (banner.bmp 110x208 pixels) with the logo of your application.

Execute the InstallerEditor.exe file.

Select the menu 'File'->'New...' and create a new file with the name 'reference.xml' .

Select from the menu 'Tools'->'Language for New Item' the user interface language that you want. (for now there are only English and Italian, but you can write your custom messages editing manually the properties.)

Right click on the 'Config File' node and select 'Add'->'Web Configuration'

Select the just created node 'reference:' and customize the properties 'referencefile' for example write '#TEMPPATH\MyApplicationName\configuration.xml'.

Select the node 'Download Dialog' under 'reference:' and customize the properties 'dialog_caption' and 'dialog_message'.

Right click on the 'Download Dialog' node and select 'Add'->'Download File'

Select the just created node under 'Download Dialog' and customize the properties 'componentname', 'destinationpath' (write for example '#TEMPPATH\MyApplicationName\', must be the same path of the 'referencefile' property) and 'sourceurl' (write 'http://www.mysite.com/MyRelease/configuration.xml', must be the URL where you can download the previously created configuration file) .

Select the menu 'File'->'Save'.

Select the menu 'File'->'Create Exe'; in the 'Template dotNetInstaller.exe file' select the path of your 'dotNetInstaller.exe', in the 'Banner Bitmap' select the bitmap created previously. Click Make button and select a file name of the new dotNetInstaller, for example 'MyWebSetup.exe'.

Copy 'MyWebSetup.exe' under your 'http://www.mysite.com/MyRelease/'.

Now the user must only download the 'MyWebSetup.exe' (310 Kb) and this application automatically download and install the required components, in this example .NET Framework and one MSI package.

Path variables

These are the variables that can be used in all the attribute that contains a path (dialog_bitmap,command, ...):

#APPPATH - This string is replaced with the directory of dotNetInstaller.exe program.

#SYSTEMPATH - This string is replaced with the windows system directory (using GetSystemDirectory() API, usually c:\WINNT\System32 ).

#WINDOWSPATH - This string is replaced with the windows directory (using GetWindowsDirectory() API, usually c:\WINNT ).

#TEMPPATH - This string is replaced with the temp directory (using GetTempPath() API, usually C:\Documents and Settings\[User]\Local Settings\Temp ).

Check if the component is already installed

You can use the installedcheck element to check if a component is already installed, for example you can check if the .NET Framework 1.1 is installed by reading this registry key SOFTWARE\Microsoft\NET Framework Setup\NDP\v1.1.4322\Install = 1.

For now there are two type of install check:

'check_registry_value' - Check for a specific registry value.

'check_file' - Check for a specific file with a specific version.

There are two type of comparison when check for a registry value or file version: 'match' (check if the exact value is present) or 'version' (check if the version is greater or equal).

You can look at the example to see the check used with the most common components: .NET Framework, Internet Explorer, MDAC, JET and more.

Check the operating system version

This is the operating system table used to install a component only in a specific operating system version.

Operating System Name

Enum

Numeric Identifier

Not Valid

winNotValid

0

Windows 95

win95

5

Windows 95 OSR2

win95osr2

10

Windows 98

win98

15

Windows 98 Second Edition

win98se

20

Windows Millennium

winME

25

Windows NT4

winNT4

30

Windows NT4 Service Pack 6

winNT4sp6

35

Windows NT4 Service Pack 6a

winNT4sp6a

40

Windows 2000

win2000

45

Windows 2000 Service Pack 1

win2000sp1

50

Windows 2000 Service Pack 2

win2000sp2

55

Windows 2000 Service Pack 3

win2000sp3

60

Windows 2000 Service Pack 4

win2000sp4

65

Windows XP

winXP

75

Windows XP Service Pack 1

winXPsp1

80

Windows Server 2003

winServer2003

90

Next ....

winLater

100

Same examples:

Install a component only in Windows XP (with no service pack check) : os_filter_greater='74', os_filter_smaller='90' .

Install a component only in Windows 2000 or later : os_filter_greater='44', os_filter_smaller='' .

Usually is best to use an install check to see if the component is already installed, but for some components is necessary to check the operating system version (especially for service pack or windows update).

XML Elements help:

Warning: the XML parser is not fully compatible with the standard xml specification; it supports only the basic features. Do not include XML comments and use a normal XML sintax like the examples provided in the .zip. Is recommended to use the editor InstallerEditor to create or modify your configuration files or I suggest to use a normal text editor. If you want to insert the " char in the XML manually you must write &quot; .

configurations

Root element

ATTRIBUTES:

CHILDREN:

configuration

configuration (type='install')

A configuration used to install a collection of components.

ATTRIBUTES:

type

'install' - Type of the configuration. Can be 'install' or 'reference'.

lcid

A filter to install this configuration only on all operating system language equals or not equals than the LCID specified (see Help->LCID Table). Separate multiple LCID with comma (',') and use not symbol ('!') for NOT logic ('1044,1033,!1038' ). You can also filter a specified component.

dialog_caption

Main dialog title.

dialog_message

Main message of the main dialog.

dialog_bitmap

Bitmap file used in the left panel of the main dialog. If this file doesn't exist or this attribute is empty the application load the bitmap from the .exe resource. Can contain path constant (see Help->Path Constant).

install_caption

Caption of the Install button.

cancel_caption

Caption of the Cancel button.

reinstallflag_caption

Caption for the 'Reinstall all check box'.

status_installed

The string used for indicating an installed component.

status_notinstalled

The string used for indicating a not installed component.

failed_exec_command_continue

The message used when a component cannot be installed and ask if the application can continue with others components (Yes/No message). Must contain one '%s' string where the application put the description of the component.

installation_completed

Installation completed message.

dialog_install_next

Caption for the next button.

dialog_install_skip

Caption for the skip button.

installing_component_wait

The message used when installing a component. Must contain one '%s' string where the application put the description of the component.

reboot_required

The message used when the application need to restart and ask if restart now (with a Yes/No message).

CHILDREN:

components

configuration (type='reference')

A configuration used to download a configuration file from a specific URL.

ATTRIBUTES:

type

'reference' - Type of the configuration. Can be 'install' or 'reference'.

lcid

A filter to install this configuration only on all operating system language equals or not equals than the LCID specified (see Help->LCID Table). Separate multiple LCID with comma (',') and use not symbol ('!') for NOT logic ('1044,1033,!1038' ). You can also filter a specified component. If empty no filter is applied.

CHILDREN:

downloaddialog

configfile

configfile

The path to the configuration file downloaded.

ATTRIBUTES:

filename

The configuration file where the application can find the configuration. Usually this is the destination directory of the downloaded component. Can contain path constant (see Help->Path Constant).

CHILDREN:

components

A collection of elements of type 'component'.

ATTRIBUTES:

CHILDREN:

component

component (see also specific help based on the 'type' attribute)

A component to be installed.

ATTRIBUTES:

type

The type of the component; can be 'cmd' for executing generic command line installation or 'msi' for installing Windows Installer MSI package or 'openfile' to open a file. Each type has his own attributes.

os_filter_greater

A filter to install this component only on all operating system id greater than the id specified (see Help->Operating System Table). For example to install a component only in Windows 2000 or later write '44'.

os_filter_smaller

A filter to install this component only on all operating system id smaller than the id specified (see operating system table). For example to install a component preceding Windows 2000 write '45'.

os_filter_lcid

A filter to install this component only on all operating system language equals or not equals than the LCID specified (see Help->LCID table). Separate multiple LCID with comma (',') and use not symbol ('!') for NOT logic ('1044,1033,!1038' ). You can also filter all the configuration element.

installcompletemessage

The message used when a component is successfully installed. To disable this message leave this property empty.

mustreboot

Indicates if ask to reboot after this component is installed successfully (True/False). Normally if the system must be restarted is automatically the component that tells this setup (with special return code) to stop and restart the system, but in special circumstances (for example in Windows 98) we must force a reboot to install correctly some components (for example the .NET Framework).

description

Description of this component. This value is used also in some message to replace the %s string.

installmessage

The message used to confirm the installation of this component.

note

Note, not used by the setup.

CHILDREN:

installedcheck

downloaddialog

component (type='cmd')

A component that can be used to execute an .exe file like a setup application.

ATTRIBUTES:

see also 'component' element

type

'cmd'

command

Specifies the command to execute when installing this component. Must be a valid command for the 'CreateProcess' API. Can contain " char and path constant (see Help->Path Constant).

CHILDREN:

component (type='msi')

A component that can be used to install an msi package.

ATTRIBUTES:

see also 'component' element

type

'msi'

package

Specifies the path to the msi package to execute when installing this component. Can contain path constant (see Help->Path Constant).

cmdparameters

Specifies the command line parameters for the msiexec program. Can contain " char and path constant (see Help->Path Constant). See MSDN for the command line you can use with Windows Installer.

CHILDREN:

component (type='openfile')

A component that can be used to open a web page, a readme file or execute any file during the installation process.

ATTRIBUTES:

see also 'component' element

type

'openfile'

file

Specifies the file to open when installing this component. Must be a valid command for the 'ShellExecute' API. Can contain " char and path constant (see Help->Path Constant). Can be for example a internet link.

CHILDREN:

downloaddialog

Represents a list of files to download and the configurations of the download dialog.

ATTRIBUTES:

dialog_caption

The caption of the download dialog.

dialog_message

The initial message that appears in the download dialog before the user press the 'Start' button.

autostartdownload

True to start the download without user interaction, False to let the user press the 'Start' button.

dialog_message_downloading

The message that appears in the download dialog when the download process start.

buttonstart_caption

Caption of the 'Start' button.

buttoncancel_caption

Caption of the 'Cancel' button.

CHILDREN:

downloads

downloads

A collection of elements of type 'download'.

ATTRIBUTES:

CHILDREN:

download

download

Represent a single file to download.

ATTRIBUTES:

componentname

The description of the file to download.

sourceurl

The complete source path of the file to download. For example 'http://www.yourwebsite.com/ SetupX/Setup.exe' . Must be URL with http:// or ftp:// protocol

destinationpath

The complete destination path where the application copy the sourceurl file. Is recommended to use the TEMP path for destination like this: '#TEMPPATH\\APPLICATION_NAME' . Can contain path constant (see Help->Path Constant).

destinationfilename

New name of the downloaded file. Leave this value empty to use the same filename of the original filename.

CHILDREN:

installedcheck (type='check_file')

The application check if a component is installed looking for the specified registry information or file.

ATTRIBUTES:

type

'check_file' - Type of the check, can be 'check_registry_value' to check for a specific value in the registry or 'check_file' to check for a specific file.

filename

Specifies the file to search, if the application cannot find the specified file then the component must be installed. This attribute can contain path constant (see Help->Path Constant).

fileversion

The version of the file, can be used to perform version check based on comparison attribute. If empty the application check only for the presence of the file.

comparison

Comparison mode, can be 'match' to check if the exact version of the file is present or 'version' to compare if a version equal or greater is present.

CHILDREN:

installedcheck (type='check_registry_value')

The application check if a component is installed looking for the specified registry information or file.

ATTRIBUTES:

type

'check_registry_value' - Type of the check, can be 'check_registry_value' to check for a specific value in the registry or 'check_file' to check for a specific file.

path

Specifies the registry path to search for the registry value specified, must be a path under HKEY_LOCAL_MACHINE like 'SOFTWARE\\MyCompany'.

fieldname

The registry field name in the specified path, for example 'Installed'.

fieldvalue

The registry value used to check if the component is installed, this value is converted based on the value type specified.

fieldtype

Specifies the type of the registry field, can be 'REG_DWORD' (for numeric value) or 'REG_SZ' (for string value).

comparison

Comparison mode; can be 'match' to check if the exact value is present in the registry or 'version' to compare the registry version with the specified version and return true if the registry version is equal or greater then the version specified.

CHILDREN:

Notes

If a component needs to restart the system the application automatically add a key in the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run to reload the application at the next startup.

Is useful that also your setup write a little registry value where you can put some information about the installed version, this allows this application to check if your setup is already installed using a 'installedcheck' element.

In order to install MDAC 2.7 in Windows 98 you must first install the updates for year 2000 compatibility. In my sample configuration files I added a component for this files, you can download these updates from Windows Update Catalog web site.

In Windows 98 after installing .NET Framework I must force a reboot of the computer (with the 'mustreboot' attribute) otherwise some .NET Framework or Windows Installer components or not installed correctly.

The only way that I found to check if JET 4.0 is already installed is to search for Msjet40.dll file in the system directory with the version 4.0.7328.0 (JET 4.0 Sp7).

You can use this project also to launch multiple MSI or others setup at the same time, and can be used also for not .NET project (like Visual Basic, VC++, ...).

In Windows Millennium I had some strange problems if I rename the dotNetInstaller.exe to Setup.exe . If I launch Setup.exe I cannot detect anymore the right operating system version ( return Windows 98 version instead of Windows Millennium ). Anyway all you have to do is to leave the executable name dotNetInstaller.exe or use a name different from Setup.exe.

In my configuration file I also added components for installing Service Pack and others system components, but warning installing this kind of components is always an unsafe operation.

For now I don't delete the downloaded components, for this reason I recommended to use the TEMP path as a destination folder.

To change the resources of the exe file I use BeginUpdateResourceW, UpdateResourceW and EndUpdateResourceW API. These API are available only on Windows NT, 2000 and XP for this reason the editor cannot be used on Windows 98 (the bootstrapper is supported also on Windows 98 ).

Summary of future works

Silent mode and command line support.

History

1.1.0.2 (02 January 2004)

Added ability to download required components from the web.

Added #TEMPPATH path variable.

Editor to create and modify XML configuration file.

Many changes to the XML structure, old files are not compatible.

Fixed a bug on the function that read the operating system LCID and others small bugs fixing.

1.0.8.0 (05 November 2003)

Added #WINDOWSPATH path constant.

1.0.7.0 (28 September 2003)

Bug fixed on MDAC and JET components configuration file (registry check to REG_SZ and language support for JET).

1.0.7.0 (27 September 2003)

First public release.

License

dotNetInstaller - C++ Setup bootstrapper for .NET

Copyright (c) 2003, Davide Icardi

All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

Neither the name of the ORGANIZATION nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

License

This article, along with any associated source code and files, is licensed under The MIT License