Customizing VB6 Setup1.exe - noSE Version - Package and Deployment Wizard (PDW)

NOTE: This file contains explanation and directions for using the included Setup1 Demo Project to easily build graphically unique, customized installers for each of your VB6 programs. The Setup1 Demo Project is a remake of the PDW Setup1.exe file. This version adds several new functions, is much more compact, and does not require Setup.exe. (noSE version stands for "no Setup.Exe".)

Updated 8-15-2006


Introduction
What is in This File?
Differences in This Version of Setup1


Step 1 - Edit Setup1
Step 2 - Compile the new Setup1 and run the PDW
Step 3 - Edit the setup.lst File Produced by the PDW
Step 4 - Rebuild the Setup CAB File and Assemble Your Package
Step 5 - Test install

Notes
Explanation of the Structure in This Custom Setup1 Code
Explanation of Setup1 Without setup.exe - the noSE version

License


Introduction
   The Package and Deployment Wizard (PDW) creates setup packages for VB6. Setup1.exe is the executable that the PDW uses for installation. The PDW normally creates a setup with 3 files (assuming there is a single CAB file): setup.exe is the "bootstrap" file that starts the install. The ProgramName.CAB file contains the program files and Setup1.exe, which is the actual installer. setup.lst is an ini file that holds install information needed by setup.

   When a PDW setup is run, setup.exe extracts Setup1.exe from the setup CAB file, moves it to the Windows folder (?), and runs it with a command line that tells Setup1.exe where to find the other files: the CAB and setup.lst. Setup1.exe then takes over from there.

   Setup1.exe is written in VB6 and the Setup1 project is included in a VB6 install. In fact, not only is the Setup1.exe code available, but it also contains numerous commented notes to provide some guidance to anyone who wants to edit the code.

   In the Wizards\PDWizard folder you should find the Setup1 project folder, a copy of Setup1.exe, a copy of setup.exe, and a file named VB6DEP.INI. (You will need to deal with those 3 files when building custom setups with VB's Setup1 project, but they are not needed for this noSE version.)

   The Setup1 Demo Project that goes with this help file is a rewrite of the version that comes with VB6. It has been "weeded" of confusing and redundant code and several rarely-used functions have been removed, such as remote install option, silent install option, etc. This is, obviously, one version of how Setup1.exe could be written. You may want to use the project as-is or you may just want it for reference in writing your own version. Either way, most of the information in this file will be relevant.

What is in This File?
   In order to customize a PDW setup one needs to know the basics of how the PDW works. This file explains those details and provides a step-by-step guide, "soup to nuts", for anyone who wants to create their own custom setups.

NOTE: This help file is specific to the noSE version of the custom Setup1 code.

Back to Index

Differences in This Version of Setup1
   This version of Setup1 has been cleaned and several optional functions have been removed in order to simplify and shrink the resulting executable.There have also been functions added. The resulting EXE is about half the original size.

Weeding done in this Setup1:
   If you have looked at the original Setup1 code you may have noticed that it seems unnecessarily bloated, convoluted and confusing. For example, the functions MakeLongPath, GetLongPath and LongPath are all pointing to each other! Another example: With variables in the functions to determine whether an installing file should overwrite the existing version, owYes means "No, don't overwrite, the file is not newer" and owNo means "Yes, overwrite the old file".

   In other places several redundant variables are created, apparently to signify different details about the content of the variable. For example, the variable SrcFile might hold the path of a file to be installed. Then if SrcFile is moved to the TEMP folder the code might run something like: TempFile = SrcFile By the end of the function there might be 4 variables that are all holding the same file path!

   This version of Setup1 has been cleaned to remove redundant code and rewrite confusing code. Many functions have been left mainly untouched. It's still essentially the same Setup1, but the code has been simplified. Some of the functions have been entirely rewritten in order to clean them up. Others have been edited in an attempt to simplify unnecessary complexity. Example: The function IsSourceFileNewer was returning a UDT variable, declared in the FileComparison ENUM with 3 constants: fcNewer, fcOlder and fcEquivalent. Yet equivalent gets the same treatment as older in the code, so there is no purpose to it. IsSourceFileNewer was therefore changed to a Boolean function for clarity and the ENUM FileComparison was removed.

Functionality removed from this Setup1
   In the interest of simplicity, optional functions that are rarely used have been removed from this version of Setup1. If you need a specific function you may need to add it back in. The following changes have been made in this Setup1:

   - Silent install functions removed.
   - Remote install functions removed.
   - Special treatment for data access components removed.
   - Does not write path value in registry for multiple apps. (only used if setup.lst includes "AppPath" value in [Setup] section.)
   - No ability to install from 2 or more drives.
   - racmgr.exe, etc. functions removed.
   - Installer must have only 1 CAB.

Functionality added to this version of Setup1
Graphics:
   This version of Setup1 is designed for easy graphical customizing. There are only 3 forms: The "Welcome" form, the form for changing selected install path, and a progress bar form. There are built-in functions to create a color gradient on these forms, if desired. The general design of this Setup1 makes it easy to swap out logos and icons, colors and backgrounds, in order to create a customized, professional-looking installer for each program being installed.

Shortcuts: Start Menu, Desktop and Quick Launch -
   When you open the demo project you'll see that frmBegin.frm has 2 checkboxes, one for a Desktop shortcut and one for Quick Launch. If these boxes are left checked during install then shortcuts will be created in those locations. The shortcut creation will also be logged so that they can be removed at uninstall.

   The PDW normally creates a shortcut and optional folder on the Start Menu only. This version of Setup1 creates a shortcut in the All Users Start Menu\Programs folder. Then it also provides the other two optional shortcuts. In accord with standard practice, the Desktop shortcut is created on the All Users Desktop. The way the code works is to first get the basic Desktop folder, which is the right path for Win9x. Then, if the install is on NT, it tries to get the All Users Desktop path. The result is that the shortcut appears on all Desktops, on all systems.
   The Quick Launch shortcut is created in the current user's Q.L. folder. (If it were created in the All Users Q.L. folder Windows would not display it.)

   Note that you can call the sub AddShortcuts additional times (or edit the sub) if you want to add multiple Start Menu icons.

Application Data Install option -
   With the increasing use of multi-user WinNT systems like XP, the Program Files folder is being used more for just the basic program binaries, while the current user's App. Data folder is used for any configuration information not kept in the Registry. The standard behavior established is that a company subfolder is created in the App. Data folder, and that subfolder stays when the program is removed. This approach will apparently be enforced in Vista, with access to the Program Files folder requiring the highest level of security!

   In order to accomodate these changes, this version of Setup1 has built-in functionality to 1) find the path of the user's App. Data folder, 2) install files to that folder during setup, and 3) leave those files during uninstall. The PDW does not provide an App. Data option, but the setup.lst file can be edited to provide the necessary information so that this version of Setup1 can automatically create an App. Data subfolder and install all designated files there.

