Introduction
I recently ran into a problem where I required a self-extracting installer that would allow customers to download one single huge file in order for them to choose from a variety of setups or associated documents, like readme files or release notes. Consider a company that ships a product suite that is made up of different components like a server installation, a client installation, an administrative installation, and a command line tools installation. If each of those components has a separate setup program or an MSI file that customers have to download, this is soon going to be tedious for the customer. Having all relevant setups for each component combined in one big self-extracting installer with a user interface that allows for the selection of an individual component would be the ideal solution for this problem.
Requirements
I came up with the following requirements for the solution to this problem:
- The individual setups should be stored in a compressed format in the self-extracting installer.
- The compression format should be a standard format.
- The self-extracting installer should run on Windows 2000 and higher OS versions, and should be entirely UNICODE.
- The individual setups to be extracted should be extracted on an on-demand basis, so not all embedded setups are extracted during program start. This way, only the minimum temporary storage is required on the user's hard disk, and program startup is as fast as possible.
- Every setup component should be startable either via the execution of a program whose command line and executable can be specified, or be ShellExecute'd via the setup component's file extension. An MSI file should be started via MSI APIs so that the MSI's user interface is parented to the self-extracting installer window. This way, MSI setups appear to be much better integrated into the self-extracting installer.
- The programs that make up the self-extracting installer should be reusable. There must be a convenient way to create a custom self-extracting installer with a program that serves as sort of a self-extracting installer editor.
Solution Overview
As the compression format, I chose the zip format. There are a number of constraints or limitations in using the zip format, that I will outline below. At creation time of the self-extracting installer, a zip file, containing all files that make up the installation, is appended to a stub file (sfx.exe). The stub will extract a couple of files, immediately at runtime, into a temporary directory, and then launch a child process (setupui.exe) that implements the user interface that can be seen in the screenshot at the top of the article. The creation of a self-extracting installer is done with the program sfxmaker.exe that is built as part of this project. Using sfxmaker.exe, you can specify which files go into the self-extracting installer and which components of the self-extracting installer are offered to the user at runtime. You can also brand your self-extracting installer with your company's name so that the self-extracting installer's file version information contains your company and product name. In addition, several localization aspects can be done with sfxmaker, such as the text on the labels and buttons of the self-extracting installer's user interface.
For each component to be installed, you can specify a custom icon that appears in the list control of the self-extracting installer next to the component's description. For this to work, those icon files have to be added to the project, and must be extracted during startup of the self-extracting installer so they can be shown immediately. As a convention, all files to be extracted at startup of the self-extracting installer must start with "setupui", so these icon files must have names that start with "setupui" as well. Some files to be extracted at startup of the self-extracting installer have predefined names: If there is a file named setupui.bmp, it will be displayed on the self-extracting installer user interface like the bitmap with the bubbles in the screenshot above. If a file named setupui.ico is contained in the self-extracting installer package, it will be used as the icon of the self-extracting installer when Alt-tabbing between applications, so it is best if you add your product's icon file as setupui.ico to the installer package in sfxmaker. If a file named setupui.avi is contained in the self-extracting installer package, it will be displayed in a progress dialog if a setup program is invoked from the self-extracting installer while the installation runs, unless the setup is an MSI installation.
Sfxmaker.exe is a document view model based MFC application that works with documents with the file name extension sfx. One such sfx document created by sfxmaker.exe describes exactly one self-extracting installer binary, and has the format of a Windows INI file, albeit in UNICODE format (UTF-16). This makes an SFX file human readable, and also perfectly suited for source control systems. At creation time of the self-extracting installer package, this SFX document file is added as setupui.ini to the zip file, and setupui.exe can extract all relevant information at runtime from this file.
Seeing the Installer at Work
In order to get an impression of how such a self-extracting installer package works, please download the self-extracting installer demo, unpack and execute it. This demo shows the fictitious foobar application suite that shows the various components in the list control that can be installed or launched. The first two components launch MSI files for the foobar server and client. These two components show the special treatment of MSI based setups, because the self-extracting installer window acts as a parent window for the MSI installer windows. Now, launch the third setup, the foobar tools setup. This setup is also MSI based, but it is launched via a special command line using msiexec. Notice that there is no parent-child relationship of the self-extracting installer window and the MSI user interface, in this case, and that the self-extracting installer shows a progress dialog while this setup is running. You can override the relatively boring animation in this progress dialog if you specify a setupui.avi file in your self-extracting installer package, as mentioned before. The fourth component starts an executable that demos how you can add arbitrary EXE files to be executed from your self-extracting installer package. Notice that you will also see the progress dialog in this case.
The last two entries allow the user to launch a PDF file with the release notes and a readme text file. For both components, the icons that are displayed in the list control are extracted at runtime from the associated applications, which are Acrobat Reader and Notepad, in most cases. Extracting the associated icons at runtime helps you display the Acrobat icon without adding it to your installer package, which would be a violation of Adobe's copyrights. If there is no associated application with a file to be ShellExecute'd, like it is done with the readme file or the PDF file, then there is simply no icon visible for the list control entry of the setup component.
Running sfxmaker
In this paragraph, I will show how you can recreate the self-extracting installer demo from existing source files. This way, you will get a rough idea of what you have to do in order to create your own self-extracting installer for your product. First, download the demo project for a self-extracting installer, and unzip it with directory preservation into the drive c:\ root directory. The files that make up this demo project should now all be in the directory c:\sfxdemo. You will see that this directory contains the individual MSI files for the foobar client, server, and tools installation. You will also see a couple of *.ico files for the individual setups, and the readme.txt and the relnote.pdf files. Now, download the project's source code into an empty directory of your hard disk, and find the release directory with the sfxmaker.exe file in it, and launch it. The user interface of sfxmaker.exe will look like:
Now, open the file c:\sfxdemo\sfxdemo.sfx in sfxmaker and notice how all the user interface elements are populated:
- The label "Company name" contains the name of your company, and is shown in the version info resource of the final self-extracting installer.
- The label "Product name" contains the name of your product, and is also shown in the version info resource of the final self-extracting installer.
- The list control under the label "Installation components" contains information about the installation components in the order in which they appear in the self-extracting installer's list control. You can move individual items or add and delete new items with the buttons at the right side of the list control. You can change the values for each item with a double click on the item. This will invoke a dialog where you can change the individual parameters of the component.
- The list box under the label "Files" contains all the files that are compressed into the zip file that is appended to the stub to create the self-extracting installer. Use the buttons at the right side of this list box to add or delete files. The order of the list box items is irrelevant.
- The text you can specify next to the label "Header text" is the text that appears in the label above the component list control of the resulting self-extracting installer.
- The text you can specify next to the label "Title text" is the text that appears as the window caption of the resulting self-extracting installer.
- The text you can specify next to the label "Install button text" is the text that appears on the button that launches an installation in the resulting self-extracting installer.
- The text you can specify next to the label "Quit button text" is the text that appears on the button that exits the resulting self-extracting installer.
- The combo box with the label "Vista execution level" specifies the execution level of the resulting self-extracting installer when run on Windows Vista.
Now, click the button labelled "Create SFX". This will prompt you now for the name and location of the resulting self-extracting installer. Choose a name and location of your liking, and click OK. It will now take a few seconds, and then the self-extracting installer will have been created for you.
Adding and Updating Components
If you add a new component or update an existing one in sfxmaker, a dialog like the following will be presented to you:
The items that you can specify for each component here are as follows:
- Description: This is the text that appears in the list control of the resulting self-extracting installer for the component.
- Command line: This is an optional command line for the component that is executed if the installation button is pressed for the component in the resulting self-extracting installer, or if the component is double-clicked.
- Application: Here, you can specify the application path for the file to be executed in addition to the command line.
- File to unpack: This is the name of the file as it resides in the zip file of the self-extracting installer. If the installation button is pressed for the component in the resulting self-extracting installer, or if the component is double-clicked, then this file will be extracted into the temporary directory, and then optionally either the command line will be launched, or the file will be ShellExecute'd.
- Icon file: This is the icon file that will be shown next to the component text in the user interface of the resulting self-extracting installer. If this value is empty, the icon will be determined at runtime from the unpacked file's extension. If you specify an icon file here, make sure its name starts with "setupui".
- Text: This is the text that appears under the list control in the user interface of the resulting self-extracting installer if the component is selected.
For the "Application" and "Command Line" items, you can specify text that contains environment variables. They will be resolved at runtime by the self-extracting installer. You can use the special environment variable CURRENTDIRECTORY. This environment variable expands, at runtime, to the temporary directory where the files are uncompressed to by the self-extracting installer. Look at how the "Foobar Tools 1.0" installation in the demo project uses this variable so msiexec.exe finds the MSI file. Make sure that you add a corresponding file name to the "Files" list box for every component's "File to unpack" you add. Also make sure you add each icon file to the "Files" list box.
Using the Code
Use Visual Studio 2005 with a Vista SDK or a Server 2008 SDK integrated to compile the project. A bare bones Visual Studio 2005 installation will not work because for some reason beyond my imagination, Visual Studio 2005 is missing the import library for msi.dll, msi.lib. In addition, I heavily use PREfast __analysis_assert statements in my code in order to make it PREfast-clean. You can also use Visual Studio 2008 which will convert the solution and project files for you into the Visual Studio 2008 format. For both development environments, you need a variant that contains MFC, so the express editions will not suffice. In order to compile the project files, first extract the source code for this article recursively into an empty directory on your hard disk. Under the project's sfx directory, create a subdirectory named zlib123 which then should be in parallel with the subdirectories include, lib, mc, setupui, sfxmaker, sfx zlibstat, and sfxcommn. This is because you also need the current version of the zlib library, version 1.2.3. Download a copy of the library here. Unzip the zlib files into this directory, again with directory preservation. Now, you should be able to compile the whole project.
Limitations
The current implementations suffer from three main limitations, you have to judge yourself if they are problems for you:
- The file names embedded in the self-extracting installer should better contain 7-bit ASCII characters only. Although the entire project is UNICODE only, file names in zip archives are not UNICODE. So, in order to prevent any problems, use 7-bit ASCII characters for file names.
- The total sum of files to be added to a project may not exceed 2 GB in size. This again is a limitation of the zip format.
- Currently, all the files that are embedded in the zip file of the resulting self-extracting installer are contained in the root directory of the zip file. This way, all files added to the project must have unique names.
Extracting All Files
Using the command line parameter -e or -x you can extract the content of a self-extracting installer into a directory. Specifying only -e as the command line parameter will show a directory picker dialog that you can use to select or create a directory, where all files in the self-extracting installer should be extracted to. If you use -e=targetdirectory or -x=targetdirectory as the command line parameter, all files will be extracted to the target directory without showing the directory picker dialog. So for example, if you specify -e=c:\foobar, all files will be extracted to the directory c:\foobar. If necessary, the directory will also be created.
Trivia
You can open a self-extracting installer built with the code and binaries from this article with Total Commander, much like a zip file. Just select the file and type Ctrl-Pagedown. You can then select individual files from the self-extracting binary and copy them from there to somewhere else.
Future Outlook
It would be interesting to change the user interface that is presented via setupui.exe to an HTA-based user interface. This way, the design of the UI could be entirely left to the user and his/her HTML skills. Adding a command line option to sfxmaker to run it in an automated way from a build script would also be something real cool.
History
- Version 1.0.0.39 - 10/19/2008
- 10/23/2008 Edit
- Added a hint that for Visual Studio 2005, a recent SDK is required, because of the missing msi.lib in Visual Studio 2005 and missing
PREfast support in Visual Studio 2005 without a recent SDK
- Version 1.0.0.40 - 11/28/2008
- Added the option to extract all files from a self-extracting installer using the
-e or -x command line parameters
- Version 1.0.0.41 - 11/28/2008
- Fixed bug with failing installer starts on Vista with execution level set to "run as invoker"
- Added forgotten serialization of Vista execution levels
- Version 1.0.0.42 - 12/12/2008
- Added handling for
-? or -h command line parameters which will show a messagebox with an explanation of all command line parameters
- Made UI a bit larger
| You must Sign In to use this message board. |
|
|
 |
