![]() | ![]() | ![]() | ![]() | ![]() |
Wise Installer OLE Automation |
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).
You can download "WISEINST" from the PPWIZARD (http://www.labyrinth.net.au/~dbareis/ppwizard.htm) download page.
The defined macros currently support (basically I believe anything you can do manually you should be able to do via this mechanism):
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.
I have created a de-compiler (disassembler) for 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 decompiler can also be used to work out the differences between two versions of the same package. I have also written a MSI dump program which can tell you a lot about the installer package.
Now the organisation I work for will have tens or hundreds of packages with a lot of common code and settings. For this reason I created the "BSD.WIH" header file (as a front end to the more generic "WISEINST.WIH"
WI_SAMP.WI |
This is a "hello world" sample which is about as basic as it gets, all it does is create an MSI which contains itself. You should have no trouble to get this building on your environment and that is its main purpose.
;---------------------------------------------------------------------------- ; ; MODULE NAME: WI_SAMP.WI ; ; $Author: USER "Dennis" $ ; $Revision: 1.8 $ ; $Date: 28 Nov 2001 16:59:10 $ ; $Logfile: C:/DBAREIS/Projects.PVCS/PpwAddOn/WiseInst/WI_SAMP.wi.pvcs $ ; ; DESCRIPTION: This is a "Hello World" type sample for the direct use ; of "WISEINST.WIH" (which is not the way I recommend)... ; ; For the purposes of this sample everything is self ; contained, in real life I would define some things ; externally (at least the output WSI/MSI names) on ; the ppwizard command line etc. ; ; Also note that nothing has been done in this sample for ; upgrade codes etc. ; ; To make the VBS you could run a ppwizard command similar ; to (on NT/2000/XP): ; ; PPWIZARD WI_SAMP.WI /output:out\WI_SAMP.VBS ; ; Windows 95/98/ME users will probably need to type either ; (NT/XP/2000 users can also use this syntax): ; ; regina.exe PPWIZARD.rex WI_SAMP.WI /output:out\WI_SAMP.VBS ; ; or: ; ; ppwpath\regina.exe ppwpath\PPWIZARD.rex WI_SAMP.WI /output:out\WI_SAMP.VBS ; ; To create the WSI/MSI and the HTML (package doco) you ; should execute the VBScript, for example: ; ; CSCRIPT out\WI_SAMP.VBS ; ; REQUIRED ; ~~~~~~~~ ; Of course the VBS build step requires PPWIZARD to have ; been installed and the MSI creation step requires ; Wise Installer PRO. ;---------------------------------------------------------------------------- ;--- WISE OLE AUTOMATION requires full filenames (work out current dir) ----- #evaluate CurrentDir 'DirGetCurrent()' ;--- Set up some WiseInst options ------------------------------------------- #define GENERATE <$CurrentDir>\out\wi_samp ;;Generate out\wi_samp.wsi & .msi #define ProductName WISEINST - Hello World Sample #define ProductVersion 03.04.0000.0000 ;--- Include WiseInst support ----------------------------------------------- #include "WISEINST.WIH" ;--- Define the start of the MSI package ------------------------------------ <$Package> ;--- Set some MSI properties ------------------------------------------------ <$SetProperty NAME="ProductVersion" VALUE="<$ProductVersion>"> <$SetProperty NAME="ProductName" VALUE="<$ProductName>"> <$SetProperty NAME="_WiseDialogSuffix" VALUE=^(ver <$ProductVersion>)^> ;--- Set some MSI summary information --------------------------------------- #define COMMENTS A fairly simple "WISEINST.WIH" example. <$TABLE "Summary"> <$Row "Author" Value="Dennis"> <$Row "Comments" Value="<$COMMENTS>"> <$Row "Title" Value="<$ProductName> <$ProductVersion>"> <$Row "Subject" Value="<$COMMENTS>"> <$/TABLE> ;--- Create directory (mapped to "[ProgramFilesFolder]\<$ProductName>") ----- <$DirectoryTree Name="INSTALLDIR" DIRECTORY="C:\Program Files\<$ProductName>"> ;--- Create a component ----------------------------------------------------- <$AddComponent NAME="INSTALLDIR" DestDir="INSTALLDIR"> ;--- Just add this script --------------------------------------------------- #( <$AddFileWild DestDir="<$INSTALLDIR>" SrcDir="<$CurrentDir>" Add2="INSTALLDIR" Add2Type="<$IS_COMPONENT>" includes="wi_samp.wi" KeyFile="*" > #) ;--- Lets be stupid and add ourselves as a binary resourse ------------------ <$TABLE "Binary"> <$Row Name="wi_samp.wi" Data="@Bin(<$CurrentDir>\wi_samp.wi)"> <$/TABLE> ;--- Want the file commented in the HTML report ----------------------------- <$CommentFile File="wi_samp.wi" Comment='Very simple "Hello World" type source file'> ;--- Define the end of the MSI package -------------------------------------- <$/Package>
BSDUTIL.WI |
This is an extremely simple script which produces an MSI that:
Most of the above is performed by my "organisations intermediate header file" which we have set up to ensure all packages we create follow set standards.
;---------------------------------------------------------------------------- ; ; MODULE NAME: BSDUTIL.WI ; ; $Author: USER "Dennis" $ ; $Revision: 1.0 $ ; $Date: 10 May 2001 17:33:28 $ ; $Logfile: C:/DBAREIS/Projects.PVCS/PpwAddOn/WiseInst/bsdutil.wi.pvcs $ ; ; DESCRIPTION: This is my attempt at setting up "BSD_UTIL" correctly. ; ; Wise Installer 3+ & PPWIZARD is required to build the ; WSI/MSI packages. The WSI dump utility is used to ; decompile packages. ; ; All known ANX standards are applied "behind the scenes", ; for example support contact information and the fact ; that MSI packages install without prompting. Note that ; as show a lot of information is defaulted and the version ; number has been autogenerated. ; ; Shortcuts/registry/feature/components etc also supported. ; Basically if it can be done manually I can do it in a ; script. ; ;---------------------------------------------------------------------------- ;--- Define Comment for BSDUTIL --------------------------------------------- #define ProductComments \ This product is a collection of a number of tools required \ by other products. \ It also contains BSD standard DLLs such as the LU 6.2 \ communications API. ;--- Start Package ---------------------------------------------------------- #define DEBUG_OUTPUT ;;Option: Macros display text (no trap handler - VB too stupid) #define ProductName BSD_UTIL #define BSD_NO_VER_FILE_EXISTS #include "BSD.WIH" ;--- Define all directories used -------------------------------------------- <$Directory Name="PgmFilesBSD" SubDir="BSD_UTIL"> ;--- Want directory to be at end of SYSTEM "PATH" --------------------------- <$Path PATH="<$PgmFilesBSD>"> ;--- Add files to "COMPLETE" ------------------------------------------------ <$AddFileWild \ SrcDir="P:\DEVELOP\Exported\BSD_UTIL" \ DestDir="<$PgmFilesBSD>" \ ; includes="cssapi.dll" ;;default is "*.*" \ >
LIFE.WI |
The example shown above was quite a simple one, this example is a much more complex package.
The "BSD.WIH" header will by default look for a ".VER" file to match the ".WI" package being created, the example above told the header that this was not being supplied.
The ".VER" file contains header information (relevant to all "LIFE" releases) as well as every release distributed with at least a version number and a change history. There are a number of reasons for "splitting" the information, one of the most important is to prevent the actual package script from being modified just because you are creating a new release, we would like it to change only if the installation process does. It also allows someone without any real knowledge of the process to be able to safely update the version information.
The "BSD.WIH" header file reads the version file first extracting any heading information as well as the first (current) change record to pick up the version number that should be used for the current MSI build. It also picks up the change information for this version and adds it to the Generated MSI allowing batch files to scan MSI files for change information independent of any associated readme files etc (which may get lost etc).
The version file for the "LIFE" package looks like:
;---------------------------------------------------------------------------- ; ; MODULE NAME: LIFE.VER ; ; $Author: USER "Dennis" $ ; $Revision: 1.9 $ ; $Date: 17 Oct 2001 17:13:00 $ ; $Logfile: C:/DBAREIS/Projects.PVCS/PpwAddOn/WiseInst/life.ver.pvcs $ ; ; DESCRIPTION: Holds: ; ; (1) Product description & version history ; ; (2) Version history (current version at top!) ; ;---------------------------------------------------------------------------- ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; ProductName = ANX Quote Life ; DESCRIPTION = This holds the ANX Quote Life ; = quoting program. ; INSTALLED = SSPBCH_WSN ; HTML_XSTD = ; HTML_NOTE = ; VARIANT = ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ;############################################################################ MAJ_MIN : 1.05 VERSION : 01.289 CHANGES : Contains the 1.0.5 version of the application. : Update to the occupation list. : Replace "Hiv" with "HIV" on the medical requirements screen. : Increase in underwriting limits, the new limits are: : Blood testing limits - : $500,001 for ages <50; : $350,001 for ages 50+. : Medical Examination limits - : $1,000,001 for ages < 30; : $1,000,001 for ages <35; : $1,000,001 for ages <40; : $1,000,001 for ages <45; : $500,001 for ages <50; : $400,001 for ages <55; : $100,001 for ages 55+ : Medical by lifescreen and Chest X-Rays are : no longer necessary. ;############################################################################ MAJ_MIN : 1.03 VERSION : 01.141 CHANGES : Contains the 1.0.3 version of the application.
The actual package script for "LIFE" looks like:
;---------------------------------------------------------------------------- ; ; MODULE NAME: LIFE.WI ; ; $Author: USER "Dennis" $ ; $Revision: 1.5 $ ; $Date: 19 Nov 2001 17:06:22 $ ; $Logfile: C:/DBAREIS/Projects.PVCS/PpwAddOn/WiseInst/life.wi.pvcs $ ; ; DESCRIPTION: Creates MSI for ANX Quote Life. ; ;---------------------------------------------------------------------------- ;--- Where are all the source files located? -------------------------------- #define SOURCE_QUOTE_LIFE_PGM <?=getenv("EXPDIR_ANX_QUOTE_LIFE_PGM", "Y")> #define SOURCE_QUOTE_LIFE_DATA <?=getenv("EXPDIR_ANX_QUOTE_LIFE_DATA", "Y")> #define ANX_QUOTE_LIFE_ICON .\ANXQLIFE.ICO ;--- Some constants --------------------------------------------------------- #define QL_SHORTDIR_TEXT <$ANX_AIS_STD_PGM_DIRNAME> #define QL_IDRIVE_DATA_DIR_TEXT I:\Program Files\ANX\<$QL_SHORTDIR_TEXT> ;--- Load "BSD" support ----------------------------------------------------- #define BSD_COMPLETE_FEATURE_DIR DIR_LIFE_PGM #define BSD_ALLUSERS 0 #include "BSD.WIH" ;--- Directory - PROGRAM in "\PROGRAM FILES\ANX\ANX Quote Life..." ---------- <$Directory Name="DIR_LIFE_PGM" Parent="DIR_ProgramFilesBSD" SubDir="<$QL_SHORTDIR_TEXT>"> ;--- Directory - DATA ------------------------------------------------------- <$Directory Name="DIR_LIFE_DATA" Parent="DIR_LIFE_PGM" SubDir="<$BsdIDriveSetupShortDirText>"> ;--- Take care of the data -------------------------------------------------- #( ;--- Create Component ---------------------------------------------------- <$AddComponent NAME="DIR_LIFE_DATA" DestDir="DIR_LIFE_DATA" ;;;; Attributes="<$CATTR_NOT_REMOVE_AT_UNINSTALL>+<$CATTR_NEVER_OVERWRITE>" > #) #( <$AddFileWild DestDir="<$DIR_LIFE_DATA>" SrcDir="<$SOURCE_QUOTE_LIFE_DATA>" Add2="DIR_LIFE_DATA" Add2Type="<$IS_COMPONENT>" KeyFile="*" > #) ;--- EXE Needs to go into it's own component -------------------------------- <$AddComponent NAME="QLIFE.EXE" DestDir="DIR_LIFE_PGM"> #( <$AddFileWild DestDir="<$DIR_LIFE_PGM>" SrcDir="<$SOURCE_QUOTE_LIFE_PGM>" Add2="QLIFE.EXE" Add2Type="<$IS_COMPONENT>" KeyFile="*" includes="ANXQuoteLife.exe" EXLIST="QLIFE_PGM" > #) ;--- These items need to be in seperate components (MS/AIS rules) ----------- #( <$AddFileWild DestDir="<$DIR_LIFE_PGM>" SrcDir="<$SOURCE_QUOTE_LIFE_PGM>" Add2="<$BSD_COMPLETE_FEATURE_NAME>" Add2Type="<$IS_FEATURE>" includes="*.dll" EXLIST="QLIFE_PGM" > #) #( <$AddFileWild DestDir="<$DIR_LIFE_PGM>" SrcDir="<$SOURCE_QUOTE_LIFE_PGM>" Add2="<$BSD_COMPLETE_FEATURE_NAME>" Add2Type="<$IS_FEATURE>" includes="*.ocx" EXLIST="QLIFE_PGM" > #) ;--- All other Program files can go into one component ---------------------- <$AddComponent NAME="DIR_LIFE_PGM" DestDir="DIR_LIFE_PGM"> #( <$AddFileWild DestDir="<$DIR_LIFE_PGM>" SrcDir="<$SOURCE_QUOTE_LIFE_PGM>" Add2="DIR_LIFE_PGM" Add2Type="<$IS_COMPONENT>" KeyFile="*" EXLIST="QLIFE_PGM" > #) ;--- Create the shortcut ---------------------------------------------------- <$AddIcon KEY="ICON_QLIFE.EXE" FILE="<$ANX_QUOTE_LIFE_ICON>"> #( <$AddShortCut RowKey="SC_ANX_QUOTE_LIFE_PGM" Title="ANX Quote Life <$MajVersion>" ScDir="SCDIR_BUSAPPS" ScTarget="anzquotelife.exe" ScWorkDir="DIR_LIFE_PGM" ScDesc="Life Insurance Quoting Application (BSD v<$BsdVersion>)" Add2="QLIFE.EXE" Add2Type="<$IS_COMPONENT>" ScIconNumb=0 ScIconKey="ICON_QLIFE.EXE" > #) ;--- Fix 2 Wise Installer BUGs ---------------------------------------------- <$HereWeAre "Working around 2 Wise Installer bugs (Icon Indexes 'adjusted' + Working directory bug)"> <$TABLE "Shortcut"> <$Row "SC_ANX_QUOTE_LIFE_PGM" WkDir="DIR_LIFE_PGM" IconIndex="0"> <$/TABLE> ;--- Add INI ---------------------------------------------------------------- <$IniFile FILE="ANXQUOTE.INI" SECTION="FileDetails" DIR="DIR_LIFE_PGM" ADD2="DIR_LIFE_PGM"> <$IniAdd Key="AgentDetailsFilePath" Value="<$QL_IDRIVE_DATA_DIR_TEXT>"> <$IniAdd Key="CustomerFilePath" Value="<$QL_IDRIVE_DATA_DIR_TEXT>"> <$IniAdd Key="QuoteFilePath" Value="<$QL_IDRIVE_DATA_DIR_TEXT>"> <$IniAdd Key="TempFilePath" Value="<$QL_IDRIVE_DATA_DIR_TEXT>"> <$IniAdd Key="CustomerQuoteKillDuration" Value="60"> <$IniAdd Key="CustomerQuoteKillDate" Value="30/12/2001"> <$IniAdd Key="Bank" Value="Y"> <$/IniFile> ;--- Add registry entries --------------------------------------------------- #define+ HKEY_DEFAULT <$CLASSES_ROOT> #define+ DEFAULT_ADD2 REG_CLASSES_ROOT #define+ DEFAULT_ADD2TYPE <$IS_COMPONENT> <$AddComponent NAME="<$DEFAULT_ADD2>" DestDir="DIR_LIFE_PGM"> #( <$AddRegValue KeyPath="Y" RowKey="KeyPathRegEntry" Key="CalculationXDll.clsCalculation" Value="CalculationXDll.clsCalculation" > #) #( <$AddRegValue Key="MedFinReqXDll.clsMedicalFinancialReq\Clsid" Value="{03AC0317-0756-11D3-9CDA-00C04F886CB8}" > #) #( <$AddRegValue Key="QuoteXDll.clsQuotes" Value="QuoteXDll.clsQuotes" > #) #( <$AddRegValue Key="CalculationXDll.clsCalculation\Clsid" Value="{C47325AD-0CF3-11D3-9CA9-00C04F886CB8}" > #) #( <$AddRegValue Key="DiscountBandXDll.clsDiscountBands" Value="DiscountBandXDll.clsDiscountBands" > #) #( <$AddRegValue Key="MedFinReqXDll.clsMedicalFinancialReqs\Clsid" Value="{03AC0319-0756-11D3-9CDA-00C04F886CB8}" > #) #( <$AddRegValue Key="ConstantXDll.clsConstant" Value="ConstantXDll.clsConstant" > #) #( <$AddRegValue Key="CalculationXDll.clsCalculationResults\Clsid" Value="{C47325AB-0CF3-11D3-9CA9-00C04F886CB8}" > #) #( <$AddRegValue Key="DiscountBandXDll.clsDiscountBand\Clsid" Value="{EBB4C949-0755-11D3-9CDA-00C04F886CB8}" > #) #( <$AddRegValue Key="CalculationXDll.clsCalculationResults" Value="CalculationXDll.clsCalculationResults" > #) #( <$AddRegValue Key="CustomerXDll.clsCustomer\Clsid" Value="{C06B9199-0CCF-11D3-9CA9-00C04F886CB8}" > #) #( <$AddRegValue Key="ProductXDll.clsProduct\Clsid" Value="{A76A95A1-0CF3-11D3-9CA9-00C04F886CB8}" > #) #( <$AddRegValue Key="CalculationXDll.clsCalculationResult" Value="CalculationXDll.clsCalculationResult" > #) #( <$AddRegValue Key="DiscountBandXDll.clsDiscountBands\Clsid" Value="{EBB4C947-0755-11D3-9CDA-00C04F886CB8}" > #) #( <$AddRegValue Key="MedFinReqXDll.clsMedicalFinancialReqs" Value="MedFinReqXDll.clsMedicalFinancialReqs" > #) #( <$AddRegValue Key="TrueDBGrid50.TDBDropDown" Value="True DBDropDown Control" > #) #( <$AddRegValue Key="DiscountBandXDll.clsDiscountBand" Value="DiscountBandXDll.clsDiscountBand" > #) #( <$AddRegValue Key="ProductXDll.clsProducts" Value="ProductXDll.clsProducts" > #) #( <$AddRegValue Key="TrueDBGrid50.TDBGrid" Value="True DBGrid Control" > #) #( <$AddRegValue Key="CustomerXDll.clsCustomers\Clsid" Value="{C06B9197-0CCF-11D3-9CA9-00C04F886CB8}" > #) #( <$AddRegValue Key="TrueDBGrid50.Style" Value="APEX True DBGrid Style Object" > #) #( <$AddRegValue Key="CalculationXDll.clsCalculationResult\Clsid" Value="{C47325A9-0CF3-11D3-9CA9-00C04F886CB8}" > #) #( <$AddRegValue Key="PrintQuoteXDll.clsPrint\Clsid" Value="{BDFAFAE8-0E58-11D3-9CAB-00C04F886CB8}" > #) #( <$AddRegValue Key="ProductXDll.clsProduct" Value="ProductXDll.clsProduct" > #) #( <$AddRegValue Key="ProductXDll.clsProducts\Clsid" Value="{A76A95A3-0CF3-11D3-9CA9-00C04F886CB8}" > #) #( <$AddRegValue Key="CalculationXDll.clsCalculations" Value="CalculationXDll.clsCalculations" > #) #( <$AddRegValue Key="TrueDBGrid50.ValueItem\CLSID" Value="{00028C65-0000-0000-0000-000000000046}" > #) #( <$AddRegValue Key="PrintQuoteXDll.clsPrint" Value="PrintQuoteXDll.clsPrint" > #) #( <$AddRegValue Key="QuoteXDll.clsQuotes\Clsid" Value="{8B14AE1E-0CCF-11D3-9CA9-00C04F886CB8}" > #) #( <$AddRegValue Key="CalculationXDll.clsCalculations\Clsid" Value="{C47325AF-0CF3-11D3-9CA9-00C04F886CB8}" > #) #( <$AddRegValue Key="CustomerXDll.clsCustomers" Value="CustomerXDll.clsCustomers" > #) #( <$AddRegValue Key="TrueDBGrid50.Style\CLSID" Value="{00028C6C-0000-0000-0000-000000000046}" > #) #( <$AddRegValue Key="TrueDBGrid50.TDBDropDown\CLSID" Value="{00028C70-0000-0000-0000-000000000046}" > #) #( <$AddRegValue Key="MedFinReqXDll.clsMedicalFinancialReq" Value="MedFinReqXDll.clsMedicalFinancialReq" > #) #( <$AddRegValue Key="QuoteXDll.clsQuote" Value="QuoteXDll.clsQuote" > #) #( <$AddRegValue Key="QuoteXDll.clsQuote\Clsid" Value="{8B14AE1C-0CCF-11D3-9CA9-00C04F886CB8}" > #) #( <$AddRegValue Key="CustomerXDll.clsCustomer" Value="CustomerXDll.clsCustomer" > #) #( <$AddRegValue Key="ConstantXDll.clsConstant\Clsid" Value="{3DCFDC55-0CF3-11D3-9CA9-00C04F886CB8}" > #) #( <$AddRegValue Key="TrueDBGrid50.TDBGrid\CLSID" Value="{00028C49-0000-0000-0000-000000000046}" > #) #( <$AddRegValue Key="TrueDBGrid50.ValueItem" Value="APEX True DBGrid Value Item Object" > #) ;--- Set up I: drive (VBS, INF(s) and registry) ----------------------------- #define IDRV_DIRKEY_VBS DIR_LIFE_DATA ;;Key into directory table (with only one dir INF/VBS in same dir as data) #define IDRV_DIRINFO_INF.1 ~<$ProductName>.INF ;;Name of INF file (typically shortname, but actually relative to VBS dir) #define IDRV_DIRINFO_DIRKEY.1 DIR_LIFE_DATA ;;Key to directory table #define IDRV_DIRINFO_SRC.1 <$SOURCE_QUOTE_LIFE_DATA>\*.*(CPYFLG_NeverOverwrite) #define IDRV_DIRINFO_ON_I.1 <$QL_IDRIVE_DATA_DIR_TEXT> ;;Full dir name on I drive #include "IDRIVESU.WIH"
![]() | ![]() | ![]() | ![]() | ![]() |