EULA clickthrough:
   The Welcome form is set up with an EULA clickthrough. Just insert an appropriate EULA for each build.

Add/Remove Update:
   In Windows XP the Add/Remove applet displays a program icon and program size for each installed program listed. That functionality is relatively new. It was built into Windows Installer setups but is not part of the PDW setup. This Setup1 includes an update to fix that. (While the icon and program size are fairly useless additions to Add/Remove, if you do not provide the size XP will "make a guess". It's not unusual for that guess to be wildly off. So without this update your software listing in Add/Remove might say that the program files take up 800 GB, or something similarly ridiculous.)

Back to Index

Step 1 - Edit Setup1
   This Setup1 is designed for easy customizing. It's recommended that you start by making a copy of the project, one copy specifically for each program. For example, if your program is ABC-Editor then copy the Setup1 project to something like "ABC-Editor Setup1".

   Next, open the project and do the GUI work for the specific program: Change the name and version labels in the Welcome form, select colors or backgrounds for the forms, assign new icons, and insert an appropriate EULA in fWelcome. If you do not want to use the color gradient background option then comment out the ColorBack sub in each Form_Load. If you do want to use a gradient, edit each Form_Load call to ColorBack, specifying the colors you want. For convenience, the parameters are simple 6-character hex strings with RRGGBB format, as in HTML.

   In addition to the GUI update, do a search in the code for "UNIQUE". (All in uppercase.) That string marks areas where you may need to edit the code. For example, in ModDeclares, the constant sSetup represents the title used in message boxes. That needs to be adjusted for each specific program install.

   See the Notes section for important info. about editing the Setup1 project.

Back to Index

Step 2 - Compile the new Setup1 and run the PDW
   After editing the project, compile a new Setup1. The name does not matter for this version of Setup1. You can name it anything you like: Setup.exe, ABCEdSetup.exe, BlahSetup10.exe, etc.

   In this noSE version of Setup1, Setup.exe is not used. The PDW cannot be made to adapt to this setup modification. The package it makes will just have to be edited after creation. So, the next thing to do after compiling a new Setup1 is to just run the PDW and let it do things its own way, creating a new setup package.

Back to Index

Step 3 - Edit the setup.lst File Produced by the PDW
   After creating a setup package with the PDW you should have something like: ABC-Ed.CAB, setup.exe and setup.lst. There should also be a folder named Support.

   There are two steps that need to be performed now: Edit the setup.lst file and rebuild the CAB file. The package can then be assembled.

Edit the Setup.lst file:

   Setup.lst is an INI file. With the noSE version of Setup1 some of the values are no longer relevant, while some new ones must be added. Open setup.lst in Notepad and make the following adjustments:

[Bootstrap] section:

  SetupTitle, SetupText, Cabs and Spawn - Remove these values. They are no longer used. SetupText is what shows in the odd gray window that flashes at beginning of setup. That window is created by Setup.exe, so it won't show with this version of setup because Setup.exe is not used at all. Spawn is the name of the Setup1 executable that Setup.exe should extract from the CAB. Again, there's no Setup.exe so Spawn is not needed. The Cabs value is the number of CABs used in setup. There must be only 1 CAB in this case, so the Cabs value is not needed. (This Setup1 assumes no floppy installs, so more than 1 CAB is not necessary.)

   The other 3 values in [Bootstrap] will stay. Uninstal (st6unst.exe), TmpDir and Cabfile are still used.

[Setup] section:

  Title - Check this value. In the original Setup1 this is used as the title along the top of the fullscreen blue window. That's not used here, but Title is also the name for the program folder. The PDW may not have guessed the name that you want.

   The other settings in [Setup] will stay, but two or three new ones must be added:

  AppSize - This is a new value, specific to this version of Setup1. AppSize needs to be the total size of the installed software, in KB. Example: AppSize=2320. The AppSize value gets written to the Registry and is used in XP to show the program size in the Add/Remove applet window.

  AppRemIcon - This is a new value, specific to this version of Setup1. AppRemIcon is the icon that XP will display in the Add/Remove applet window. This value needs to be an icon from a file in the program folder or a subfolder thereof. The program folder path (i.e. "C:\Program Files\ABC-Editor\") will be concatenated with this value and written to the Registry by this version of Setup1. An example for this value might be: AppRemIcon=abc-ed.exe 0.

NOTE: If [Program Folder Path] + [AppRemIcon Value] is an invalid path, your program may not be listed in Add/Remove.

  AppDataName - This is a new value, specific to this version of Setup1. AppDataName is the name of a folder to create inside the current user's Application Data folder. If this value is missing then any files set to install to App. Data will instead be installed to the program folder. If no files are to be installed to App. Data then this value is not necessary. The AppDataName should be a unique company name, such as Microsoft. Mozilla, Adobe, etc. Example: AppDataName=AceAndAcme

[Bootstrap Files] section:

   This section is no longer needed. It was the list of files that Setup.exe was supposed to install before running Setup1.exe. Typically VB6STKIT.DLL is here, but that will be dealt with by the new Setup1. If the VB6 runtimes were being installed that would also be listed here, but the runtime must be already installed for this Setup1 to work.

[Setup1 Files] section:

   This section is not edited unless files are being installed to App. Data. If you want to install files to an Application Data\YourCompanyName subfolder you must first add the AppDataName value (see above). Since the PDW does not deal with App. Data, it does not matter what path you select for installation when running the PDW. To have a file installed to an App. Data subfolder, edit the path section of the file string as shown below:

File1=@filler2.txt,$(AppPath),,,7/27/06 11:42:20 PM,61,0.0.0.0
File2=@filler1.txt,$(AppData),,,7/27/06 11:42:08 PM,53,0.0.0.0

   Notice that filler1.txt, the 2nd file, is set to install to $(AppData).

   If any of the above explanations are not clear, see the setup.lst file included with the "Blah Program" sample installer. That installer, blahsetup.exe is a self-executing zip file. If you rename it from ".exe" to ".zip" most ZIP programs will be able to open it.

Back to Index

Step 4 - Rebuild the setup CAB File and Assemble Your Package
   Now you have the updated setup.lst file, Setup.exe, the program CAB, and the Support folder. The CAB needs to be rebuilt because you need some of the setup files to be outside of the CAB during installation. It will be rebuilt without those files. Proceed as follows:

1) Copy your edited setup.lst into the Support folder, overwriting the one there, so that you don't risk having your version overwritten when you rebuild the CAB.

2) Open the project .DDF (text) file in the Support folder. Toward the bottom of that file, after the last line that begins with ".Set", you should see a list of all files in the CAB - one per line. Remove the following file names from that list if they appear: VB6STKIT.DLL, ST6UNST.EXE and Setup1.exe (or whatever the name of the Setup1 executable is). Then save the changes to the DDF file.