|
 |
Hello all,
I have moved recently from my old XP machine to Windows Vista (Yes, I am slow...). Runing now with Service Pack 2 and Visual Studio 2005, developing in C++ (not managed).
When I recently had to make a change in my program, it works fine on my PC, but when trying to run it on the client's machine it fails.
It comes up with "The application has failed to start because the application configuration is incorrect. blah blah..."
I tried looking for the latest redistribution package, but the latest one I can find for VS 2005 is dated sometime in 2007.
It seems I managed to isolate the problem to a specific VS 2005 patch called "Security Update for Microsoft Visual Studio 2005 Service Pack 1 " - If I install this, my resulting EXE no longer runs on an XP machine.
Any suggestions? PLEASE...
Cheers Alex
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
Hi Stefan
Thanks for that. Probably a good idea.
Will be good if you can point me out to where from to get it.
Cheers Alex
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Alex,
please google for "vcredist" or "vcredist.exe", also check if your VC installation has a file with a similar name. Also keep in mind that VC comes with MSI merge modules (msm files) that you can use with your installer, if it is MSI based.
-- Stefan
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi Stefan,
Thanks for the feedback. I have been using vcredist fro a long time, I searched for the latest, and installed it on the target machine, but still no go.
It seems something in the security patch #1 is newer than what is in the vcredist package.
Hope someone has another idea maybe.
Cheers Alex
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Alex,
As far as I know, the latest patch for ATL that patched a great deal of VS2005 and 2008 header files and libraries made a couple of new runtime DLLs necessary for builds that are made after this patch. I dunno if a new vcredist was deployed as well as part of this patch. I am glad that I almost exclusively use static linking and that VS2010 will relieve us from the manifest hell, because VS2010 will not use manifested runtimes anymore.
-- Stefan
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Just a tiny thing: the source code size is shown in the article with 510 MB (megabytes!). I downloaded it anyway and was happy that it only had 510 kB 
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hello knestel,
I have already noticed this and it will be fixed with the next update that will hopefully be online in a few days matter.
-- Stefan
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
 | folders  Member 4510372 | 17:58 27 Nov '08 |
