Automates Making a Distributable


Download makedist


MakeDist is a VBScript utility I use to automate Making a Distribution: it makes a backup of the project, copys the executable and optionally the source to my distribution folder, with unneeded files removed, and then zips everything up. I wrote it so I'd stop making mistakes when putting distributions together.


MakeDist is a VBScript text file. It is intended to be run from a Shortcut (.lnk file) with its various command line parameters canned in the Shortcut.

makedist exeName projectFolder [otherFolder]... [/s[name]] [/d] [-name]...

In the Shortcut, set the current directory to contain the .\Backup folder, and usually the project folder. Set the parameters as needed. The exeName and the project folder name are required.

/s Distribute the source.
/sname ...naming the .zip file "name".
/d Use the .exe's modified date instead of its version resource for the backup folder name suffix.
-name Omit files named "name" or extended ".name", or folders if "\name".
otherFolder will be included in the backup and source distribution.

For example, MakeDist is "makedist'ed" by a Shortcut containing a Target and Start In:

"%userprofile%\My Documents\VC98 Projects\MakeDist\makedist.vbs" MakeDist.vbs MakeDist /d -zip.exe

"%userprofile%\My Documents\VC98 Projects"

WMPVolKeys is "makedist'ed" by a Shortcut containing a Target and Start In:

"%userprofile%\My Documents\VC98 Projects\MakeDist\makedist.vbs" WMPVKeys.exe WMPVolkeys /s"WMPVolKeys Source" Common TrayButton

"%userprofile%\My Documents\VC98 Projects"

The .zip'ing is done with Info-Zip's free zip.exe. I wasted quite a bit of time trying to do the job with Windows' built-in Compressed Folder stuff (zipfldr.dll), but it's really not documented, even though it's been around since Windows 98. Googling around eventually turned up gzip, which led me to Info-Zip.


My first attempt at makedist was a batch file (see figure). The result was almost satisfactory, though I couldn't find a command to get the file version and had to write my own. The xcopy command had a handy feature, the /EXCLUDE parameter, which made it easy to strip out unneeded files. Well, fairly easy, as the list of files had to be in a file itself, which the batch file made if missing. Learning all the tricky parameter and variable expansion flags was sort of fun, as was figuring out how to execute a command and set a variable to its output, by using for with the /f "usebackq" flag to enable the feature. All in all, a triumph of cryptic script.

Windows may depend on path names, but it doesn't handle them well, certainly not in the Command Prompt (cmd.exe). Many paths - even short paths - require quoting, say, if the path contains an ampersand ("&"), but commands themselves can't be quoted. I eventually gave up on batch files and turned to another scripting language, VBScript.

My VBScript version (see figure) handles paths well, and path manipulation relies on method calls rather than command expansion flags. Actually, VBScript itself doesn't operate on files at all, but additional scripting objects such as the Scripting.FileSystemObject and WScript.Shell do a fine job of it. VBScript has some other limitations, such as lacking a useful STOP statement, but it does have various EXIT statements, such as EXIT FOR and EXIT SUB, which allow for reasonable code structure. It has only three variable types: variants, objects, and arrays. Variables normally are assigned as implicit LET statements, but assigning an object to a variable requires a SET statement, for no good reason that I can find. Also, the VBScript documentation is somewhat lacking, in that it assumes that VBScript is just a subset of Visual Basic, without ever being explicit about what parts of Visual Basic are included, such as statement continuation (with "_") or multiple statements (with ":"). It also lacks any form of I/O, so it can be a bit hard to tell when a script has finished execution.

The code is structured as if it were in a "real language". Global variables are defined at the top, then the various functions and subroutines, and finally the main program at the bottom. VBScript doesn't require this, but it makes the code and variable declarations easier to follow. All variables must be explicitly declared, which allows VBScript to warn me about misspelled variable names.

The locations to put distributables and backups in are declared at the top with the other Global variables. Distributables have an absolute path, but backups are relative to the current directory, a feature that might come in handy later, though not so far. The lists of files and folders to exclude are kept in strings, with entries separated by a character that normally isn't allowed in a file name, ":". The lists can be searched with the INSTR function. The lists can be extended with command line parameters, which is why they aren't declared CONST. The two file system objects are created. I needed both. The Scripting.FileSystemObject had most of what I needed, but the WScript.Shell object has the current directory, run, and timed message box stuff. The temporary directories are declared here so they can be cleaned up properly on errors.

Argument parsing can be confusing, and GetArgs is the last of several iterations. As structured now, parameters can be positional, or they can be flags in any order, and flags can have additional data. GetArgs only checks the syntax of the command line when it parses it, leaving semantic checks for later. All the flags must be "real", and there must be at least two positional parameters.

MakeDistImpl does the work. First it validates the two required positional parameters, the exe and the project, sets up paths, and then copies the project and other folders to a temp directory, omitting various files, by calling CopyFolderExclude. It then zips up the copied folders, changing the current directory so that only relevant path information will be placed in the .zip file. It tries to report all errors and check parameters enough that there won't be unexpected errors. I want unexpected errors to be brought to my attention, so I don't use On Error Resume Next.

CopyFolderExclude is a simple recursive directory copy routine that iterates over the files and copys files that don't match the excludes list, and then iterates over the directories and calls itself for any that don't match the excludes list.

ZipIt encapsulated running zip.exe as an external command. Flags are set for recursive copying, quiet mode, and tight compression, and it is run in a hidden window. We wait for completion so we can return a status code, and anyway, running several cpu-intensive tasks at the same time won't be faster.


Back to Tony NelsonJHC's R Pentomino's Home Page

Valid HTML 4.0!