3) Run the BAT file in the Support folder. That will cause MAKECAB.EXE to replace the project CAB file, leaving out the files that have been removed from the DDF file list.

4) Three files will now need to be packaged outside the CAB in your setup package, along with the setup.lst file: VB6STKIT.DLL (The setup "tookit" used by Setup1), ST6UNST.EXE (The uninstaller executable), and your custom Setup1 executable.

5) You no longer need setup.exe, so that can now be deleted.


6) Ideally, the CAB and 4 files should now be packaged more neatly, perhaps by putting them into a self-executing zip file. Either way, the setup is now started by having the CAB and other 4 files in one place, and then running the Setup1 executable. Since this version of setup does not use setup.exe, it does not matter how long the Setup1 executable name is, or what the name is. The final collection of files going into the package should be:

YourProgram.CAB (the CAB file)
YourSetup1.exe (the custom, noSE version, Setup1 executable)
VB6STKIT.DLL (DLL used by setup)
ST6UNST.EXE (VB6 Uninstaller executable)
setup.lst (setup INI file)

   If using a self-executing ZIP package, put all 5 files into the zip, set it to unload into the TEMP folder, and set it to run your Setup1 executable after unloading. If a self-executing ZIP is not used, all 5 files will still, nevertheless, need to be in the same location when install is run.