|
 |
I am installing a program that has .net and sql express as prerequisites. These prerequisites sit in folders of their own next to the main msi and setup file. They can't sit within the same folder. What do you suggest?
I thought about zipping the files and including the zip in your sfx ... then running a command to unzip them ... then possibly running setup.exe ... is there a better way?
Reading your article, it did say that you have a limitation on including folders ... so i am out of luck eh?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hello Member 4510372,
yes I am afraid you are out of luck then. Supporting a zip file structure with subfolders was not on my agenda for my first version of a self-extracting installer because all I personally needed was a flat directory where I could my individual MSI files into. Maybe a subsequent version will support subfolders.
-- Stefan
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I really need to simplify the installation of additional game files. These files need to be placed in two folders inside the games install directory.
The game is located at c/program files/shockwave/Think Tanks, and the self installer I wanted to try to create would put additional files in c/program files/Shockwave/Think Tanks/game/ and in c/program files/Shockwave/Think Tanks/game/client folders. There is an additional small .cs file that goes in the main Think Tanks folder. Is it possible to create something that will simplify the placing of these files as most of the players trying to expand the game are young and not computer literate.
Thanks in advance for any input.
Frank
Keep Medicated!!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hello Frank,
Yes, surely. Write an MSI file that installs the files into these folders and invoke them using /qn so users cannot accidentally install into a fifferent location. But I don't see how this is related to this article. Could you elaborate?
-- Stefan
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi Steve, I'm not sure how I ended up posting it here. I guess Ive been searching online for answers and I thought self extracting installer was close to what I needed. I know a bit about computers, but I don't think I have what it takes to make MSI or invoke with /qn because I don't know what that is. I'd like to learn because what I need is so simple, yet It would solve a 5 year old problem of players updating a game. Its only a matter of 2 or 3 folders and one text file or main.cs file in the main folder. I have been spending much time one on one, on yahoo messenger helping players update but I'm afraid I can't continue helping one on one. I run a website where I can simply host a file for download and the players can just extract it and run it and the file/folders get put into the right place/directory. This would be the greatest thing I can contribute to the community and is much needed. Any help with this would be fantastic. Also thanks for the reply and have a great T-Giving and holiday's.
Frank
Keep Medicated!!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
You listed a couple of requirements for your installer but I don't see any requirements that aren't supported by WIX or NSIS.
|
| Sign In·View Thread·PermaLink | 5.00/5 |
|
|
|
 |
