![]() | ![]() | ![]() | ![]() | ![]() |
I wanted to be able to create MSI (Windows Installer) packages by defining a simple script and processing this via command line tools that could be run via a make file or simply a batch file.
I found that Wise installer supports OLE automation. I did a bit of research and created a header file which will generate a Visual Basic Script (VbScript) which when executed will create an MSI installer package from scratch (no template required).
The defined macros currently support:
Other stuff not currently supported can be added via more macros or simply via inline VbScript. Unless you wish to add inline VbScript you do not need to have any knowledge of this language.
There is no need to ever use the wizard although it can be handly to confirm the approach you are using or for debugging your script. Another reason is to examine the tables that wise uses so you know how to update them from the script.
If you have many projects you will find that even though these scripts are simple, 90% of what they do is common between them and a bit of tweeking will quickly get your second, third or hundredth script going in no time. Nothing is hidden by the wizard, code and changes can be commented and PVCS and other standard difference like tools can be used.
In future I plan on creating a de-compiler (disassembler) for MSI/WSI files so that you can take existing packages and create a script from this (it would probably need tweeking to make more readable but should work OK without the tweeking).
This is the sample script I was using for my testing. It produces a perfectly executing MSI package that correctly installs and uninstalls:
;--- Include PPWIZARD WISE INSTALLER OLD AUTOMATION support ----------------- #include "WISEINST.WIH" ;--- Define some global variables ------------------------------------------- #define ProductName PPWIZARD #define ProductVersion 20.00.355 #define ProductAuthor Dennis Bareis - <$BSD> #define ProductDir Program Files\PPWIZARD_W #define ShortCutDir <$STARTBAR_PGM_DIR>\PPWIZARD_W ;--- Start Install Package -------------------------------------------------- <$PackageStart> ;--- Set some properties ---------------------------------------------------- <$SetProperty NAME="ProductName" VALUE="<$ProductName>"> <$SetProperty NAME="ProductVersion" VALUE="<$ProductVersion>"> <$SetProperty NAME="Author" VALUE="<$ProductAuthor>"> <$SetProperty NAME="Manufacturer" VALUE="<$ProductAuthor>"> ;--- Update PATH (system/at end) -------------------------------------------- <$Path PATH="c:\at\end\system"> ;--- Update PATH (user/at start) -------------------------------------------- <$Path \ PATH="c:\at\start\user" \ SYSTEM="N" \ ATEND="N" \ > ;--- Set another "PATH" like variable --------------------------------------- <$Path \ NAME="REGINA_MACROS" \ PATH="c:\at\end\reginamacros" \ > ;--- Add files to "COMPLETE" ------------------------------------------------ <$AddFile \ SOURCE="c:\winnt\system32\notepad.exe" \ DESTINATION="Program Files\PPWIZARD_W\notepad.exe" \ > ;--- Load all files (including from subdirectories) ------------------------- <$AddFiles \ SrcDir="C:\tmp\Test InstallShield\PPWIZARD" \ DestDir="Program Files\PPWIZARD_W" \ > ;--- Create a shortcut to the doco ------------------------------------------ <$AddShortCut \ Title="Test PPWIZARD_W Shortcut" \ ScDir="<$ShortCutDir>" \ ScTarget="<$ProductDir>\PPW_DOCO\ppwizard.htm" \ ScDesc="A test short cut to ppwizard doco" \ ScType="<$FOR_CMDLINE>" \ > ;--- Set registry key ------------------------------------------------------- <$AddRegValue \ HKEY="<$CURRENT_USER>" \ KeyPath="Software\ANZ\PPWIZARD_W" \ ValueName="TestPPWIZARDKEY" \ Value="TestPPWIZARDVALUE" \ > ;--- End Install Package (compile) ---------------------------------------- <$PackageEnd>
While the above is good for testing, in real life I would have things slightly different, for example I would either pick up the version number by reading a file or pass it using the "/define" switch.
I would never want to modify the script unless the packaging requirements changed.
This is the header file that is included in the above script, you would never touch this file apart from adding macros etc to make scripts like the above easier to write.
The header file is not documented so for that reason only a person writing a script would need to refer to the file:
;---------------------------------------------------------------------------- ; ; MODULE NAME: WISEINST.WIH ; ; $Author: USER "Dennis" $ ; $Revision: 1.1 $ ; $Date: 01 Jan 2001 18:37:18 $ ; ; DESCRIPTION: Provides a script like OLE AUTOMATION SUPPORT for ; wise installer. ; ; Do NOT touch this file it is included by your script! ; ; No VB knowledge is required. ; ; To build (uses PPWIZARD - free preprocessor): ; ; REM *** Convert script into VB code ****************** ; ppwizard test1.wi /output:out\*.vbs /other /dependson:out\*.dep /define:WISEWSI=c:\tmp\test1.wsi ; ; REM *** Execute VB code to create MSI package ******** ; if not errorlevel 1 cscript out\test1.vbs ; ; PPWIZARD is the most powerful preprocessor available ; AND IT'S FREE, it's homepage is at: ; ; http://www.labyrinth.net.au/~dbareis/ppwizard.htm ; ;---------------------------------------------------------------------------- ;--- Define Version number of this install support -------------------------- #ifdef WISEINST_VERSION #eof 1; ;;Don't process again if included twice! #endif #define WISEINST_VERSION 00.356 ;--- Make sure user specified the name of the output file ------------------- #ifndef WISEWSI #error ^The define "WISEWSI" must contain name of output WISE package^ #endif ;--- Define our group ------------------------------------------------------- #define BSD ANZ - Australia - Branch Systems Development - (03)9658-1409 ;--- Default feature -------------------------------------------------------- #define Complete Complete ;;Default Feature Name ;--- WISE HKEY TYPES -------------------------------------------------------- #define CURRENT_USER_PUI -1 #define CLASSES_ROOT 1 #define CURRENT_USER 2 #define LOCAL_MACHINE 3 #define USERS 4 ;--- WISE REGISTRY KEY TYPES ------------------------------------------------ #define STRING 0 #define EXPANDABLE_STRING 1 #define INTEGER 2 #define BINARY 3 ;--- WISE ADD KEY OPERATION TYPES ------------------------------------------- #define CREATED_IF_MISSING 1 #define CREATED_...More ;--- Add to Component or Feature -------------------------------------------- #define FEATURE 0 #define COMPONENT 1 ;--- Attributes ("OR" or "ADD" together) ------------------------------------ #define CANT_RUN_FROM_SOURCE 0 #define ONLY_RUN_FROM_SOURCE 1 #define RUN_FROM_SOURCE_OR_LOCAL 2 #define KEY_PATH_FOR_REGISTRY 4 #define INC_SHARED_DLL_COUNT 8 #define NOT_REMOVE_AT_UNINSTALL 16 #define KEY_PATH_FOR_ODBC 32 #define COMPONENT_IS_TRANSITIVE 64 #define NEVER_OVERWRITE 128 ;--- How to add wildcard files from directory ------------------------------- #define NO_SUBDIRECTORIES 0 #define SUBDIRECTORIES 1 #define UPDATE_NEW_COMPONENTS 2 ;--- Shortcut types --------------------------------------------------------- #define ADVERTISED 1 #define FOR_FILE 2 #define FOR_CMDLINE 3 ;--- Define some directory location ----------------------------------------- #define DESKTOP_DIR Windows\Profiles\Desktop #define STARTBAR_DIR Windows\Profiles\Start Menu #define STARTBAR_PGM_DIR <$STARTBAR_DIR>\Programs ;--- Define some window sizes (for shortcuts) ------------------------------- #define NORMAL 0 #define MINIMISED 7 #define MAXIMISED 3 #define MINIMIZED <$MINIMISED> #define MAXIMIZED <$MAXIMISED> ;--- Start of Install script ------------------------------------------------ #OneLine '<?NewLine>' #define PackageStart '---------------------------------------------------------------- ' This file was automatically produced by PPWIZARD ' version <?Version> from: ' ' <?InputComponent> ' ' The PPWIZARD header file used was "WISEINST.WIH" version ' <$WISEINST_VERSION>, this provides the script to VB code ' conversion logic. ' ' Apart from possiblity doing some debugging do not modify this ' file as your changes will get lost when the file is ' regenerated. ' ' PPWIZARD is a FREE product (private or commercial), ' available from: ' ' <?PpwizardHomePage> ' '---------------------------------------------------------------- <?NewLine> Option Explicit Public WiseObj 'global variables Dim argCount:argCount = Wscript.Arguments.Count ;--- Define some global variables -------------------------------- Dim TableEnvironment Dim Row dim PvComponent dim Key ;--- Connect to Wise for Windows Installer object ---------------- <?NewLine> Wscript.Echo "Creating Wise Document" Set WiseObj = Nothing Set WiseObj = Wscript.CreateObject("WfWi.Document") ;--- Make MSI ---------------------------------------------------- WiseObj.NewEx {$TYPE="1"}, {$WANTPRJFILE="TRUE"} 'End - $PackageStart <?NewLine> <?NewLine> #OneLineEnd ;--- End of Install script ------------------------------------------------ #OneLine '<?NewLine>' #define PackageEnd <?NewLine> <?NewLine> 'START - $PackageEnd Wscript.Echo "Generating: <$WISEWSI>" WiseObj.Compile "<$WISEWSI>" Wscript.Quit 0 'END - $PackageEnd #OneLineEnd ;--- Wise Hide compile dialog box ------------------------------------------- #define HideCompileDialogBox \ WiseObj.SetSilent ;--- Set properties --------------------------------------------------------- #OneLine '<?NewLine>' #define SetProperty <?NewLine>Wscript.Echo "SetProperty: {$Name} to {$Value}" WiseObj.SetProperty "{$Name}", "{$Value}" #OneLineEnd ;--- Add file --------------------------------------------------------------- #define AddFile \ <?NewLine>Wscript.Echo "AddFile: {$SOURCE}" %\ Key = WiseObj.AddFileEx( \ "{$SOURCE}", \ "{$DESTINATION}", \ {$Attributes="0"}, \ "{$Add2="<$Complete>"}", ;;Feature/Component name \ {$Add2Type="<$FEATURE>"}, \ PvComponent \ ) %\ <$DieIfKeyInvalid Rc="Key"> ;--- Add files (wildcard)---------------------------------------------------- #define AddFiles \ <?NewLine>Wscript.Echo "AddFiles: {$SrcDir}" %\ Key = WiseObj.AddWildcard( \ "{$FEATURE="<$Complete>"}", \ "{$CONDITION=^^}", \ "{$Includes=^*.*^}", ;;Delimiter = ";" \ "{$Excludes=^^}", ;;Delimiter = ";" \ "{$SrcDir}", \ "{$DestDir}", \ {$How="<$SUBDIRECTORIES>"}, \ {$CompAttr="<$CANT_RUN_FROM_SOURCE>"} \ ) %\ <$DieIfKeyInvalid Rc="Key"> ;--- Add Registery Value ---------------------------------------------------- #define AddRegValue \ <?NewLine>Wscript.Echo "AddRegValue: {$KeyPath}\{$ValueName}" %\ Key = WiseObj.AddRegistryValueEx( \ {$HKEY}, \ "{$KeyPath}", \ "{$ValueName}", \ "{$Value}", \ {$Type="<$string>"}, \ {$HOW="<$CREATED_IF_MISSING>"}, \ "{$Add2="<$Complete>"}", ;;Feature/Component name \ {$Add2Type="<$FEATURE>"}, \ PvComponent \ ) %\ <$DieIfKeyInvalid Rc="Key"> ;--- Add Shortcut ----------------------------------------------------------- #define AddShortCut \ <?NewLine>Wscript.Echo "AddShortCut: {$Title}" %\ Key = WiseObj.AddShortCutEx( \ {$ScType=^<$FOR_CMDLINE>^}, \ "{$ScTarget=^^}", ;;Not required if ADVERT \ "{$AdvAdd2="<$Complete>"}", ;;Feature name \ "{$Title}", ;;Shortcut's Name \ "{$ScDir=^<$STARTBAR_PGM_DIR>^}", ;;Create where? \ "{$ScArgs=^^}", ;;Shortcut's arguments \ "{$ScDesc=^^}", ;;Shortcut's description \ "{$ScWorkDir=^^}", ;;Shortcut's work dir \ {$ScHotKey=^0^}, ;;Shortcut's hot key \ {$ScWinSize=^<$NORMAL>^}, ;;Shortcut's Window size \ {$ScIconNumb=^0^}, ;;Icon # in EXE \ "{$Add2="<$Complete>"}", ;;Feature/Component name \ {$Add2Type="<$FEATURE>"}, ;;Feature or Component? \ PvComponent \ ) %\ <$DieIfKeyInvalid Rc="Key"> ;--- Update PATH (type variables) ------------------------------------------- #define ENV_CREATE_WHEN_INSTALLED #define ENV_DELETE_ON_INSTALL ! #define ENV_DELETE_ON_UNINSTALL - #define ENV_CREATE_IF_NONEXISTANT + #OneLine '<?NewLine>' #define Path ;--- Work out the modifier required for the env vars location ---- #if ['{$SYSTEM=^Y^}' = 'Y'] -\ #define+ ENV_SYS * -\ #elseif -\ #define+ ENV_SYS -\ #endif -\ ;--- How is variable updated ------------------------------------- #if ['{$ATEND=^Y^}' = 'Y'] -\ #define+ ENV_POS [~];{$PATH} -\ #elseif -\ #define+ ENV_POS {$PATH};[~] -\ #endif -\ ;--- Point to The Environment TABLE ------------------------------ Set TableEnvironment = WiseObj.WTables("Environment") ;--- Add Details to the table (create new row) ------------------- set Row = TableEnvironment.NewWRow() Row("Environment") = "LINE_<?OutputLine>" Row("Name") = "<$ENV_SYS>={$HOW=^<$ENV_DELETE_ON_UNINSTALL>^}{$NAME=^PATH^}" Row("Value") = "<$ENV_POS>" Row("Component_") = "{$Component=^Registry^}" #OneLineEnd ;--- ErrorChecking ---------------------------------------------------------- #OneLine '<?NewLine>' #define DieIfKeyInvalid ;--- Fail on zero value ------------------------------------------ if {$Rc} = "" then ;--- Display reason for failure ------------------------------ Wscript.Echo "" Wscript.Echo "Error Detected" Wscript.Echo "~~~~~~~~~~~~~~" Wscript.Echo WiseObj.GetLastError() ;--- Exit with error RC -------------------------------------- Wscript.Quit 219 end if #OneLineEnd
![]() | ![]() | ![]() | ![]() | ![]() |