Back to Index

Step 5 - Test Install
   Once setup.lst has been edited, the CAB rebuilt, and the setup package assembled, test the installation. If there are any problems, check the steps above to make sure that 1) you used the right version of your custom Setup1 executable, and that 2) the values in setup.lst are valid.

Back to Index

Notes
Code comments: In almost all cases, where there are comments in the Setup1 code, a plain apostrophe marks the original Microsoft comments. My own comments are marked by: '--

Locked controls on forms: A hidden property, LockControls, has been set in the original Setup1 form files (but not in the files in this package). LockControls does not show up in the properties window but it prevents controls from being moved at design time. To unblock the original Setup1 project forms for modification, open them in Notepad and remove the LockControls property manually.

Type Libraries: There are two included type libraries that are referenced in this project. The path will need to be changed in the VBP file or the TLBs will need to be re-referenced:
   VBSHELL.TLB - shows in References dialogue as: VB-friendly Shell interfaces
   SHELLLNK.TLB - shows in References dialogue as: VB 5 - IShellLinkA Interface(ANSI)

PDW bug: As some people may be aware, the PDW's Setup1 code was originally written with a bug in the function SourceFileIsNewer. That function compares versions of files when a file being installed has a version. If version cannot be found then it compares dates. In the original code, the version check worked OK, but the date check had a typo causing it to overwrite an existing copy of the file only if the pre-existing copy was newer than the copy being installed. It should have been written to overwrite the file only if it was *older*. This version of Setup1 fixes that bug.

Win2000/ME/XP installs: Windows 2000, ME and XP all have System File Protection enabled by default, which prevents system files from being overwritten. According to Microsoft, main system files on these systems should only be updated by official service packs. Since all 3 systems already have the VB6 runtime, there are few system files that might be needed anyway. If a newer system file is shipped on these systems the install is likely to loop, rebooting to install the system file, then needing to repeat the action after Windows SFP puts back the old version!

   In order to avoid install problems, system files should only be shipped for Win95/98/NT4. The shipping version should always predate the same file on SFP systems. Some of these files have been handled in service packs to VS/VB. If you look in the Wizards\PDWizard\Redist folder you should see a number of files that have been put there by service packs. The PDW will use those files rather than the version in the system folder. For example, MSVCRT.DLL (The VC++ runtime) should be in the Redist folder. The version should be 6.00.8397.0. No later version of MSVCRT.DLL should ever be shipped. Likewise, several OLE files are in the Redist folder.

   The PDW almost always works well. When it doesn't the reason is usually because the installer was made on a late Windows version, such as XP, and attention was not paid to researching the files being put into the installation, to make sure that they're compatible with the target systems and that no system files being shipped are newer than the versions on Win2000/ME/XP.

Back to Index

Explanation of the Structure in This Custom Setup1 Code
Start -

Sub Main (Mod1)

Calls GetPathStrings and GetProgFolder to work out folder paths needed by setup. GetPathStrings gets path of win, sys, temp, etc. and also path info from setup.lst. GetProgFolder gets path of Program Files folder. If it fails then it shows frmPath and asks person installing to choose a parent folder for installation. Once there's a prog. folder path, an app folder is added to that path and entered into text box of frmBegin as suggested install path. (ex: "C:\Program files\ABC-Editor" )

Then Main loads the forms, puts border on forms and shows fWelcome form. (Each form load contains the code for its own back gradient coloring.)

fWelcome form (opening splash screen with EULA):

