PPWIZARD is a free preprocessor for HTML, REXX, Visual Basic or any text files.
[Bottom][Contents][Search][Prev]: The Header File - BSD.WIH[Next]: Creating HTML pages from Windows URL Shortcuts or OS/2 URL Objects

The Header File - WISEINST.WIH

This is the header file that is provides generic support for the creation of Wise Installer ".WSI" packages as well as Microsoft's Windows Installer ".MSI" packages.

This is an extremely powerful tool which eliminates the need for using the Wise Installer wizard when creating installation packages, for more information and examples on how some packages might look have a look at "Wise Installer OLE Automation".

This facility allows you to automate package generation as well as allowing people without full Wise/packaging training to support and create packages. Package creation is consistant as nothing is ever forgotten.

The header file is not documented so for that reason only a person writing a script would need to refer to the file. If interest in this facility is shown I may add documentation.

The header follows:

    ;----------------------------------------------------------------------------
    ;
    ;    MODULE NAME:   WISEINST.WIH
    ;
    ;        $Author:   USER "Dennis"  $
    ;      $Revision:   1.8  $
    ;          $Date:   30 May 2001 17:29:44  $
    ;       $Logfile:   C:/DBAREIS/Projects.PVCS/PpwAddOn/WiseInst/wiseinst.wih.pvcs  $
    ;
    ;    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 WISETEST.wi /output:out\*.vbs /other /dependson:out\*.dep /define:GENERATE=c:\tmp\WISETEST /errorfile:out\ppwizard.err
    ;
    ;                      REM *** Execute VB code to create MSI package ********
    ;                      if not errorlevel 1 cscript out\WISETEST.vbs
    ;
    ;                   PPWIZARD is the most powerful preprocessor available
    ;                   AND IT'S FREE (personal or commercial use),
    ;                   it's homepage is at:
    ;
    ;                       http://www.labyrinth.net.au/~dbareis/ppwizard.htm
    ;
    ;                   Note that if you wish to keep Windows Installer GUIDS
    ;                   fixed then you can use the ppwizard add-on "NEEDGUID"
    ;                   to "remember" them for you.
    ;
    ;           HELP:   The Wise Wizard, particularly the TABLE view under
    ;                   the "SETUP EDITOR" can be very handy for checking that
    ;                   you have correctly done something or simply to work
    ;                   out what to do.
    ;
    ;                   What you can also do if use my "DUMPWSI" tool after
    ;                   manually making a change to work out what has changed
    ;                   and either user the dumped output as is or simply for
    ;                   diagnostic purposes.
    ;
    ;        WARNING:   It is early days for this script (and my knowledge)
    ;                   so things will probably change for future versions
    ;                   of this header. Always back up any existing scripts
    ;                   as well as older versions of ppwizard and this header
    ;                   before upgrading.
    ;----------------------------------------------------------------------------
    
    
    ;--- Define Version number of this install support --------------------------
    #ifdef   WISEINST_VERSION
             #eof 1;                ;;Don't process again if included twice!
    #endif
    #define  WISEINST_VERSION   01.150
    #require 01.086
    #option  PUSH DefineMacroReplace=ON
    #define  WISEINST_HEADER    <?InputComponent>
    #option  POP
    
    ;--- Make sure user specified the name of the output file -------------------
    #ifndef GENERATE
            #error ^The define "GENERATE" must contain name of output WISE package^
    #endif
    #define  GENERATE_WSI   <$GENERATE>.wsi
    #define  GENERATE_MSI   <$GENERATE>.msi
    #define? GENERATE_RPT   <$GENERATE>.htm
    
    ;--- A prefix for Special "generator" type properties -----------------------
    #define? WISEINST_PROP_PREFIX     ____
    
    ;--- Default feature --------------------------------------------------------
    #define Complete           Complete            ;;Default Feature Name
    
    ;--- Add to Component or Feature --------------------------------------------
    #define IS_FEATURE             0
    #define IS_COMPONENT           1
    
    ;--- Make it easier to specify multiple items all added to same components etc ---
    #define? DEFAULT_FEATURE       <$Complete>
    #define? DEFAULT_ADD2          <$DEFAULT_FEATURE>
    #define? DEFAULT_ADD2TYPE      <$IS_FEATURE>
    
    ;--- How to add wildcard files from directory -------------------------------
    #define NO_SUBDIRECTORIES          0
    #define SUBDIRECTORIES             1
    #define UPDATE_NEW_COMPONENTS      2
    
    
    ;--- Define some directory location -----------------------------------------
    #define DESKTOP_DIR        Windows\Profiles\Desktop
    #define STARTBAR_DIR       Windows\Profiles\Start Menu
    #define STARTBAR_PGM_DIR   <$STARTBAR_DIR>\Programs
    
    ;--- Set default for trap detection handler ---------------------------------
    #ifdef DEBUG_OUTPUT
           ;--- No runtime trap handler if debugging (VB is too stupid!) --------
           #define? RUNTIME_TRAPS_DETECTED N
           #define? VERBOSE_OUTPUT         Y
    #elseif
           ;--- In "Production" mode probably want trap detection ---------------
           #define? RUNTIME_TRAPS_DETECTED Y
           #define? VERBOSE_OUTPUT         N
    #endif
    
    ;--- Start/end of Install script --------------------------------------------
    #define Package   <$VBSCRIPT_AT_START>
    #define /Package                                          \
            <$SRCLINE 'Processing "/Package" macro'>         -\
            <$GenerateAnyHtmlReports>                        -\
            <$VBSCRIPT_AT_END>
    
    ;--- Define 'X' codes that can be used within VB "literal" strings ----------
    #DefineRexx ''
       do  Ascii = 0 to 255
           ;--- This code is only to be used within a VB STRING (double quoted) ---
           VbCode = '" & chr(' || Ascii || ') & "'
    
           ;--- Set up the code -------------------------------------------------
           call SetXCode d2x(Ascii), VbCode
       end;
       call SetXCode "CRLF", '" & vbCRLF & "'
       call SetXCode "CR",   '" & vbCR & "'
       call SetXCode "LF",   '" & vbLF & "'
       call SetXCode "DQ",   '" & chr(' || c2d('"') || ') & "'
    #DefineRexx
    #DefineRexx REXX_$$VBSTR
                ;--- Handle user entering double quotes in a value --------------
                TheValue = '"' || ReplaceString(TheValue, '"', '<?xDQ>') || '"';
    #DefineRexx
    
    ;--- Allows imbedding of VB statements/variables in "literals" --------------
    #RexxVar ^VbDq^ =x= ^"^     ;;Can't use double quotes directly
    #define  VBIMBED                                                       \
             <?xVbDq>      ;;End literal with double quote                 \
             &             ;;Concatenate user's VB statement/variable      \
             {$STAT}       ;;User's VB statement/variable                  \
             &             ;;Concatenate rest of literal                   \
             <?xVbDq>      ;;Start Literal
    
    ;--- Used to remember location in code (make up for stupid VB deficiency) ---
    #DefineRexx REXX_$$SHORT
                ;--- Transformation to return short name given one with path ----
                TheValue = _filespec('name', TheValue);
    #DefineRexx
    #( '<?NewLine>'
       #define HereWeAre
               ;--- Set a global variable to hold information -------------------
               #evaluate ^^ ^<$Rexx2GetSrcLine>^
               <?NewLine>                                         -\
               <?NewLine>                                         -\
               '=================================================================
               '=== Line <?InputComponentLine> of <?InputComponent>
               '=== <??SrcLine>
               '=================================================================
               HereWeAre "<?InputComponent $$SHORT>(<?InputComponentLine>)", "{$#1=^^}"
    #)
    #DefineRexx 'Rexx2GetSrcLine'
               if  AltText4SrcLine <> '' then
                   SrcLine = AltText4SrcLine;
               else
                   SrcLine = space(GetFileLineBeingProcessed())
    #DefineRexx
    #define SRCLINE                                    \
            #RexxVar AltText4SrcLine = '{$#1 $$SQx2}'
    <$SRCLINE ''>
    
    
    ;--- Useful Macros (use if you write imbedded VbSCript!) --------------------
    #define WiseObj         WiseObj                ;;In case interface completely changes...
    #define DieIfKeyInvalid KeyMustBeOk({$KEYVAR="Key"})
    #define DieIfNotOk      BoolMustBeTrue(Ok)
    
    
    ;--- Work out the name of this header file ----------------------------------
    #DefineRexx ''
       WiseInstHeaderFile = '<?InputComponent>';
    #DefineRexx
    
    
    ;--- Wise Hide compile dialog box -------------------------------------------
    #define HideCompileDialogBox        \
            <$HereWeAre "{$MacName}">  %\
            <$WiseObj>.SetSilent
    
    ;--- Set properties ---------------------------------------------------------
    #(   '<?NewLine>'
       #define SetProperty
               <$HereWeAre "{$?MacName} - {$Name}">
               #RexxVar RxPropertyValue = ^{$Value}^
               Ok = <$WiseObj>.SetProperty("{$Name}", <??RxPropertyValue $$VBSTR>)
               <$DieIfNotOk>{$!}
    #)
    ;**      CommentBlock  /* (Thursday 24/05/2001, 09:20:02, by Dennis Bareis) */
    ;**+--------------------------------------------------------------------------
    ;**|#(   '<?NewLine>'
    ;**|   #define SetProperty
    ;**|           <$HereWeAre "{$?MacName} - {$Name}">
    ;**|           Ok = <$WiseObj>.SetProperty("{$Name}", {$Value $$VBSTR})
    ;**|           <$DieIfNotOk>{$!}
    ;**|#)
    ;**+--------------------------------------------------------------------------
    ;**                    /* (Thursday 24/05/2001, 09:20:02, by Dennis Bareis) */
    
    ;--- Set Load Template ------------------------------------------------------
    #(   '<?NewLine>'
       #define LoadTemplate
               <$HereWeAre "{$?MacName} - {$File}">
               Ok = <$WiseObj>.Open("{$File}")
               <$DieIfNotOk>{$!}
    #)
    
    ;--- Add Feature ------------------------------------------------------------
    #define  FDISP_INVISIBLE                                 0
    #define  FDISP_VISIBLE_AND_EXPANDED                      1
    #define  FDISP_VISIBLE_AND_COLLAPSED                     2
    #define? FDISP_DEFAULT                                   <$FDISP_VISIBLE_AND_COLLAPSED>
    #define  FILVL_NEVER_INSTALL                             0
    #define  FILVL_ALWAYS_INSTALL                            1
    #define  FILVL_NORMAL                                    3
    #define? FILVL_DEFAULT                                   <$FILVL_NORMAL>
    #define  FATTR_ADVERTISING_NONE                          0
    #define  FATTR_FAVOR_SOURCE_INSTALL                      1
    #define  FATTR_FAVOR_PARENT_ATTRIBUTES                   2
    #define  FATTR_FAVOR_ADVERTISED_FEATURE                  4
    #define  FATTR_DISALLOW_ADVERTISING                      8
    #define  FATTR_DISALLOW_OPT_TO_SET_ABSENT               16
    #define  FATTR_DISALLOW_ADVERTISED_IF_OPSYS_WONT_ALLOW  32
    #define  FATTR_REQUIRED_FEATURE                         <$FATTR_DISALLOW_OPT_TO_SET_ABSENT>
    #define? FATTR_DEFAULT                                  <$FATTR_FAVOR_ADVERTISED_FEATURE>+<$FATTR_REQUIRED_FEATURE>
    #define AddFeature                                                \
            <$HereWeAre "{$?MacName} - '{$Name}' to '{$Parent=^^}'"> %\
            #evaluate+ ^BitsCombined^ ^<$FATTR_DEFAULT>^             -\
            Ok = <$WiseObj>.AddFeature(                               \
                  "{$Name}",                                          \
                  "{$Parent=^^}",                                     \
                  "{$Title}",                                         \
                  "{$Description=^LINE_<?InputComponentLine>^}",      \
                  {$Display=^<$FDISP_DEFAULT>^},                      \
                  {$Level=^<$FILVL_DEFAULT>^},                        \
                  "{$DestDir}",                                       \
                  {$Attributes="<$BitsCombined>"}                     \
            )                                                        %\
            <$DieIfNotOk>{$!}
    
    ;--- Add Component ----------------------------------------------------------
    #define  CATTR_CANT_RUN_FROM_SOURCE       0
    #define  CATTR_ONLY_RUN_FROM_SOURCE       1
    #define  CATTR_RUN_FROM_SOURCE_OR_LOCAL   2
    #define  CATTR_KEY_PATH_FOR_REGISTRY      4
    #define  CATTR_INC_SHARED_DLL_COUNT       8
    #define  CATTR_NOT_REMOVE_AT_UNINSTALL    16
    #define  CATTR_KEY_PATH_FOR_ODBC          32
    #define  CATTR_COMPONENT_IS_TRANSITIVE    64
    #define  CATTR_NEVER_OVERWRITE            128
    #define? CATTR_DEFAULT                    <$CATTR_CANT_RUN_FROM_SOURCE>
    #define AddComponent                                             \
            <$HereWeAre "{$?MacName} - '{$Name}' to '{$Feature="<$DEFAULT_FEATURE>"}'"> %\
            #evaluate+ ^BitsCombined^ ^<$CATTR_DEFAULT>^            -\
            Ok = <$WiseObj>.AddComponent(                            \
                  "{$Name}",                                         \
                  "{$DestDir}",                                      \
                  "{$CONDITION=^^}",                                 \
                  {$Attributes="<$BitsCombined>"}                    \
            )                                                       %\
            <$DieIfNotOk>                                           %\
            Ok = <$WiseObj>.AddComponentToFeature(                   \
                  "{$Name}",                                         \
                  "{$FEATURE}"                                       \
            )                                                       %\
            <$DieIfNotOk>{$!}
    
    
    ;--- Component GUID (to "fix" GUIDs have a look at "NEEDGUID.H") ------------
    #( '<?NewLine>'
       #define SetComponentGuid
               <$HereWeAre "{$?MacName} - {$COMPONENT}">
               Ok = <$WiseObj>.SetComponentGUID("{$COMPONENT}", {$GUID})
               <$DieIfNotOk>{$!}
    #)
    
    
    ;--- Handle Exclude lists ---------------------------------------------------
    #define ExcludeListClear           \
            #evaluate ^^ ^<$Rexx4ExcludeListClear {$?}>^
    #define ExcludeListAddWild         \
            #evaluate ^^ ^<$Rexx4ExcludeListAddWild {$?}>^
    #NextId
    #DefineRexx 'Rexx4ExcludeListClear'
       ;--- Work out where to store info ----------------------------------------
       <$Rexx4WorkOutStem EXLIST=^{$EXLIST}^ VAR="@@Stem">
    
       ;--- Now clear the "array" -----------------------------------------------
       call value @@Stem || '.0', 0;       ;;Zero entries in the array
    #DefineRexx
    #DefineRexx 'Rexx4WorkOutStem'
       ;--- Try and use username as is ------------------------------------------
       @@Base = '{$EXLIST}'
       if  symbol(@@Base) = 'BAD' then
           @@Base = c2x(translate(@@Base));
    
       ;--- Return the stem without dot we will use -----------------------------
       {$VAR} = 'EXLIST_' || @@Base;
    
       ;--- Make sure the variable exists ---------------------------------------
       if  symbol({$VAR} || '.0') <> 'VAR' then
       do
           ;--- Init to empty array ---------------------------------------------
           call value {$VAR} || '.0', 0;
       end;
    #DefineRexx
    #DefineRexx 'Rexx4ExcludeListAdd1'
       ;--- Work out where to store info ----------------------------------------
       <$Rexx4WorkOutStem EXLIST=^{$EXLIST}^ VAR="@@Stem">
    
       ;--- Make upper case for faster compares later ---------------------------
       @@FileU = translate({$FILEVAR});
    
       ;--- Now add into the array ----------------------------------------------
       @@Count = value(@@Stem || '.0') + 1;           ;;Get count + Increment it
       call value @@Stem || '.' || @@Count, @@FileU;  ;;Save file
       call value @@Stem || '.0',           @@Count;  ;;Save updated count
    #DefineRexx
    #DefineRexx 'Rexx4ExcludeListAddStem'
       ;--- Work out where to store info ----------------------------------------
       <$Rexx4WorkOutStem EXLIST=^{$EXLIST}^ VAR="@@Stem">
    
       ;--- Add to the exclude list ---------------------------------------------
       @@Count = value(@@Stem || '.0');                     ;;Get current count
       do  @@I = 1 to {$FILESTEM}.0
           ;--- Add each file to the exclude list -------------------------------
           @@Count = @@Count + 1;
           call value @@Stem || '.' || @@Count, translate({$FILESTEM}.@@I);
       end
       call value @@Stem || '.0', @@Count;                  ;;Save updated count
    #DefineRexx
    #DefineRexx 'Rexx4ExcludeListFileIn'
       ;--- Work out where info stored ------------------------------------------
       <$Rexx4WorkOutStem EXLIST=^{$EXLIST}^ VAR="@@Stem">
    
       ;--- Convert passed file to uppercase ------------------------------------
       @@Look4 = translate({$FILEVAR});
    
       ;--- Add to the exclude list ---------------------------------------------
       {$FOUNDVAR} = 'N';
       do  @@I = 1 to value(@@Stem || '.0')
           ;--- Check passed filename against exclude list entry ----------------
           if  @@Look4 = value(@@Stem || '.' || @@I) then
           do
               ;--- Found entry -------------------------------------------------
               {$FOUNDVAR} = 'Y';
               leave;                ;;Exit loop
           end;
       end
    #DefineRexx
    #DefineRexx 'Rexx4ExcludeListAddWild'
       ;--- Get list of files to be excluded ------------------------------------
       @@Files.0 = 0;
       Look4     = "{$FILES}";
       call _SysFileTree   Look4, "@@Files";
       if  @@Files.0 = 0 then
       do
           ;--- Did not find any files, is this OK? -----------------------------
           if  '{$NONEOK=^N^}' = 'N' then
               Error('No files matched "' || Look4 || '"!');
       end
    
       ;--- Add to the stem -----------------------------------------------------
       <$Rexx4ExcludeListAddStem EXLIST=^{$EXLIST}^ FILESTEM="@@Files">
    #DefineRexx
    
    
    ;--- Add file ---------------------------------------------------------------
    #define  SFATTR_READ_ONLY                1
    #define  SFATTR_HIDDEN                   2
    #define  SFATTR_SYSTEM                   4
    #define  SFATTR_VITAL                    512             ;;Installation fails if file can't be installed
    #define  SFATTR_CONTAINS_CHECKSUM        1024
    #define  SFATTR_UNCOMPRESSED_OUTSIDE     8192
    #define? SFATTR_DEFAULT                  <$SFATTR_VITAL>
    #define AddFile1                                                            \
            ;--- Create VbScript to add file -----------------------------     -\
            <$HereWeAre "{$?MacName} - {$SOURCE}">                             %\
            #DependsOn INPUT "{$SOURCE}"                                       -\
            KeyPath = <$WiseObj>.AddFileEx(                                     \
                      "{$SOURCE}",                                              \
                      "{$DESTINATION}",                                         \
                      {$Attributes="<$SFATTR_DEFAULT>"},                        \
                      "{$Add2="<$DEFAULT_ADD2>"}", ;;Feature/Component name     \
                      {$Add2Type="<$DEFAULT_ADD2TYPE>"},                        \
                      PvComponent                                               \
            )                                                                  %\
            <$DieIfKeyInvalid KEYVAR="KeyPath">{$!}                            -\
                                                                               -\
            ;--- Remember file for the HTML report -----------------------     -\
            #evaluate ^^ ^<$Rexx2AddFileToReport {$?ResetUsed}{$?}>^
    #NextId
    #RexxVar RptFileCnt = 0             ;;Currently storing no file information
    #DefineRexx 'Rexx2AddFileToReport'
            ;--- Get Passed Information -----------------------------------------
            @@Src    = '{$SOURCE}'
            @@DstDir = _filespec('location', '{$DESTINATION}');
            @@Added2 = '{$Add2="<$DEFAULT_ADD2>"}'
    
            ;--- Check that file exists -----------------------------------------
            @@SrcFull = stream(@@Src, 'c', 'query exists');
            if @@SrcFull = '' then
               error('Could not find the file "' || @@Src || '"');
    
            ;--- Get file info --------------------------------------------------
            @@Date = GetFileTimeStamp(@@SrcFull);
            @@Size = AddCommasToDecimalNumber(stream(@@SrcFull, 'c', 'query size'));
            @@SrcDir = _filespec('location', @@SrcFull);
            @@Short  = _filespec('name',     @@SrcFull);
    
            ;--- Clean up directories -------------------------------------------
            if right(@@DstDir, 1) = '\' then
               @@DstDir = left(@@DstDir, length(@@DstDir)-1);
            if right(@@SrcDir, 1) = '\' then
               @@SrcDir = left(@@SrcDir, length(@@SrcDir)-1);
    
            ;--- Combine (using good sort order) and save -----------------------
            @@All  = @@Short || '00'x || @@DstDir || '00'x || @@SrcDir || '00'x || @@Date || '00'x || @@Size;
            RptFileCnt         = RptFileCnt + 1;
            RptFile.RptFileCnt = @@All;
            RptFile.0          = RptFileCnt;
    #DefineRexx
    
    ;--- AddFileWild (Does an "AddFile()" once for each file --------------------
    #define AddFileWild                                                        \
           <$HereWeAre "{$?MacName} - {$SrcDir}\{$Includes=^*.*^}">           %\
           #evaluate ^^ ^<$AddFileWildRexx {$?ResetUsed}{$?}>^                -\
           <??Vb>
    #NextId
    #DefineRexx 'AddFileWildRexx'
           ;--- Get list of SOURCE FILES ----------------------------------------
           SrcFiles.0 = 0;
           Look4      = "{$SrcDir}\{$Includes=^*.*^}";
           call _SysFileTree   Look4, "SrcFiles";
           if  SrcFiles.0 = 0 then
           do
               ;--- Did not find any files, is this OK? -------------------------
               if  '{$NONEOK=^N^}' = 'N' then
                   error('No files matched "' || Look4 || '"!');
           end;
    
           ;--- If keyfile supplied, make sure it is valid to do so -------------
           KeyFileUsed = 'N'
           KeyFile     = translate('{$KEYFILE=^^}');
           if  KeyFile <> '' then
           do
               ;--- Must be adding to a component -------------------------------
               if  '{$Add2Type="<$DEFAULT_ADD2TYPE>"}' = '<$IS_FEATURE>' then
               do
                   error('If you want to set the keyfile to be "' || KeyFile || '"', 'then you must add the files to a component (not a feature)');
               end;
           end;
    
           ;--- Create output ---------------------------------------------------
           Vb         = ''
           do  Findex = 1 to SrcFiles.0
               ;--- Have exclude list? ------------------------------------------
               if  '{$EXLIST=^^}' <> '' then
               do
                   ;--- See if this file is in the exclude list -----------------
                   <$Rexx4ExcludeListFileIn EXLIST=^{$EXLIST}^ FILEVAR=^SrcFiles.Findex^ FOUNDVAR=^@@IsExcluded^>
                   if  @@IsExcluded = 'Y' then
                   do
                       ;--- This file is excluded so ignore ---------------------
                       iterate;
                   end
               end;
    
               ;--- Make sure that the Key into the file table is consistant case! ---
               SourceFile = ToLowerCase(SrcFiles.Findex);
    
               ;--- Create VB code to add the file ------------------------------
               ShortName = _filespec('name', SrcFiles.Findex);
               Vb = Vb || '<' || '$AddFile1 '
               Vb = Vb || '       SOURCE=^' || SourceFile || '^ '
               Vb = Vb || '  DESTINATION=^{$DestDir}\' || ShortName || '^ '
               Vb = Vb || '         ADD2=^{$Add2="<$DEFAULT_ADD2>"}^ '
               Vb = Vb || '     Add2Type=^{$Add2Type="<$DEFAULT_ADD2TYPE>"}^ '
               Vb = Vb || '   Attributes=^{$Attributes="<$SFATTR_DEFAULT>"}^ '
               Vb = Vb || '><?NewLine>'
    
               ;--- Did user specify a keyfile, if so is this it? ---------------
               if  KeyFile <> '' & KeyFileUsed = 'N' then
               do
                   ;--- User has specified a keyfile (used "*"?) ----------------
                   if  KeyFile = '*' then
                   do
                       ;--- Use 1st file found (User wants any) -----------------
                       KeyFile = translate(ShortName);
                   end;
    
                   ;--- Does this file match the keypath? -----------------------
                   if  KeyFile = translate(ShortName) then
                   do
                       ;--- This is the keyfile (KeyPath is global VB variable) -
                       Vb = Vb || 'Ok = <$WiseObj>.SetComponentKeyPath("{$Add2}", KeyPath)<?NewLine>'
                       Vb = Vb || '<$DieIfNotOk><?NewLine>'
                       KeyFileUsed = 'Y'
                   end;
               end;
           end;
    
           ;--- Ensure macro(s) gets expanded -----------------------------------
           Vb = Vb || d2c(10)
    
           ;--- Have exclude list we need to add these files to? ----------------
           if  '{$EXLIST}' <> '' then
           do
               ;--- Add this file to it -------------------------------------
               <$Rexx4ExcludeListAddStem EXLIST=^{$EXLIST}^ FILESTEM="SrcFiles">
           end
    
           ;--- Ensure that if user specified a keyfile that it was used --------
           if  KeyFile <> '' then
           do
               ;--- User has specified a keyfile --------------------------------
               if  KeyFileUsed = 'N' then
               do
                   error('The KeyFile "{$KEYFILE}" was not found.', 'Searched "' || Look4 || '"');
               end;
           end;
           {$!}
    #DefineRexx
    
    ;--- This Wise call not only buggy, but my replacement macro is probably better ---
    ;**      CommentBlock  /* (Friday 30/03/2001, 15:22:27, by Dennis Bareis) */
    ;**+--------------------------------------------------------------------------
    ;**|;--- Add files (wildcard - Front end to AddWildCard() call) -----------------
    ;**|#define AddFiles                                                 \
    ;**|        <$HereWeAre "{$?MacName} - {$SrcDir}">                  %\
    ;**|        Key = <$WiseObj>.AddWildcard(                            \
    ;**|              "{$FEATURE="<$DEFAULT_FEATURE>"}",                        \
    ;**|              {$CONDITION=^^  $$VBSTR},                          \
    ;**|              "{$Includes=^*.*^}",     ;;Delimiter = ";"         \
    ;**|              "{$Excludes=^^}",        ;;Delimiter = ";"         \
    ;**|              "{$SrcDir}",                                       \
    ;**|              "{$DestDir}",                                      \
    ;**|              {$How="<$SUBDIRECTORIES>"},                        \
    ;**|              {$CompAttr="<$CATTR_DEFAULT>"}                     \
    ;**|        )                                                       %\
    ;**|        <$DieIfKeyInvalid>{$!}
    ;**+--------------------------------------------------------------------------
    ;**                    /* (Friday 30/03/2001, 15:22:27, by Dennis Bareis) */
    
    
    
    
    ;--- Macros etc to set up for INI entry addition ----------------------------
    #RexxVar IniFileStarted = ''   ;;"" means outside "INIFILE" block
    #RexxVar IniComponent   = ''   ;;Which component controls these entries?
    #RexxVar IniFile        = ''   ;;ShortName of INI file (note, this is NOT a key into the file table, but actual INI name)
    #RexxVar IniDir         = ''   ;;Directory where INI resides (no "[]", example "DIR_QUOTE_LIFE_PGM")
    #define IniFile                                                             \
            ;--- Make sure not already in an INIFILE block -----------------   -\
            <$HereWeAre "{$?MacName} - Start of INI '{$FILE}'">                %\
            #if [IniFileStarted <> '']                                         -\
                #error ^Already in INIFILE "<??IniDir>\<??IniFile>" started at <??IniFileStarted>^  -\
            #endif                                                             -\
            #RexxVar IniFileStarted = ^<?=GetInputFileNameAndLine()>^          -\
                                                                               -\
            ;--- OK, remember details --------------------------------------   -\
            #RexxVar IniFile    = ^{$FILE}^                                    -\
            #RexxVar IniDir     = ^{$DIR}^                                     -\
            #RexxVar IniSection = ^{$SECTION=""}^                              -\
            #RexxVar IniComponent = ^{$Add2="<$DEFAULT_ADD2>"}^                -\
                                                                               -\
            ;--- Now Gain access to the "IniFile" table --------------------   -\
            <$Table "IniFile">                                                 -\
            {$!}
    #define IniSection                                                          \
            ;--- User is indicating the start of a new [section] -----------   -\
            <$HereWeAre "{$?MacName} - Start of INI Section '{$#1}'">          %\
            <$MustBeWithinIniFileBlock>                                        -\
            #RexxVar IniSection = ^{$#1}^                                      -\
            {$!}
    #define /IniFile                                                            \
            ;--- At end of block so end table and clear memory -------------   -\
            <$HereWeAre "{$?MacName} - End of INI '<??IniFile>'">              %\
            <$MustBeWithinIniFileBlock>                                        -\
            <$/Table>                                                          -\
            #RexxVar IniFileStarted = ^^                                       -\
            {$!}
    #define MustBeWithinIniFileBlock                                            \
            #if [IniFileStarted = '']                                          -\
                #error ^You must be within a "IniFile" block to use this macro!^  -\
            #endif                                                             -\
    
    ;--- Macros etc for INI Addition --------------------------------------------
    #define  INIACT_CREATE_OR_UPDATE          0
    #define  INIACT_CREATE_IF_DOESNT_EXIST    1   ;;Never update an existing value!
    #define  INIACT_CREATE_OR_APPEND_COMMASEP 3   ;;Appends to comma delimited list
    #define? INIACT_DEFAULT                  <$INIACT_CREATE_OR_UPDATE>
    #define IniAdd                                                              \
            ;--- Do some validations ---------------------------------------   -\
            <$HereWeAre "{$?MacName} - KEY = {$Key}">                          %\
            <$MustBeWithinIniFileBlock>                                        -\
            #if [IniSection = '']                                              -\
                #error ^You have not defined an INI Section!^                  -\
            #endif                                                             -\
                                                                               -\
            ;--- Add the INI entry to the table ----------------------------   -\
            #evaluate+ ^^ ^DefaultIniKey= 'AddIni<$WiCounter "{$?MacName}">'^  -\
            <$Row                                                               \
                       Key="{$Key}"                                             \
                     Value="{$Value}"                                           \
                    Action="{$Action=^<$INIACT_DEFAULT>^}"                      \
                   IniFile="{$RowKey=^<??DefaultIniKey>^}"                      \
                  FileName="<??IniFile>"                                        \
               DirProperty="<??IniDir>"                                         \
                   Section="<??IniSection>"                                     \
                Component_="<??IniComponent>"                                   \
            >                                                                  -\
            {$!}
    
    
    
    
    ;--- Add Registery Value ----------------------------------------------------
    #define  CURRENT_USER_PUI                 -1      ;;HKEY_
    #define  CLASSES_ROOT                      0      ;;HKEY_
    #define  CURRENT_USER                      1      ;;HKEY_
    #define  LOCAL_MACHINE                     2      ;;HKEY_
    #define  USERS                             3      ;;HKEY_
    #define? HKEY_DEFAULT                             ;;User must override for value to default
    #define  RT_STRING                         0      ;;Type
    #define  RT_EXPANDABLE_STRING              1      ;;Type
    #define  RT_INTEGER                        2      ;;Type
    #define  RT_BINARY                         3      ;;Type
    #define? RT_DEFAULT                        <$RT_STRING>
    #define  RH_CREATED_IF_MISSING             1      ;;How
    #define  RH_CREATE_AND_DELETE_ON_UNINSTALL 3      ;;How
    #define? RH_DEFAULT                        <$RH_CREATED_IF_MISSING>
    #define? DEFAULT_REGKEY                    RegKey<$WiCounter "AddRegValue">
    #define AddRegValue                                                         \
            <$HereWeAre "{$?MacName} - {$ValueName=^(Default)^}">              %\
            #if ['{$HKEY=^<$HKEY_DEFAULT>^}' = '']                                -\
                #error ^HKEY parameter can't default until you specify a default!^ -\
            #endif                                                             -\
            KeyPath = <$WiseObj>.AddRegistryValueEx(                            \
                      {$HKEY},                   ;;Hive can default (see above) \
                      "{$Key}",                  ;;Key Part 1                   \
                      "{$ValueName=^^}",         ;;Key Part 2                   \
                      {$Value  $$VBSTR},         ;;The data!                    \
                      {$Type="<$RT_DEFAULT>"},                                  \
                      {$HOW="<$RH_DEFAULT>"},                                   \
                      "{$Add2="<$DEFAULT_ADD2>"}", ;;Feature/Component name     \
                      {$Add2Type="<$DEFAULT_ADD2TYPE>"},                        \
                      PvComponent                                               \
            )                                                                  %\
            <$DieIfKeyInvalid KEYVAR="KeyPath">                                %\
                                                                               -\
            ;--- Need to adjust the generated Registry entry? ------------     -\
            #RexxVar RxRowKey = ^{$RowKey=^<$DEFAULT_REGKEY>^}^                -\
            #if RxRowKey <> ''                                                 -\
                <$HereWeAre "{$?MacName} - Setting Key to: <??RxRowKey>">      %\
                set RegistryTable = <$WiseObj>.WTables("Registry")             %\
                set RegistryRows  = RegistryTable.WRows()                      %\
                set RegistryRow   = RegistryRows.Row(KeyPath)                  %\
                KeyPath           = "<??RxRowKey>"                             %\
                RegistryRow("Registry") = KeyPath                              %\
                set RegistryRow = Nothing                                      %\
            #endif                                                             -\
                                                                               -\
            ;--- User want this registry entry to be the keypath? --------     -\
            #if ['{$KEYPATH=^N^}' = 'Y']                                       -\
                ;--- User wants to use this registry item as a keypath         -\
                <$HereWeAre "{$?MacName} - This entry is the component keypath">  %\
                Ok = <$WiseObj>.SetComponentKeyPath("{$Add2}", KeyPath)        %\
                <$DieIfNotOk>                                                  %\
            #endif                                                             -\
            {$!}                                                               -\
                                                                               -\
            ;--- Remember this for the HTML report -----------------------     -\
            #evaluate ^^ ^<$Rexx2AddRegToReport {$?ResetUsed}{$?}>^
    #NextId
    #RexxVar RptRegCnt = 0             ;;Currently storing no file information
    #DefineRexx 'Rexx2AddRegToReport'
            ;--- Get Passed Information -----------------------------------------
            @@Hkey = "{$HKEY=^<$HKEY_DEFAULT>^}"
            @@Hkey = word("CURRENT_USER_PU CLASSES_ROOT CURRENT_USER LOCAL_MACHINE USERS", @@Hkey+2);
            @@Key       = "{$Key}"
            @@ValueName = "{$ValueName=^(Default)^}"
            @@Value     = '{$Value $$Sqx2}'
    
            ;--- Combine (using good sort order) and save -----------------------
            @@All  = @@Hkey || '00'x || @@Key || '00'x || @@ValueName || '00'x || @@Value;
            RptRegCnt = RptRegCnt + 1;
            RptReg.RptRegCnt = @@All;
            RptReg.0         = RptRegCnt;
    #DefineRexx
    
    
    
    
    ;--- Add Binary to Binary TABLE ---------------------------------------------
    #define? WISEINST_MAX_BINARY_ENTRIES 100
    #RexxVar RxBinaryCnt = 0
    #(   '<?NewLine>'
       #define AddBinary
               ;--- Generate code to place icon into a VB variable ("ID") -------
               <$HereWeAre "{$?MacName} - {$File}">
               #DependsOn INPUT "{$File}"
               #RexxVar RxBinaryCnt + 1                 ;;Increment counter
               BinaryKey(<??RxBinaryCnt>)  = "{$Key}"   ;;Remember Key
               BinaryFile(<??RxBinaryCnt>) = "{$File}"  ;;Remember File Name
               {$!}
    #)
    
    
    
    ;--- Add ICON to icon table (must be referred to by shortcut or gets "dropped") ---
    #RexxVar   AddIconCnt = 0
    #(   '<?NewLine>'
       #define AddIcon
               ;--- Generate code to place icon into a VB variable ("ID") -------
               <$HereWeAre "{$?MacName} - {$Key=^<?=_filespec('name', "{$File}")>^} : {$File}">
               #DependsOn INPUT "{$File}"
               #evaluate ^^ ^<$LoadIconIntoVbVariable "{$File}">^
               <??VbCode>
    
               ;--- Generate VB code to remember the details --------------------
               '!!! Hack to work around WISE Installer 3.1 Limitations... !!!!!!!!!!
               set IconTable   = <$WiseObj>.WTables("Icon")
               set IconRow     = IconTable.NewWRow()
               IconRow("Name") = "{$Key}"
               IconRow("Data") = ID
               set IconRow     = Nothing
               #evaluate ^^ ^<$AddIconHackRememberDetails KEY=~{$Key}~ FILE=~{$File}~>^
               {$!}
    #)
    #DefineRexx 'AddIconHackRememberDetails'
                ;--- Add to my array --------------------------------------------
                AddIconCnt = AddIconCnt + 1;
                AddIconHack.AddIconCnt.IconKey  = '{$Key}';
                AddIconHack.AddIconCnt.IconFile = '{$File}';
    #DefineRexx
    #DefineRexx 'UpdateMsiForIcons'
                VbCode = "<?NewLine>'!!! Hack to work around Wise 3.1 issues !!!!!<?NewLine>"
                do HackIndex = 1 to AddIconCnt
                   VbCode = VbCode || 'HackIconIntoMsi '
                   VbCode = VbCode || '"' || AddIconHack.HackIndex.IconKey  || '", '
                   VbCode = VbCode || '"' || AddIconHack.HackIndex.IconFile || '", '
                   VbCode = VbCode || '"{$FILE}"<?NewLine>'
                end;
    #DefineRexx
    
    
    ;**      CommentBlock  /* (Friday 16/02/2001, 10:30:52, by Dennis Bareis) */
    ;**+--------------------------------------------------------------------------
    ;**|;--- WISE "FEATURES" PREVENT THIS WORKING
    ;**|;--- Add ICON to icon table (must be referred to by shortcut or gets "dropped") ---
    ;**|#(   '<?NewLine>'
    ;**|   #define AddIcon
    ;**|           ;--- Generate code to place icon into a VB variable ("ID") -------
    ;**|           <$HereWeAre "{$?MacName} - {$Key=^<?=_filespec('name', "{$File}")>^} : {$File}">
    ;**|           #evaluate ^^ ^<$LoadIconIntoVbVariable "{$File}">^
    ;**|           <??VbCode>
    ;**|
    ;**|           ;--- Now Add the loaded icon file into the table -----------------
    ;**|           set IconTable   = <$WiseObj>.WTables("Icon")
    ;**|           set IconRow     = IconTable.NewWRow()
    ;**|           IconRow("Name") = "{$Key}"
    ;**|           IconRow("Data") = ID
    ;**|           set IconRow     = Nothing
    ;**|           {$!}
    ;**|#)
    ;**+--------------------------------------------------------------------------
    ;**                    /* (Friday 16/02/2001, 10:30:52, by Dennis Bareis) */
    
    
    ;--- Add Shortcut -----------------------------------------------------------
    #define? SCD_DEFAULT        <$STARTBAR_PGM_DIR>      ;;Default shortcut dir
    #define  SCT_ADVERTISED     1
    #define  SCT_FOR_FILE       2
    #define  SCT_FOR_CMDLINE    3
    #define? SCT_DEFAULT        <$SCT_FOR_CMDLINE>
    #define  SCW_NORMAL         0
    #define  SCW_MINIMISED      7
    #define  SCW_MAXIMISED      3
    #define  SCW_MINIMIZED      <$SCW_MINIMISED>
    #define  SCW_MAXIMIZED      <$SCW_MAXIMISED>
    #define? SCW_DEFAULT        <$SCW_NORMAL>
    #define AddShortCut                                                        \
            ;--- Actually create the shortcut ---------------------------     -\
            <$HereWeAre "{$?MacName} - {$Title}">                             %\
            <?NewLine>                                                        -\
            Key = <$WiseObj>.AddShortCutEx(                                    \
                  {$ScType=^<$SCT_DEFAULT>^},                                  \
                  lcase("{$ScTarget=^^}"),           ;;Not required if ADVERT (Component name etc) \
                  "{$AdvAdd2="<$DEFAULT_FEATURE>"}", ;;Advert? Install what?   \
                  ShortLongSpec({$Title $$VBSTR}),   ;;Shortcut's Name         \
                  "{$ScDir=^<$SCD_DEFAULT>^}",       ;;Create where?           \
                  "{$ScArgs=^^}",                    ;;Shortcut's arguments    \
                  "{$ScDesc=^^}",                    ;;Shortcut's description  \
                  "{$ScWorkDir=^^}",                 ;;Shortcut's work dir     \
                  {$ScHotKey=^0^},                   ;;Shortcut's hot key      \
                  {$ScWinSize=^<$SCW_DEFAULT>^},     ;;Shortcut's Window size  \
                  {$ScIconNumb=^0^},                 ;;Icon # in EXE           \
                  "{$Add2="<$DEFAULT_ADD2>"}",       ;;Feature/Component name  \
                  {$Add2Type="<$DEFAULT_ADD2TYPE>"}, ;;Feature or Component?   \
                  PvComponent                                                  \
            )                                                                 %\
            <$DieIfKeyInvalid>                                                %\
                                                                              -\
            ;--- Need to adjust the generated shortcut? ------------------    -\
            #if '{$ScIconKey=^^}' <> '' | '{$RowKey=^^}' <> ''                -\
                <$HereWeAre "{$?MacName} - Pointing to ICON: {$ScIconKey}">   %\
                set ShortCutTable = <$WiseObj>.WTables("Shortcut")            %\
                set ShortCutRows  = ShortCutTable.WRows()                     %\
                set ShortCutRow   = ShortCutRows.Row(Key)                     %\
                #if ['{$ScIconKey=^^}' <> '']                                 -\
                    ;--- Assign ICON to this shortcut --------------------    -\
                    <$HereWeAre "{$?MacName} - Add Icon: {$ScIconKey}">       -\
                    <?NewLine>                                                -\
                    ShortCutRow("Icon_") = "{$ScIconKey}"<?NewLine>           -\
                #endif                                                        -\
                #if ['{$RowKey=^^}' <> '']                                    -\
                    ;--- Modify the key (as specified by user) -----------    -\
                    <$HereWeAre "{$?MacName} - New Key: {$RowKey}">           -\
                    <?NewLine>                                                -\
                    ShortCutRow("Shortcut") = "{$RowKey}"<?NewLine>           -\
                #endif                                                        -\
                set ShortCutRow = Nothing                                     %\
            #endif                                                            -\
            {$!}                                                              -\
                                                                              -\
            ;--- Remember this for the HTML report -----------------------    -\
            #evaluate ^^ ^<$Rexx2AddScToReport {$?ResetUsed}{$?}>^
    #NextId
    #RexxVar RptScCnt = 0             ;;Currently storing no file information
    #DefineRexx 'Rexx2AddScToReport'
            ;--- Get Passed Information -----------------------------------------
            @@ScTitle  = '{$Title $$SQx2}'
            @@ScDir    = "{$ScDir=^<$STARTBAR_PGM_DIR>^}"
            @@ScTarget = "{$ScTarget=^^}"
            @@ScArgs   = "{$ScArgs=^^}"
    
            ;--- Combine (using good sort order) and save -----------------------
            @@All  = @@ScTitle || '00'x || @@ScDir || '00'x || @@ScTarget || '00'x || @@ScArgs;
            RptScCnt = RptScCnt + 1;
            RptSc.RptScCnt = @@All;
            RptSc.0        = RptScCnt;
    #DefineRexx
    
    
    
    ;--- Set environment Variables ----------------------------------------------
    #define    ENV_SET_DURING_INSTALLATION =
    #define    ENV_DELETE_ON_INSTALL       !
    #define    ENV_DELETE_ON_UNINSTALL     -
    #define    ENV_CREATE_IF_NONEXISTANT   +
    #define?   ENV_DEFAULT_HOW             <$ENV_SET_DURING_INSTALLATION><$ENV_DELETE_ON_UNINSTALL>
    #define?   ENV_DEFAULT_AS_SYSTEM_VAR   Y       ;;Y/N
    #define?   ENV_DEFAULT_COMPONENT
    #(   '<?NewLine>'
       #define Environment
               ;--- Work out the modifier required for the env vars location ----
               #if ['{$SYSTEM=^<$ENV_DEFAULT_AS_SYSTEM_VAR>^}' = 'Y']  -\
                   #define+ ENV_SYS  *                                 -\
               #elseif                                                 -\
                   #define+ ENV_SYS                                    -\
               #endif                                                  -\
    
               ;--- Default KEY/Component names and description -----------------
               #define+ ENV_KEY   ENV_VAR_{$NAME}_AT_LINE_<?InputComponentLine>
    
               ;--- Point to The Environment TABLE ------------------------------
               <$HereWeAre "{$?MacName} - {$NAME}">
               Set TableEnvironment = <$WiseObj>.WTables("Environment")
    
               ;--- Add Details to the table (create new row) -------------------
               set Row = TableEnvironment.NewWRow()
               Row("Environment") = "{$Key=^<$ENV_KEY>^}"
               Row("Name")        = "<$ENV_SYS>{$HOW=^<$ENV_DEFAULT_HOW>^}{$NAME}"
               Row("Value")       = "{$Value}"
    
               ;--- What component is this being added to (if default then create component) ---
               #if ['{$Component=^<$ENV_DEFAULT_COMPONENT>^}' = '']
                   #error ^You must supply the component name the environment variable is being added to!^
               #endif
    
               ;--- Used supplied component's name ------------------------------
               Row("Component_") = "{$Component}"
               set Row = Nothing               ;;Release object
               {$!}
    #)
    
    
    ;--- Update PATH (type variables) -------------------------------------------
    #(   '<?NewLine>'
       #define Path
               ;--- How is variable updated -------------------------------------
               #if ['{$ATEND=^Y^}' = 'Y']           -\
                   #define+ ENV_POS  [~];{$PATH}    -\
               #elseif                              -\
                   #define+ ENV_POS  {$PATH};[~]    -\
               #endif                               -\
    
               ;--- Point to The Environment TABLE ------------------------------
               <$HereWeAre "{$?MacName}: Setting PATH variable '{$NAME=^PATH^}'">
               <$Environment NAME=~{$NAME=^PATH^}~ VALUE=^<$ENV_POS>^ {$?}>
    #)
    
    
    ;--- Macro(s) to simplify definition of "DIRECTORY ALIASES" -----------------
    ;**      CommentBlock  /* (Thursday 03/05/2001, 10:01:22, by Dennis Bareis) */
    ;**+--------------------------------------------------------------------------
    ;**|#define Directory                                                 \
    ;**|        <$HereWeAre "{$?MacName} - '{$Name}'">                   %\
    ;**|        TmpText1 = "{$SubDir=@<$ProductName>@}"                  %\
    ;**|        TmpText1 = ShortLongSpec(TmpText1)                       %\
    ;**|        <$TABLE "Directory">                                     -\
    ;**|           <$Row                                                  \
    ;**|                      Directory="{$Name}"                         \
    ;**|               Directory_Parent="{$Parent=^ProgramFilesFolder^}"  \
    ;**|;;;;                 DefaultDir="{$SubDir=^<$ProductName>^}"      \
    ;**|                     DefaultDir=^<$VBIMBED STAT=~TmpText1~>^      \
    ;**|           >                                                     -\
    ;**|        <$/TABLE>                                                -\
    ;**|                                                                 -\
    ;**|        ;--- Define a macro which refers to this directory ----  -\
    ;**|        #define {$Name} [{$Name}]                                -\
    ;**|        {$!}
    ;**+--------------------------------------------------------------------------
    ;**                    /* (Thursday 03/05/2001, 10:01:22, by Dennis Bareis) */
    #define Directory                                                      \
            <$HereWeAre "{$?MacName} - '{$Name}'">                        %\
            <$TABLE "Directory">                                          -\
               #if ['{$VALUE=^^}' = '']                                   -\
                   ;--- Just simple definition ------------------------   -\
                   TmpText1 = "{$SubDir=@<$ProductName>@}"                %\
                   TmpText1 = ShortLongSpec(TmpText1)                     %\
                   <$Row                                                   \
                              Directory="{$Name}"                          \
                       Directory_Parent="{$Parent=^ProgramFilesFolder^}"   \
                            DefaultDir=^<$VBIMBED STAT=~TmpText1~>^        \
                   >                                                      -\
               #elseif                                                    -\
                   ;--- Create "template" directory entry -------------   -\
                   <$Row                                                   \
                              Directory="{$Name}"                          \
                       Directory_Parent="TARGETDIR" ;;Value doesn't matter     \
                             DefaultDir=^See_Prop.Tbl|See Property - {$Name}^  \
                   >                                                      -\
                                                                          -\
                   ;--- Now Set the value for the above entry! --------   -\
                   <$SetProperty NAME="{$Name}" VALUE="{$Value}">         -\
               #endif                                                     -\
            <$/TABLE>                                                     -\
                                                                          -\
            ;--- Define a macro which refers to this directory --------   -\
            #define {$Name} [{$Name}]                                     -\
            {$!}
    #define SetDirectoryTextCa                                                  \
            ;--- Create Custom Action to set directory to specific value ---   -\
            <$HereWeAre "{$?MacName} - '{$Directory}' (set with Custom Action)"> %\
            #evaluate+ ^CA_NUMB^     ^'<$WiCounter "{$?MacName}">'^            -\
            #define+    CA_LONG  CA_SetFullDirName_<$CA_NUMB>                  -\
            <$TABLE "CustomAction">                                            -\
               <$Row                                                            \
                   Source="{$Directory}"                                        \
                   Target="{$Text}"                                             \
                   Action="<$CA_LONG>"                                          \
                     Type="35"              ;;Assign text to directory          \
               >                                                               -\
            <$/TABLE>                                                          -\
                                                                               -\
            ;--- Make sure the directory has (or is) created! -------------    -\
            #ifndef {$Directory}                                               -\
               ;--- Create the directory as the user hasn't ---------------    -\
               <$Directory  NAME=^{$Directory}^ SubDir=^SeeCa35.<$CA_NUMB>|See <$CA_LONG>^>  -\
            #endif                                                             -\
            {$!}
    
    
    ;--- Macro to simplify definition of SERVICEs -------------------------------
    #define ServiceInstall                                                      \
            <$HereWeAre "{$?MacName} - '{$Name}'">                             %\
            <$TABLE "ServiceInstall">                                          -\
               <$Row                                                            \
                              Name="{$Name}"                                    \
                       DisplayName="{$DisplayName=~~}"                          \
                    ServiceInstall="{$ServiceInstall}"                          \
                       ServiceType="{$ServiceType=~<$SERVTYPE_DEFAULT>~}"       \
                         StartType="{$StartType=~<$SERVSTART_DEFAULT>~}"        \
                      ErrorControl="{$ErrorControl=~<$SERVERROR_DEFAULT>~}"     \
                    LoadOrderGroup="{$LoadOrderGroup=~~}"                       \
                      Dependencies="{$Dependencies=~~}"   ;;Syntax NOT straightforward, read doco! \
                         StartName="{$StartName=~~}"                            \
                          Password="{$Password=~~}"                             \
                         Arguments="{$Arguments=~~}"                            \
                        Component_="{$Add2=^<$DEFAULT_ADD2>^}"                  \
                       Description="{$Description=~<?=space(GetFileLineBeingProcessed())>~}" \
               >                                                     -\
            <$/TABLE>                                                -\
            {$!}
    #define  SERVTYPE_WIN32_OWN_PROCESS    &H00000010
    #define  SERVTYPE_WIN32_SHARE_PROCESS  &H00000020
    #define  SERVTYPE_INTERACTIVE_PROCESS  &H00000100   ;;Interacts with desktop
    #define  SERVTYPE_KERNEL_DRIVER        &H00000001   ::MSI Doco says unsupported
    #define  SERVTYPE_FILE_SYSTEM_DRIVER   &H00000002   ::MSI Doco says unsupported
    #define? SERVTYPE_DEFAULT              <$SERVTYPE_WIN32_OWN_PROCESS>+<$SERVTYPE_INTERACTIVE_PROCESS>
    #define  SERVSTART_AUTO_IN_STARTUP     &H00000002
    #define  SERVSTART_ON_DEMAND           &H00000003
    #define  SERVSTART_DISABLED            &H00000004
    #define  SERVSTART_DRIVER_BOOT_START   &H00000000   ;;For device driver only
    #define  SERVSTART_DRIVER_SYSTEM_START &H00000001   ;;For device driver only
    #define? SERVSTART_DEFAULT             <$SERVSTART_AUTO_IN_STARTUP>
    #define  SERVERROR_IGNORE              &H00000000
    #define  SERVERROR_NORMAL              &H00000001
    #define  SERVERROR_CRITICAL            &H00000003
    #define? SERVERROR_DEFAULT             <$SERVERROR_CRITICAL>
    
    
    ;--- Macro to simplify definition of SERVICEs -------------------------------
    #define ServiceControl                                                      \
            <$HereWeAre "{$?MacName} - '{$Name}'">                             %\
            <$TABLE "ServiceControl">                                          -\
               <$Row                                                            \
                   ServiceControl="{$ServiceControl=~~}"                        \
                             Name="{$Name}"                                     \
                            Event="{$Event}"                                    \
                        Arguments="{$Arguments=~~}" ;;Arguments should be seperated with "[~]"! \
                             Wait="{$Wait=~<$SERVWAIT_DEFAULT>~}"               \
                       Component_="{$Add2=^<$DEFAULT_ADD2>^}"                   \
               >                                                               -\
            <$/TABLE>                                                          -\
            {$!}
    #define  SERVEVENT_I_START          &H001
    #define  SERVEVENT_I_STOP           &H002
    #define  SERVEVENT_I_DELETE         &H008
    #define  SERVEVENT_UI_START         &H010
    #define  SERVEVENT_UI_STOP          &H020
    #define  SERVEVENT_UI_DELETE        &H080
    #define  SERVWAIT_FOR_SERVICE_START 1
    #define  SERVWAIT_FOR_PENDING       0
    #define? SERVWAIT_DEFAULT           <?SERVWAIT_FOR_SERVICE_START>
    
    
    
    ;--- Define TABLE -----------------------------------------------------------
    #RexxVar InTable = ''
    #define /Table                                                              \
            #RexxVar InTable = ''
    #define Table                                                               \
            ;--- Make sure not already in a table ---                          -\
            #if ['<??InTable>' <> '']                                          -\
                #Error ^Already in table "<??InTable>" started at <??InTableStarted>^  -\
            #endif                                                             -\
                                                                               -\
            ;--- OK, remember details ---------------                          -\
            #RexxVar InTableStarted = ^<?=GetInputFileNameAndLine()>^          -\
            #RexxVar InTable        = ^{$#1}^                                  -\
                                                                               -\
            ;--- Now generate VbScript to access table ---                     -\
            <?NewLine>                                                         -\
            <$HereWeAre =^{$?MacName} - '{$#1}'^>                              %\
            set CurrentTable = <$WiseObj>.WTables("{$#1}")   ;;Generates runtime error if table does not exist  %\
            set CurrentRows  = CurrentTable.WRows()<?NewLine>
    #define MustBeWithinTableMacro                                    \
            ;--- Make sure not already in a table ---                -\
            #if ['<??InTable>' = '']                                 -\
                #Error ^You must be in a table to use this macro!^   -\
            #endif
    
    ;--- Update/Create Row Macro (to update pass key as unnamed parameter) ------
    #define Row                                                                 \
            ;--- Generate code to create a new row ---                         -\
            <$MustBeWithinTableMacro>                                          -\
            <?NewLine>                                                         -\
            #if    ['{$#1=^!NEW!^}' = '!NEW!']                                 -\
                   <$HereWeAre =^{$?MacName} - New Record^>                    %\
                   set CurrentRow  = CurrentTable.NewWRow()                    %\
            #elseif                                                            -\
                   <$HereWeAre =^{$?MacName} - KEY='{$#1}'^>                   %\
                   set CurrentRow = CurrentRows.Row("{$#1}")                   %\
            #endif                                                             -\
                                                                               -\
            ;--- Generate code to initialize fields/columns ---                -\
            #evaluate ^^ ^<$RexxUpdateColumns {$?}>^                           -\
            <??VbCode>     ;;Invalid Field name will cause runtime error
    #DefineRexx RexxUpdateColumns
                ;--- Create rexx stem from passed information -------------------
                {$??}        ;;Allows access to ROW/VALUE information
    
                ;--- Now Create VB code to update the supplied columns ----------
                VbCode = '';
                do Field = 1 to MP.0
                   VbCode = VbCode || 'CurrentRow("' || MP.Field.MpName || '") = "' || ReplaceString(MP.Field.MpValue, '"', '""') || '"<?x0A>'
                end;
                VbCode = VbCode || 'set CurrentRow = Nothing<?x0A>'
    #DefineRexx
    
    ;--- Delete all current records in table ------------------------------------
    #define DeleteAllRows                                                       \
            ;--- Generate code to delete all rows of table ---                 -\
            <$MustBeWithinTableMacro>                                          -\
            <$HereWeAre "{$?MacName}">                                         %\
            for each CurrentRow in CurrentRows                                 %\
                CurrentRows.Delete CurrentRow, FALSE                           %\
            next
    
    ;--- Delete Row by KEY ------------------------------------------------------
    #define DeleteRow                                                           \
            ;--- Generate code to delete specific row ---                      -\
            <$MustBeWithinTableMacro>                                          -\
            <$HereWeAre "{$?MacName} - {$#1}">                                 %\
            CurrentRows.DeleteKeyRow "{$#1}", FALSE{$!}
    
    
    ;--- Load Icon File into a VB Variable (fails or returns VBCODE in 'VbCode') -
    #NextId
    #DefineRexx 'LoadIconIntoVbVariable' NOPACK
            ;--- An Icon file should be small (and separate from pgm)! ----------
            #define? ICON_MAX_SIZE  20000          ;;Default max size
            @@IconFile = '{$#1}';
            @@IconSize = stream(@@IconFile, 'c', 'query size');
            if @@IconSize = '' then
               error('The icon "' || @@IconFile || '" could not be found.');
            if @@IconSize > <$ICON_MAX_SIZE> then
               error('The icon "' || @@IconFile || '" is ' || AddCommasToDecimalNumber(@@IconSize) || ' bytes long', 'An icon file must be SMALL (currently defined to be <= ' || AddCommasToDecimalNumber(<$ICON_MAX_SIZE>) || ' bytes).');
    
            ;--- Read the icon's data into memory -------------------------------
            @@CloseRc      = stream(@@IconFile, 'c', 'close');
            @@IconContents = charin(@@IconFile, 1, 99999);
            @@CloseRc      = stream(@@IconFile, 'c', 'close');
            if length(@@IconContents) <> @@IconSize then
               error('Could not successfully read the icon "' || @@IconFile || '".');
    
            ;--- Create a VB variable containing the data -----------------------
            <$MakeDataSafeInVbLiteral VBVAR="ID" RXVAR="@@IconContents">
    #DefineRexx
    
    ;--- Create a VB variable containing the data (returns code in "VbCode") ----
    #NextId
    #DefineRexx 'MakeDataSafeInVbLiteral' NOPACK
           ;--- Get parameters --------------------------------------------------
           @@Data  = {$RxVar}               ;;Get data into known variable
           @@VbVar = '{$VbVar}'             ;;Get VBVAR name
    
           ;--- Break into multiple lines ---------------------------------------
           #define? MAX_DATA_BLOCK  30
           #define? MAX_DATA_BLOCK  100
           VbCode = @@VbVar || ' = ""<?NewLine>'
           do  while @@Data \== ''
               ;--- How big a chunk should we process? --------------------------
               @@Grab = length(@@Data)
               if  @@Grab > <$MAX_DATA_BLOCK> then
                   @@Grab = <$MAX_DATA_BLOCK>;
    
               ;--- Grab the chunk ----------------------------------------------
               @@Chunk = left(@@Data, @@Grab);
               @@Data  = substr(@@Data, @@Grab+1);
    
               ;--- Now Make sure that all characters are OK --------------------
               @@PreFix = '" & ';
               @@Suffix = ' & "';
               @@Chunk = ReplaceString(@@Chunk, '"',     @@PreFix || 'chr(' || c2d('"') || ')' || @@Suffix);
               @@Chunk = ReplaceString(@@Chunk, '0D0A'x, @@PreFix || 'vbCRLF' || @@Suffix);
               @@Chunk = ReplaceString(@@Chunk, '0D'x,   @@PreFix || 'vbCR'   || @@Suffix);
               @@Chunk = ReplaceString(@@Chunk, '0A'x,   @@PreFix || 'vbLF'   || @@Suffix);
               do @@Chr = 0 to 31
                  @@Chunk = ReplaceString(@@Chunk, d2c(@@Chr), @@PreFix || 'chr(' || @@Chr || ')' || @@Suffix);
               end;
               do @@Chr = 128 to 255
                  @@Chunk = ReplaceString(@@Chunk, d2c(@@Chr), @@PreFix || 'chr(' || @@Chr || ')' || @@Suffix);
               end;
    
               ;--- Quote the value ---------------------------------------------
               @@Chunk = '"' || @@Chunk || '"'
    
               ;--- Need to remove '""' stuff from start and end ----------------
               @@LookS = '"" & '
               @@LookE = ' & ""'
               if  left(@@Chunk, length(@@LookS)) == @@LookS then
                   @@Chunk = substr(@@Chunk, length(@@LookS)+1)
               if  right(@@Chunk, length(@@LookE)) == @@LookE then
                   @@Chunk = left(@@Chunk, length(@@Chunk)-length(@@LookE))
    
               ;--- "Reduce" the VB command as far as possible ------------------
               @@Chunk = ReplaceString(@@Chunk, '& "" &', '&')
    
               ;--- Create new VB command to append to existing data ------------
               VbCode = VbCode || @@VbVar || ' = ' || @@VbVar || ' & ' || @@Chunk || '<?NewLine>'
           end;
    #DefineRexx
    
    
    ;--- Used by any header files to mark version like info ---------------------
    #define    RecordDetailsAboutThisHeaderFile                               \
               #evaluate ^^ ^<$Rexx4RecordDetailsAboutThisHeaderFile {$?}>^  -\
               <??Generating>
    #DefineRexx 'Rexx4RecordDetailsAboutThisHeaderFile'
               ;--- Work out the property name ----------------------------------
               if '{$FileName=^^}' = '' then
               do
                   ;--- Use the "CURRENT" input files name (normal use) ---------
                   HeaderFile = InputComponentLevel();
               end;
               else
               do
                   ;--- User wants SPECIFIC file details added ------------------
                   HeaderFile = '{$FileName}';
               end;
               HeaderId = '<$WISEINST_PROP_PREFIX>Header_' || _filespec('name', HeaderFile);
    
               ;--- Get some identifying characteristics (name, version, size and timestamp) ---
               HeaderSize = AddCommasToDecimalNumber(stream(HeaderFile, 'c', 'query size'));
               <$Rexx2GetFormattedFileTime FileVar="HeaderFile" TIMEVAR="Time" DATEVAR="Date">
               HeaderTime  = Date || ' at ' || Time
               HeaderValue = HeaderFile || ' (v{$Version}, ' || HeaderSize || ' bytes, dated ' || HeaderTime || ')'
    
               ;--- Generate code to create the property ------------------------
               Generating = '<' || '$SetProperty NAME="' || HeaderId || '"  VALUE=^' || HeaderValue || '^><?NewLine>' || d2c(10)
    #DefineRexx
    
    
    ;----------------------------------------------------------------------------
    ;--- Convert File time stamp into nicely formatted date/time ----------------
    ;----------------------------------------------------------------------------
    #NextId
    #DefineRexx 'Rexx2GetFormattedFileTime'
       ;--- Can either be passed a timestamp or a file name ---------------------
       @@FileTs = {$TSVAR=^""^};
       if  @@FileTs = '' then
       do
           ;--- A timestamp was not passed --------------------------------------
           @@FileTs = GetFileTimeStamp({$FileVar='ShouldNotDefaultHere...'});
           if  @@FileTs = -1 then
               error('Could not get the time for the file "' || {$FileVar} || '".');
       end;
    
       ;--- Convert date --------------------------------------------------------
       @@DD   = substr(@@FileTs, 7, 2);
       @@MM   = substr(@@FileTs, 5, 2);
       @@YYYY = left(@@FileTs, 4);
       {$DATEVAR} = @@DD+0 || ' ' || word('Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec', @@MM) || ' ' || @@YYYY
    
       ;--- Convert time --------------------------------------------------------
       {$TIMEVAR} = GetAmPmTimeFromHhMmSs(substr(@@FileTs, 9));
    #DefineRexx
    
    
    ;----------------------------------------------------------------------------
    ;--- Generic Counter --------------------------------------------------------
    ;----------------------------------------------------------------------------
    #NextId
    #define      WiCounter                        \
                 <$Rexx4WiCounter {$?} $$RXEXEC>
    #DefineRexx  'Rexx4WiCounter'
       @@CntVAR    = 'WICOUNTER_' || c2x(translate('{$#1}'));  ;;Generate Rexx var name unlikely to clash with anything!
       @@NumDigits = '{$Digits=^3^}'                           ;;By default padded to 3 digits
       if  symbol(@@CntVAR) <> 'VAR' then                      ;;Get incremented value
           @@Val = 1;
       else
           @@Val = value(@@CntVAR) + 1;
       call value @@CntVAR, @@Val;                ;;Remember value
    
       ;--- Pad the value (NEVER truncate!). Padding allows sorting in Orca etc -
       if  length(@@Val) >= @@NumDigits then
           RxExec = @@Val;                          ;;Don't pad!
       else
           RxExec = right(@@Val, @@NumDigits, '0'); ;;Pad to left with zeros
    #DefineRexx
    
    
    
    ;----------------------------------------------------------------------------
    ;--- The following Code should be at START of generated code ----------------
    ;----------------------------------------------------------------------------
    #( '<?NewLine>'
       ;--- Define name of macro ------------------------------------------------
       #define VBSCRIPT_AT_START
    
               '----------------------------------------------------------------
               ' This file was automatically produced by PPWIZARD.
               '
               ' PPWIZARD is a FREE product (for private or commercial use),
               ' available from:
               '
               '      <?PpwizardHomePage>
               '
               ' Apart from possiblity doing some debugging do not modify this
               ' file as your changes will get lost when the file is
               ' regenerated.
               '
               '
               ' DETAILS
               ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
               ' Generated VB: <?OutputFile>
               ' From        : <?InputFile>
               ' At          : <?CompileTime>
               ' PPWIZARD    : v<?Version> of <?PpwizardPgm>
               ' Header      : v<$WISEINST_VERSION> of <$WISEINST_HEADER>
               '----------------------------------------------------------------
    
               ;--- Require all used variables to be defined --------------------
               <?NewLine>
               Option Explicit
    
               ;--- Define some global variables --------------------------------
               dim <$WiseObj>
               dim TableEnvironment           ;;Used by PATH   macro
               dim IconTable, IconRow         ;;Used by ADDICON macro
               dim RegistryTable              ;;Used by AddRegistry macro
               dim RegistryRows, RegistryRow
               dim ShortCutTable              ;;Used by ADDSHORTCUT macro
               dim ShortCutRows, ShortCutRow
               dim CurrentTable               ;;Used by TABLE  macros
               dim CurrentRows, CurrentRow    ;;Used by ROW macros
               dim BinaryKey(<$WISEINST_MAX_BINARY_ENTRIES>)
               dim BinaryFile(<$WISEINST_MAX_BINARY_ENTRIES>)
               dim ID                         ;;Used to Hold binary data of icon
               dim TmpText1, TmpText2         ;;Some temporary text strings
               dim TmpText3, TmpText4         ;;Some temporary text strings
               dim StartTime      : StartTime        = timer()
               dim HereWeAreLoc   : HereWeAreLoc     = "(?)"
               dim HereWeAreLocTxt: HereWeAreLocTxt  = "Beginning"
               dim Row
               dim PvComponent
               dim KeyPath, Key, Ok
               dim NL, NP
               NL = chr(10) & chr(13)
               NP = NL & NL
    
               ;--- Set up some VB runtime "constants" (I support user access to these) ---
               dim VbMadeTime          ;;Date/Time VbScript was run to produce the package
               VbMadeTime = FormatDateTime(date(), vbLongDate) & " " & time()
    
               ;--- Call mainline() ---------------------------------------------
               #if ['<$RUNTIME_TRAPS_DETECTED>' = 'N']
                   ;--- Execute code (never returns) ----------------------------
                   #ifdef DEBUG_OUTPUT
                       Say  "As Per your request there was no trap handler added!"
                   #endif
                   MainLine()
               #elseif
                   ;--- Define error handler ------------------------------------
                   on error resume next
    
                   ;--- Execute code (never returns) ----------------------------
                   MainLine()
    
                   ;--- If we get here we had a runtime error (display the error) ---
                   Say ""
                   Say "VBSCRIPT TRAP Detected"
                   Say "~~~~~~~~~~~~~~~~~~~~~~"
                   Say "Error Number: " & CStr(Err.Number)
                   Say "Desc        : " & Err.Description
                   Say "Near        : " & HereWeAreLocTxt
                   Say "In Script   : " & WScript.ScriptFullName
                   Say "Detected by : " & Err.Source
    
                   ;--- Do we want a message box as well? -----------------------
                   #ifndef NO_POPUP_ON_TRAP
                           dim Text, Title
                           Title = "TRAP IN " & WScript.ScriptName
                           Text  = "Error # " & CStr(Err.Number) & " " & Err.Description & NP & "Error occurred near " & HereWeAreLocTxt
                           MsgBox Text, vbCritical, Title
                   #endif
    
                   ;--- Attempt to save WSI for possible debugging --------------
                   Say ""
                   Say "Saving WSI for debugging..."
                   Ok = <$WiseObj>.Save("<$GENERATE_WSI>")
               #endif
    
               ;--- Trap EXIT ---------------------------------------------------
               Wscript.Quit 218
    
               ;--- Define start of Mainline ------------------------------------
               <?NewLine>
               <?NewLine>
               '============================================================================
               Sub MainLine
               '============================================================================
    
               ;--- Show user what is being built -------------------------------
               Say "We are building ""<$GENERATE>"""
    
               ;--- Delete WSI/MSI (proves not in use etc) ----------------------
               <$HereWeAre "Deleting Files">
               DeleteFile "<$GENERATE_WSI>"
               DeleteFile "<$GENERATE_MSI>"
    
               ;--- Connect to Wise for Windows Installer object ----------------
               <?NewLine>
               <$HereWeAre "{$?MacName}">
               Say "Creating Wise Document"
               Set <$WiseObj> = Nothing
               Set <$WiseObj> = Wscript.CreateObject("WfWi.Document")
    
               ;--- Make sure exceptions are turned on --------------------------
               <$HereWeAre "{$?MacName} - Making sure Exceptions are enabled">
               <$WiseObj>.EnableExceptions(TRUE)
    
               ;--- Want to see SAVING/GENERATING Popups (default is YES)? ------
               #ifdef NO_WISE_PROGRESS_POPUPS
                      <$HereWeAre "{$?MacName} - Disabling Saving/Generating progress popups">
                      <$WiseObj>.SetSilent()
               #endif
    
               ;--- Make MSI ----------------------------------------------------
               #define NEWT_INSTALLER_DB_PROJECT 1
               #define NEWT_MERGE_MODULE_PROJECT 3
               Ok = <$WiseObj>.NewEx({$TYPE="<$NEWT_INSTALLER_DB_PROJECT>"}, {$WANTPRJFILE="TRUE"})
               <$DieIfNotOk>
    
               ;--- Set a GENERATOR property ("Creating Application" summary does not work?) ---
               #define? WISEINST_GENERATOR_TEXT  PPWIZARD v<?Version> (FreeWare, see <?PpwizardHomePage>)
               <$SetProperty NAME="<$WISEINST_PROP_PREFIX>Generator"  VALUE=^<$WISEINST_GENERATOR_TEXT>^>
    
               ;--- Record details about THIS header file -----------------------
               <$RecordDetailsAboutThisHeaderFile VERSION=^<$WISEINST_VERSION>^ FILENAME=^<??WiseInstHeaderFile>^>
    
               ;--- Space out ---------------------------------------------------
               <?NewLine>
               <?NewLine>
               {$!}
    #)
    
    
    ;----------------------------------------------------------------------------
    ;--- The following Code should be at END of generated code ------------------
    ;----------------------------------------------------------------------------
    #( '<?NewLine>'
       ;--- Define name of macro ------------------------------------------------
       #define VBSCRIPT_AT_END
    
               ;--- Now save the WSI file (if case compile saves can look at WSI) ---
               <?NewLine>
               <$HereWeAre "{$?MacName} - Generating Files">
               Say "Generating: <$GENERATE_WSI>"
               Ok = <$WiseObj>.Save("<$GENERATE_WSI>")
               <$DieIfNotOk>
    
               ;--- Handy Debug Hook --------------------------------------------
               #define? DEBUG_HOOK_AFTER_SAVE
               <$DEBUG_HOOK_AFTER_SAVE>
    
               ;--- Generate the MSI file ---------------------------------------
               Say "Compiling: <$GENERATE_WSI>"
               Ok = <$WiseObj>.Compile("<$GENERATE_WSI>")
               <$DieIfNotOk>
    
               ;--- Double check files exist (Wise won't complain on error!) ----
               <$HereWeAre "Double checking files were generated">
               FileMustExist "<$GENERATE_WSI>"
               FileMustExist "<$GENERATE_MSI>"
    
               ;--- Handy Debug Hook --------------------------------------------
               #define? DEBUG_HOOK_AFTER_COMPILE
               <$DEBUG_HOOK_AFTER_COMPILE>
    
               ;--- Release resources -------------------------------------------
               <$HereWeAre "Releasing resources">
               set <$WiseObj> = Nothing
    
               ;--- If we have any binary resources to add then do so -----------
               #if [RxBinaryCnt <> 0]
                    HereWeAre "", "Adding <??RxBinaryCnt> binary resources to WSI"
                    AddBinaryResources("<$GENERATE_WSI>")
                    HereWeAre "", "Adding <??RxBinaryCnt> binary resources to MSI"
                    AddBinaryResources("<$GENERATE_MSI>")
               #endif
    
               ;--- Add any icons -----------------------------------------------
               #if  AddIconCnt <> 0
                    HereWeAre "", "Hacking icons into WSI (Wise 3.1 workaround)....."
                    #evaluate ^^ ^<$UpdateMsiForIcons FILE="<$GENERATE_WSI>">^
                    <??VbCode>
                    HereWeAre "", "Hacking icons into MSI (Wise 3.1 workaround)....."
                    #evaluate ^^ ^<$UpdateMsiForIcons FILE="<$GENERATE_MSI>">^
                    <??VbCode>
                    HereWeAre "", "Hacking complete!"
               #endif
    
               ;--- Thats All Folks! --------------------------------------------
               dim Elapsed: Elapsed = timer() - StartTime
               if Elapsed < 0 then
                   Elapsed = Elapsed + (60*60*24)
               end if
               Elapsed = round(Elapsed, 0)
               Say "Thats All Folks!!! Product was successfully packaged (took " & Elapsed & " seconds)."
               Wscript.Quit 0{$!}
    
               ;--- Define end of Mainline() ------------------------------------
               End Sub 'Mainline
    
               ;--- We are about to die because of an invalid return code -------
               <?NewLine>
               <?NewLine>
               <?NewLine>
               '============================================================================
               Sub Die(Why)
               '============================================================================
                   ;--- Output a header -----------------------------------------
                   Say ""
                   Say "Error Detected"
                   Say "~~~~~~~~~~~~~~"
    
                   ;--- Output the WISE return code -----------------------------
                   Say "Near    : " + HereWeAreLocTxt
                   if  Why = Null then
                       say "Wise Rc : " & <$WiseObj>.GetLastError()
                   else
                       say "Reason  : " & Why
                   end if
    
                   ;--- Display a popup unless user doesn't want one ------------
                   #ifndef NO_POPUP_ON_ERROR
                       dim Text, Title
                       Title = "ERROR IN " & WScript.ScriptName
                       if  Why = Null then
                           Text  = "Wise reports: " & <$WiseObj>.GetLastError()
                       else
                           Text =  "Reason: " & Why
                       end if
                       Text = Text & NP & "Error occurred near " & HereWeAreLocTxt
                       MsgBox Text, vbCritical, Title
                   #endif
    
                   ;--- Simply exit ---------------------------------------------
                   Wscript.Quit 219
               end sub
    
               ;--- Display a line ----------------------------------------------
               <?NewLine>
               '============================================================================
               Sub Say(What)
               '============================================================================
                   Wscript.Echo What
               end sub
    
               ;--- Display a line ----------------------------------------------
               <?NewLine>
               '============================================================================
               Sub HereWeAre(Loc, Txt)
               '============================================================================
                   ;--- Remember where we are -----------------------------------
                   if  Loc <> "" then
                       HereWeAreLoc = Loc
                   end if
                   HereWeAreLocTxt = HereWeAreLoc + " " + Txt
    
                   ;--- If in debug mode we display the text --------------------
                   #if ['<$VERBOSE_OUTPUT>' = 'Y']
                       Wscript.Echo HereWeAreLocTxt
                   #endif
               end sub
    
               ;--- File MUST Exist ---------------------------------------------
               <?NewLine>
               '============================================================================
               Sub FileMustExist(FileName)
               '============================================================================
                   dim fso
                   set fso = CreateObject("Scripting.FileSystemObject")
                   if  not fso.FileExists(FileName) then
                       Die("The file '" & FileName & "' does not exist!")
                   end if
               End Sub
    
               ;--- Delete a file -----------------------------------------------
               <?NewLine>
               '============================================================================
               Sub DeleteFile(FileName)
               '============================================================================
                   dim fso
                   set fso = CreateObject("Scripting.FileSystemObject")
                   if  fso.FileExists(FileName) then
                       ;--- Delete it -------------------------------------------
                       dim Reason
                       on error resume next
                       fso.DeleteFile(FileName)
                       Reason = Err.Description
    
                       ;--- Ensure it has been deleted --------------------------
                       if  fso.FileExists(FileName) then
                           Die("Could not delete '" & FileName & "' (" & Reason & ")")
                       end if
                   end if
               End Sub
    
               ;--- Makes sure we have "short|long" file spec -------------------
               <?NewLine>
               '============================================================================
               function ShortLongSpec(PassedSpec)
               '============================================================================
                   ;--- May already have the shortname attached -----------------
                   if  instr(1, PassedSpec, "|", 1) <> 0 then
                       ;--- Already contains short and long specs ---------------
                       ShortLongSpec = PassedSpec
                   else
                       ShortLongSpec = ShortNameFromLong(PassedSpec) & "|" & PassedSpec
                   end if
               end function
    
    
               ;--- Creates a SHORT filename from a LONG one (user can replace) -
               <?NewLine>
               '============================================================================
               function ShortNameFromLong(LongName)
               '============================================================================
                   ;--- Define variable that user should put result in ----------
                   dim ShortName
    
                   ;--- User can replace this code to convert longname ----------
                   <$VBCODE_SHORT_NAME_FROM_LONG>
    
                   ;--- Return the short name value -----------------------------
                   ShortNameFromLong = ShortName
               end function
    
               ;--- Checks "KEY" return codes -----------------------------------
               <?NewLine>
               Sub KeyMustBeOk(ThisMustBeNonBlank)
                   if  ThisMustBeNonBlank = "" then
                       Die(Null)
                   end if
               end sub
    
               ;--- Checks Boolean return codes ---------------------------------
               <?NewLine>
               Sub BoolMustBeTrue(ThisMustBeTrue)
                   if  not ThisMustBeTrue  then
                       Die(Null)
                   end if
               end sub
    
    
               ;--- Add Binary fields "Binary Table" ----------------------------
               <?NewLine>
               <?NewLine>
               '============================================================================
               sub AddBinaryResources(MsiFile)
               '============================================================================
                   ;--- Open Windows Installer object ---------------------------
                   dim Installer
                   set Installer = Wscript.CreateObject("WindowsInstaller.Installer")
    
                   ;--- Open an MSI database (file) in READ/WRITE mode ----------
                   dim MsiDb
                   set MsiDb = Installer.OpenDatabase(MsiFile, 2)  'Open Read/Write No Transactions
    
                   '--- Open BINARY table ---------------------------------------
                   dim View, Record
                   set View = MsiDb.OpenView("SELECT Name,Data FROM Binary")
                   View.Execute
    
                   ;--- Add All binaries to table -------------------------------
                   dim BinIndex
                   for BinIndex = 1 to <??RxBinaryCnt>
                       '--- Create a record (with 2 fields) ---------------------
                       set Record = Installer.CreateRecord(2)
    
                       '--- Update the fields -----------------------------------
                       Record.StringData(1) = BinaryKey(BinIndex)
                       Record.SetStream 2,    BinaryFile(BinIndex)
    
                       '--- Insert the record -----------------------------------
                       View.Modify 1, Record
                       set Record = Nothing
                   next
    
                   ;--- Need to call "commit" to write data ---------------------
                   MsiDb.commit()
               end sub
    
               ;--- Add ICONs to "Icon Table" -----------------------------------
               <?NewLine>
               <?NewLine>
               '============================================================================
               Sub HackIconIntoMsi(IconKey, IconFile, MsiFile)
               '============================================================================
                   ;--- Open Windows Installer object ---------------------------
                   dim Installer
                   set Installer = Wscript.CreateObject("WindowsInstaller.Installer")
    
                   ;--- Open an MSI database (file) in READ/WRITE mode ----------
                   dim MsiDb
                   set MsiDb = Installer.OpenDatabase(MsiFile, 2)  'Open Read/Write No Transactions
    
                   ;--- Open ICON table -----------------------------------------
                   dim View, Record, TableName
                   set View = MsiDb.OpenView("SELECT Name,Data FROM Icon")
                   View.Execute
    
                   ;--- Create a record -----------------------------------------
                   set Record = Installer.CreateRecord(2)
    
                   ;--- Update the fields ---------------------------------------
                   Record.StringData(1) = IconKey
                   Record.SetStream 2, IconFile
    
                   ;--- Insert the record ---------------------------------------
                   View.Modify 1, Record
    
                   ;--- Need to call "commit" to write data ---------------------
                   MsiDb.commit()
               end sub
    #)
    #ifndef VBCODE_SHORT_NAME_FROM_LONG
           #define VBCODE_SHORT_NAME_FROM_LONG                  \
                   ;--- Only want valid chars! ---             -\
                   ShortName = replace(LongName, " ", "")      %\
                                                               -\
                   ;--- Now grab left 11 chars ---             -\
                   if len(ShortName) < 8 then                  %\
                       ShortName = left(ShortName, 8)          %\
                   else                                        %\
                       ShortName = left(ShortName, 8)           \
                                 & "."                          \
                                 & mid(ShortName, 9, 3)        %\
                   end if
    #endif
    
    
    
    
    
    ;----------------------------------------------------------------------------
    ;--- Generates any HTML reports ---------------------------------------------
    ;----------------------------------------------------------------------------
    #NextId
    #define GenerateAnyHtmlReports                                              \
            ;--- Create start of Report file -----------------------------     -\
            #output "<$GENERATE_RPT>" ASIS HTML                                -\
            <$WISEINST_HTMLRPT_START>                                          -\
                                                                               -\
            ;--- Generate FILES report -----------------------------------     -\
            #if [RptFileCnt = 0]                                               -\
                <$WISEINST_HTMLRPT_NO_FILES>                                   -\
            #elseif                                                            -\
               ;--- Start the HTML table ---------------------------------     -\
               <$WISEINST_HTMLRPT_HEADING TEXT="FILES">                        -\
               <$WISEINST_HTMLRPT_FILETABLE_START>                             -\
                                                                               -\
               ;--- Sort file table entries ------------------------------     -\
               #evaluate ^^ ^call SortArray 'RptFile'^                         -\
                                                                               -\
               ;--- Generate guts of report ------------------------------     -\
               #RexxVar @@Index = 1                                            -\
               #{                                                              -\
                   ;--- Split off components -----------------------------     -\
                   #evaluate ^^ ^parse var RptFile.@@Index @@Short '00'x @@DstDir '00'x @@SrcDir '00'x @@DateTs '00'x @@Size;^ -\
                   #evaluate ^^ ^@@SrcDir = BreakAt("40-50", @@SrcDir, '\ ')^  -\
                   #evaluate ^^ ^@@DstDir = BreakAt("20-30", @@DstDir, '_\ ')^ -\
                   #evaluate ^^ ^<$Rexx2GetFormattedFileTime TSVAR="@@DateTs" TIMEVAR="@@Time" DATEVAR="@@Date">^ -\
                                                                               -\
                   ;--- Generate the HTML for this file ------------------     -\
                   <$WISEINST_HTMLRPT_FILETABLE_ROW>                           -\
                                                                               -\
                   ;--- Increment counter (finished?) --------------------     -\
                   #RexxVar @@Index + 1                                        -\
                   #if [@@Index > RptFileCnt]                                  -\
                       #break                                                  -\
                   #endif                                                      -\
               #}                                                              -\
                                                                               -\
               ;--- End the HTML table -----------------------------------     -\
               <$WISEINST_HTMLRPT_FILETABLE_END>                               -\
            #endif                                                             -\
                                                                               -\
            ;--- Generate SHORTCUT report --------------------------------     -\
            #if [RptScCnt = 0]                                                -\
                <$WISEINST_HTMLRPT_NO_SHORTCUT>                                -\
            #elseif                                                            -\
               ;--- Start the HTML table ---------------------------------     -\
               <$WISEINST_HTMLRPT_HEADING TEXT="SHORTCUTS">                    -\
               <$WISEINST_HTMLRPT_SCTABLE_START>                              -\
                                                                               -\
               ;--- Sort file table entries ------------------------------     -\
               #evaluate ^^ ^call SortArray 'RptSc'^                          -\
                                                                               -\
               ;--- Generate guts of report ------------------------------     -\
               #RexxVar @@Index = 1                                            -\
               #{                                                              -\
                   ;--- Split off components -----------------------------     -\
                   #evaluate ^^ ^parse var RptSc.@@Index @@ScTitle '00'x @@ScDir '00'x @@ScTarget '00'x @@ScArgs^ -\
                   #evaluate ^^ ^@@ScTitle  = BreakAt("40-50", @@ScTitle, '\ ')^     -\
                   #evaluate ^^ ^@@ScTarget = BreakAt("40-50", @@ScTarget, '\ ')^    -\
                   #evaluate ^^ ^@@ScArgs   = BreakAt("40-50", @@ScArgs, '\ ')^      -\
                                                                               -\
                   ;--- Generate the HTML for this file ------------------     -\
                   <$WISEINST_HTMLRPT_SCTABLE_ROW>                            -\
                                                                               -\
                   ;--- Increment counter (finished?) --------------------     -\
                   #RexxVar @@Index + 1                                        -\
                   #if [@@Index > RptScCnt]                                   -\
                       #break                                                  -\
                   #endif                                                      -\
               #}                                                              -\
                                                                               -\
               ;--- End the HTML table -----------------------------------     -\
               <$WISEINST_HTMLRPT_SCTABLE_END>                                -\
            #endif                                                             -\
                                                                               -\
            ;--- Generate REGISTRY report --------------------------------     -\
            #if [RptRegCnt = 0]                                                -\
                <$WISEINST_HTMLRPT_NO_REGISTRY>                                -\
            #elseif                                                            -\
               ;--- Start the HTML table ---------------------------------     -\
               <$WISEINST_HTMLRPT_HEADING TEXT="REGISTRY">                     -\
               <$WISEINST_HTMLRPT_REGTABLE_START>                              -\
                                                                               -\
               ;--- Sort file table entries ------------------------------     -\
               #evaluate ^^ ^call SortArray 'RptReg'^                          -\
                                                                               -\
               ;--- Generate guts of report ------------------------------     -\
               #RexxVar @@Index = 1                                            -\
               #{                                                              -\
                   ;--- Split off components -----------------------------     -\
                   #evaluate ^^ ^parse var RptReg.@@Index @@Hkey '00'x @@Key '00'x @@ValueName '00'x @@Value^ -\
                   #evaluate ^^ ^@@Key   = BreakAt("40-50", @@Key, '\ ')^      -\
                   #evaluate ^^ ^@@Value = BreakAt("20-80", @@Value, '_\ ')^   -\
                                                                               -\
                   ;--- Generate the HTML for this file ------------------     -\
                   <$WISEINST_HTMLRPT_REGTABLE_ROW>                            -\
                                                                               -\
                   ;--- Increment counter (finished?) --------------------     -\
                   #RexxVar @@Index + 1                                        -\
                   #if [@@Index > RptRegCnt]                                   -\
                       #break                                                  -\
                   #endif                                                      -\
               #}                                                              -\
                                                                               -\
               ;--- End the HTML table -----------------------------------     -\
               <$WISEINST_HTMLRPT_REGTABLE_END>                                -\
            #endif                                                             -\
                                                                               -\
            ;--- Generate SOURCE CODE report -----------------------------     -\
            #ifndef WISEINST_HTMLRPT_NO_SOURCE_CODE                            -\
               <$WISEINST_HTMLRPT_HEADING TEXT="SOURCE CODE">                  -\
               #if FindFile("HTMLPRE.IH") = ''                                 -\
                   <$WISEINST_HTMLRPT_CANT_SHOW_SOURCE>                        -\
               #elseif                                                         -\
                   ;--- Have "PRE" support -------------------------------     -\
                   #define HTMLPRE_COLOR          black                        -\
                   #define HTMLPRE_STYLE_OTHER                                 -\
                   #include "HTMLPRE.IH"                                       -\
                   <$ExampleFile FILE="<?InputFile>">                          -\
               #endif                                                          -\
            #endif                                                             -\
                                                                               -\
            ;--- Create end of Report file -------------------------------     -\
            <$WISEINST_HTMLRPT_DISCLAIMER>                                     -\
            <$WISEINST_HTMLRPT_END>                                            -\
            #output
    
    ;--- User can override these report definitions to alter look & feel --------
    #( ' '
       #define? WISEINST_HTMLRPT_DISCLAIMER                                        \
       <P>Note that this report may not show all resources of the
       types show.
       To show up in the report the developer must use
       the appropriate macros and not use "TABLE" and "ROW" directly
       etc.
       The items reported are also in summary form and other
       information can be obtained from the source listing of the
       generated WSI or MSI file.
    #)
    #define? WISEINST_HTMLRPT_HEADING                                           \
             <CENTER><H1>{$Text}</H1></CENTER>
    #( '<?NewLine>'
       #define? WISEINST_HTMLRPT_START
       <HTML>
       <!--- Automatically generated at <?CompileTime> --->
       <HEAD>
           <meta name="GENERATOR" content="PPWIZARD, FREE tool for Windows, OS/2, DOS and UNIX by Dennis Bareis (<?PpwizardHomePage>)">
           <TITLE><$ProductName> v<$ProductVersion></TITLE>
           <STYLE TYPE="text/css">
           <!--
               BODY {font-size:80%;font-family:"Comic Sans MS","Verdana","Arial","Helvetica";}
               TD   {font-size:80%;font-family:"Comic Sans MS","Verdana","Arial","Helvetica";}
               PRE  {font-size:100%;background-color: #ffffc6;color:black;display:block;white-space:pre;border:1px solid #800000;padding:5}
           -->
           </STYLE>
       </HEAD>
       <BODY BGCOLOR="#ffb573">
           <TABLE BORDER=0 BGCOLOR="red" WIDTH="100%" CELLPADDING=2 CELLSPACING=0><TR><TD ALIGN="CENTER">
           <FONT SIZE="+3" COLOR="white">
                  <$ProductName> v<$ProductVersion>
           </FONT></TD></TR></TABLE>
           <$WISEINST_HTMLRPT_UNDER_TITLE>
           <P>
    #)
    #( '<?NewLine>'
       #define? WISEINST_HTMLRPT_END
           <P>
           <HR SIZE="1" COLOR="red">
           <CENTER>
           Created at <?CompileTime>
           <$WISEINST_HTMLRPT_FOOTER_UNDER_TIME>
           </CENTER>
       </BODY>
       </HTML>
    #)
    
    ;--- User can override these FILE report definitions to alter look & feel ---
    #define? WISEINST_HTMLRPT_NO_FILES                                          \
             <$WISEINST_HTMLRPT_HEADING TEXT="FILES">                          -\
             <P><B>There were no files in this package!</B>
    #( '<?NewLine>'
       #define? WISEINST_HTMLRPT_FILETABLE_START
       <CENTER>
       <TABLE COLS="5" Border="1" Border="1" BORDERCOLOR="navy" CELLPADDING="3" cellspacing="1">
       <TR>
           <TH>Short<BR>Name</TH>
           <TH>Time</TH>
           <TH>Size</TH>
           <TH>Destination<BR>Directory</TH>
           <TH>Source<BR>Directory</TH>
       </TR>
    #)
    #( '<?NewLine>'
       #define? WISEINST_HTMLRPT_FILETABLE_ROW
       <?NewLine>
       <TR>
           <TD><??@@Short></TD>
           <TD><??@@Date><BR><??@@Time></TD>
           <TD ALIGN="RIGHT"><??@@Size></TD>
           <TD><??@@DstDir></TD>
           <TD><??@@SrcDir></TD>
       </TR>
    #)
    #( '<?NewLine>'
       #define? WISEINST_HTMLRPT_FILETABLE_END
       </TABLE>
       <P><??RptFileCnt> File(s).
       </CENTER>
    #)
    
    
    ;--- User can override these SHORTCUT report definitions to alter look & feel ---
    #( '<?NewLine>'
       #define? WISEINST_HTMLRPT_NO_SHORTCUT
       <$WISEINST_HTMLRPT_HEADING TEXT="SHORTCUTS">
       <P><B>
       There are no shortcuts.
       </B>
    #)
    #( '<?NewLine>'
       #define? WISEINST_HTMLRPT_SCTABLE_START
       <CENTER>
       <TABLE COLS="4" Border="1" Border="1" BORDERCOLOR="navy" CELLPADDING="3" cellspacing="1">
       <TR>
           <TH>Title</TH>
           <TH>Location</TH>
           <TH>Target</TH>
           <TH>Arguments</TH>
       </TR>
    #)
    #( '<?NewLine>'
       #define? WISEINST_HTMLRPT_SCTABLE_ROW
       <?NewLine>
       <TR>
           <TD><??@@ScTitle></TD>
           <TD><??@@ScDir></TD>
           <TD><??@@ScTarget></TD>
           <TD><??@@ScArgs></TD>
       </TR>
    #)
    #( '<?NewLine>'
       #define? WISEINST_HTMLRPT_SCTABLE_END
       </TABLE>
       <P><??RptScCnt> Shortcut(s).
       </CENTER>
    #)
    
    
    ;--- User can override these REGISTRY report definitions to alter look & feel ---
    #( '<?NewLine>'
       #define? WISEINST_HTMLRPT_NO_REGISTRY
       <$WISEINST_HTMLRPT_HEADING TEXT="REGISTRY">
       <P><B>
       There are no registry enties.
       </B>
    #)
    #( '<?NewLine>'
       #define? WISEINST_HTMLRPT_REGTABLE_START
       <CENTER>
       <TABLE COLS="4" Border="1" Border="1" BORDERCOLOR="navy" CELLPADDING="3" cellspacing="1">
       <TR>
           <TH>HKEY<BR>(Hive)</TH>
           <TH>Key</TH>
           <TH>Value<BR>Name</TH>
           <TH>Value</TH>
       </TR>
    #)
    #( '<?NewLine>'
       #define? WISEINST_HTMLRPT_REGTABLE_ROW
       <?NewLine>
       <TR>
           <TD><??@@HKey></TD>
           <TD><??@@Key></TD>
           <TD><??@@ValueName></TD>
           <TD><??@@Value></TD>
       </TR>
    #)
    #( '<?NewLine>'
       #define? WISEINST_HTMLRPT_REGTABLE_END
       </TABLE>
       <P><??RptRegCnt> Registry entries.
       </CENTER>
    #)
    
    
    ;--- User can override these SOURCE report definitions to alter look & feel ---
    #( '<?NewLine>'
       #define WISEINST_HTMLRPT_CANT_SHOW_SOURCE
       <P><B>
       Sorry but I can't display the source as the development workstation
       does not have access to the PPWIZARD add-on "HTMLPRE.IH".
       </B>
    #)
    
    ;--- Provides a few "HOOKS" for simple changes, more complex ones need overriding of above macros ---
    #define? WISEINST_HTMLRPT_FOOTER_UNDER_TIME
    #define? WISEINST_HTMLRPT_UNDER_TITLE
    


[Top][Contents][Search][Prev]: The Header File - BSD.WIH[Next]: Creating HTML pages from Windows URL Shortcuts or OS/2 URL Objects

PPWIZARD Manual
My whole website and this manual itself was developed using PPWIZARD (free preprocessor written by Dennis Bareis)
Friday June 01 2001 at 5:58pm