|
 |
Hello Ramon,
correct me if I am wrong, but WiX is for creating individual msi files, not for Ueber-Setups, that combine several individual setups into one single large executable. In fact, the three msi files that are part of the demo project, have been created with WiX version2 and are modifications of a sample that comes from the famous tramontana WiX turorial. How do you create a similar setup that combines multiple ones in WiX?
Regarding NSIS: I looked at NSIS a few months ago and found it terrible. I personally stick with WiX (mostly v3 today) and MSI for individual setups. But that's only my position, your mileage may vary.
-- Stefan
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi Stefan,
I'm sorry you are indeed correct regarding the multi-setup issues with wix. It was a long time ago that I needed similar requirements and thought I then solved it with wix 100% but after browsing the sources it did not.
I used another boot to bootstrap it up with dotnetinstaller which can be found at the following location:
http://www.codeproject.com/KB/install/dotNetInstaller.aspx
NSIS can do this in its own scripting so no wrapping up required there and I too don't use it as it cannot be used in corporate environments because you cannot easily add those packages to for example group policies as can be done with msi packages.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi Ramon,
That's interesting. I will have to take another look at NSIS to see how a multisetup thing looks like with NSIS. Before I started working on this project I certainly looked at dotNetInstaller as well and hoped it would solve my problem. But back then (it might have changed meanwhile) it didn't have the option to pack everything into one big file, at least not in the stable build. I also found no way to have independent setups launched from dotNetInstaller, only one setup and its dependent ones, but maybe I was just too stupid to get dotNetInstaller to work for me this way. But actually, dotNetInstaller was the thing that inspired me to write the code for this project. In fact, I think if you have the need for dependent individual setups, especially with .NET based apps, dotNetInstaller is probably the best choice. But I currently do no .NET based development and therefore have no such dependency, therefore the good stuff in dotNetInstaller seems to be of no help for me. Therefore I wrote the code and this article. I also dunno if dotNetInstaller has the option to just ShellExecute stuff and has special handling of MSI files. But it wouldn't surprise me either if it had because I think dotNetInstaller is a good thing to use.
-- Stefan
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
 |