When option button is clicked to agree to license, Continue button is enabled (CmdOK) Clicking CmdOK calls ShowBeginInstall (ModFormOps). ShowBeginInstall hides fWelcome and shows frmBegin.

frmBegin form (shows path of install folder and has Install button): If Change Location button is clicked, frmPath is shown to allow for selecting new program folder. Optional shortcut checkboxes here can be unchecked to prevent creating those shortcuts. When Install button is clicked it calls ProceedInstall (Mod1)

ProceedInstall - main installation routine.
Checks to confirm adequate drive space. Starts logging of install for uninstall log file. Calls CopySection (modInstall)

CopySection reads setup.lst [Setup 1 Files] section, getting info. for each file, extracts each file from CAB and determines whether it should be copied over or whether an up-to-date copy of the file exists on the computer already. It copies files with CopyFile (ModOps) to specified folder and saves reg. info. if relevant.

Most of the actual installing code in CopySection, CopyFile, etc. is original from Microsoft. There are just minimal edits done to accomodate things like not logging App. Data files.

   After files are installed...

ProceedInstall calls RegisterFiles and RegisterLicenses. It then adds the shortcut(s) to the Start Menu, Desktop, Quick Launch with AddShorcuts (ModShell) Then it calls AddPerAppPath (ModRegDeclares) to add a new key to App Paths reg. key. And it calls MoveAppRemovalFiles (ModInstall) to install uninstall log file, clean up install files, and add the uninstall reg. key. Then, ExitSetup is called with GintRET_FINISHEDSUCCESS if everything worked out.

Back to Index

Setup1 Without setup.exe - noSE version notes
Setup1 noSE does not need setup.exe, removing approximately 135 KB from setup packages. It also removes the ugly and pointless gray window at the beginning of setup that says, "Copying files. Please stand by." The version without setup.exe is referred to here as the "noSE version" (i.e. "no Setup.Exe") for convenience.

   In a normal PDW setup, the setup.exe file has several functions. It extracts 3 files from the CAB: VB6STKIT.DLL, ST6UNST.EXE, and Setup1.exe. VB6STKIT.DLL is a specialized DLL that provides CAB extraction and logging functions for Setup1.exe. The declares for the VB6STKIT.DLL functions used are in modDeclares.bas. ST6UNST.EXE is the VB uninstaller. Normally, setup.exe copies it to the Windows folder.

   Setup.exe also creates a log file and writes some entries into it. Finally, setup.exe runs Setup1.exe with a command line that consists of:

[Current path] [Log file path] [ST6UNST.EXE path]

   Normally, Setup1.exe starts by processing that command line. The function, ProcessCommandLine, is removed in the noSE version. Instead, the noSE version of Setup1 uses CurDir to find it's location and calls the new sub DoBootstrap to take care of the functions that would have otherwise been performed by setup.exe.

   As a result of these code changes setup.exe is no longer needed. However, there are additional requirements after running the PDW, as explained above.

   The final package, when using the noSE version, consists of the CAB file, with setup.lst and the 3 files listed above stored outside of the CAB. (A good method is to put it all into a self-executing zip file that runs Setup1.exe when unpacked.)

Technical note: When setup.exe is used, it seems to copy the install CAB file to the Windows folder, for unknown reasons. It also copies the Setup1 file to the Windows folder. Oddly, with setup.exe removed, a copy of YourProgram.CAB still ends up in the Windows folder! I have been unable to find any code in Setup1 that does that. It appears to be a bug in the function ExtractFileFromCab from vb6stkit.dll that actually copies *any* CAB passed to the function into the Windows folder. Perhaps ExtractFileFromCab requires that the CAB be in the same folder? That seems too bizarre to be true, but so far I haven't found any other possible explanation for how the CAB file gets copied to the Windows folder in the noSE version. In any case, a function was added to account for the problem: During the function MoveAppRemovalFiles, the CAB file in the current directory (the original unpacking, probably the TEMP folder) is deleted as part of cleanup. An aditional check is then made for a copy of YourProgram.CAB in the Windows folder. If found, that CAB is also deleted. The final cleanup is more thorough than the normal PDW operation. It leaves behind only one copy of the Setup1 executable and a copy of setup.lst.

Back to Index

License
You use the accompanying code at your own risk.

   There are no claims made for this Setup1 code. It may be freely distributed as long as no other licensing terms are applied to it. You may not require others to add a "vanity note" to their code and this code may not be distributed as "Open Source" or under any other terms that add usage and/or redistribution restrictions.

    Joe Priestley


Setup1 code  •  JSWare  •  www.jsware.net  •  jsware@jsware.net