I compiled your project using VS2005 Team Edtion. I got following from output window. What shall I do now?
4>sfx.cpp 4>h:\installer\sfxcp\sfx\sfx\sfx.cpp(213) : error C3861: '__analysis_assert': identifier not found 4>h:\installer\sfxcp\sfx\sfx\sfx.cpp(222) : error C3861: '__analysis_assert': identifier not found 4>h:\installer\sfxcp\sfx\sfx\sfx.cpp(223) : error C3861: '__analysis_assert': identifier not found
Johnson Zhou
|
| Sign In·View Thread·PermaLink | 4.00/5 |
|
|
|
 |
|
 |
Hello Johnson Zhou,
You are right. I always have one of the latest SDKs (currently Vista SDK or Server 2008 SDK) integrated into VS2005. If you have only VS2005 installed, then these errors appear, because obviously there are no headers for PREfast available with a minimum install of VS2005. I will correct this as soon as possible.
-- Stefan
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
 |
Hello Johnson Zhou,
I updated the article to reflect in the text that you definitely need a recent SDK (either the Vista SDK or the Server 2008 SDK) in addition to your VS2005 installation to compile the source code. This is because for some strange reason, VS2005 does not ship with an x86 version of msi.lib (strangely enough, the x64 version is there). The compilation errors you see come from my usage of PREfast macros (when compiling with the /analyze command line switch) to make the code PREfast clean. Both SDKs I mentioned properly support these macros, just make sure you integrate them into VS2005 with their "Integrate Windows SDK with Visual Studio 2005" start menu entry. If you use VS2008, you don't need an additional SDK.
HTH,
-- Stefan
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
 |
Hi. Stefan, Excellent job! I can compile it with VS2008. thanks a lot. By the way, I thank NSIS is also a good job. You can try it again. Just one little thing, NSIS may has some problem with UAC of Vista(I can not download the UAC plugin, don't know why).
Any way ,thanks
Johnson
Johnson Zhou
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
|