The "VbsCa" Command |
This command is used to start the definition (and creation) of a Windows Installer VBSCRIPT based custom action which ends when the /VbsCa command is encountered. The generated script is automatically added into the "Binary" table. You should be aware of the "Norton's Malicious Script Detection" issue.
If you have an existing Windows Scripting Host (WSH) script which you want to use, use the "ExeCa" command to invoke "WSCRIPT.EXE". All parameters will typically be passed on the command line and no logging will take, in my mind good reasons why this should be avoided at nearly all costs.
You will indicate the function entry points (which you will schedule via the VbsCaSetup command) with the VbsCaEntry and /VbsCaEntry commands. You place your code between these two commands. You may define contants and common initialization code above the first use of "VbsCaEntry".
I highly recommend the use of the CaDebug function and will be reluctant to look at any user supplied code which doesn't make use of it to indicate progress and to make the code easier to debug when it fails.
If imbedding within a macro please ensure that the "current" line continuation is "<?NewLine>".
The generated script has these main characteristics:
By default binary vbscripts will be generated via the "FileMake" command, if you find your scripts being "rebuilt" for no obvious reasons (and you care) then you probably forgot to use the "FileMakeIgnore" command to "hide insignificant changes" in your code.
Microsoft actually have some very useful script information and samples at "http://www.microsoft.com/technet/scriptcenter/default.mspx". I have a collection of other useful scripting links at "http://dennisbareis.com/bookmark_developer_windows_scripting_host.htm".
Parameters |
This command takes these parameters:
This command will store the generated script in the "Binary" table under this key. You will refer to this key in a later "VbsCaSetup" command.
MAKEMSI supplies a lot of error checking and routines to binary scripts (see the "custom action functions" section).
The script will be stored under this name and referred to in the later "VbsCaSetup" command to create a type 38 (inline) custom action.
Inline scripts are intended for short (non-deferred) simple scripts and:
Its probable that in some environments an "inline" script may not trigger script alerts which a binary one would (at least with default options) because of the extra processing performed by these by default.
Scripts of both types are syntax checked during MAKEMSI's processing.
The following code can be excluded/included in the generated script:
The defaults for all optional code are indicated by the individual definitions shown here:
;--- Defaults for the "OptCode" parameter ----------------------------------- #define? VBSCA_WANT_VbsCaCadGetValidate Y ;;Want VbsCaCadGetValidate() Y/N? #define? VBSCA_WANT_CaDeleteFile Y ;;Want CaDeleteFile() Y/N? #define? VBSCA_WANT_CaSleep N ;;Want CaSleep() Y/N? - wscript.sleep unavailable in CA!
To override the above defaults, this parameter should be passed one or more space separated specifications, each of which being the name of a piece of code. If preceeded by "-" then you don't want the code included, "+" (or anything else) to include. An error is generated if an unknown option is specified.
If you indicate you don't need some code which you actually need then you will either get an unknown variable or type mismatch error and because Microsoft don't provide any error/location details (variable names, line numbers etc) in their error messages, debugging a missing script will be difficult (and a good reason for using many CaDebug() calls). Have a chat to Microsoft if you don't like this...
It is possible for you to define your own optional code, see:
;--- We need to define all possible values which can be used in for "OptCode" --- #define? VBSCA_OPCODE_LIST_USER_DEFINED ;;List of ";" delimitered user defined routines/keywords (user must also create "VBSCA_WANT_?" definitions like the above) #( ';' #define VBSCA_OPCODE_LIST ;;User shouldn't override this! Here for visibility. ;--- Add MAKEMSI defined to list (also see the required "VBSCA_WANT_?" definitions above) --- CaDeleteFile CaSleep VbsCaCadGetValidate ;--- Add user defined to list ------------------------------------------- <$VBSCA_OPCODE_LIST_USER_DEFINED> #)
If you are having trouble getting your script to work and can't work out why then use "N" for this parameter and get it working that way first before changing back.
The default for this parameter can be set via the DEFAULT_VBSCA_MUST_DEFINE_VBS_VARIABLES macro. This is initially "Y".
The default for this parameter can be set via the DEFAULT_VBSCA_DOCO macro. The initial value for this is "Y".
This can be handy if you are wondering about sequencing (for example is my custom action executing before or after files are installed etc). A message will be displayed pausing installation, you can then use explorer or other tools to examine your computer.
The default for this parameter can be set via the VBSCA_PAUSE macro. This is configured from the macro "SUNDRY_CA_PAUSE" (defaults to "N").
Main "VbsCa" Options |
Please see the "options for commands" section of the manual.
;---------------------------------------------------------------------------- ;--- General Options -------------------------------------------------------- ;---------------------------------------------------------------------------- #define? DEFAULT_VBSCA_MUST_DEFINE_VBS_VARIABLES Y #define? DEFAULT_VBSCA_CAD_DELIMITER ,_, ;;Must be 1-9 characters long (and something your parameters won't contain) #define? VBSCA_CmdLineTrapsHandledByVb true ;;Best way for testing script from command line (given how lame "err" object and its support is) #define? DEFAULT_VBSCA_SEQTABLE InstallExecuteSequence #define? VBSCA_INC_BY_SPACE_COUNT 4 #define? VBSCA_ROW_@VALIDATE NEW ;;See the "@Validate" parameter of the "ROW" command #define? VBSCA_ROW_@VALIDATE_INLINE NEW -Target:STRINGOVERFLOW ;;See the "@Validate" parameter of the "ROW" command (lets allow the script to exceed the columns 255 character width) #define? VBSCA_PAUSE <$SUNDRY_CA_PAUSE> ;;Debug pauses (Y/N) #define? VBSCA_DISABLED <$SUNDRY_DISALLOW_USE_OF_SCRIPT_CUSTOM_ACTIONS> ;;Make non blank to disable (text is error message) #define? VBSCA_DEFAULT_TYPE_ATTRIBUTES ;;For binary based CA #define? VBSCA_DEFAULT_TYPE_ATTRIBUTES_INLINE immediate ;;For inline (in CA table) based CA #define? DEFAULT_VBSCA_DOCO Y ;;"N" = Don't add to doco #define? VBSCA_BINARY_COMMENT This file generated by the "VbsCa" command at <??RxMmLocation> #define? VBSCA_CADEBUG_FORMAT_LINE12 {{[Time]: }}[1] ;;Time only visible in log! MUST include "[1]" #define? VBSCA_CAMSGBOX_PREFIX_ERROR ERROR: [1] ;;Windows Installer message template for ERROR messages #define? VBSCA_CAMSGBOX_PREFIX_INFO ;;Windows Installer message template for INFO messages #define? VBSCA_CAMSGBOX_PREFIX_OTHER ;;Windows Installer message template for "other" messages #define? VBSCA_VBEXP_CURRENT_DATE FormatDateTime(now(), vbShortDate) #define? VBSCA_VBEXP_CURRENT_TIME FormatDateTime(now(), vbLongTime) #define? VBSCA_INLINE_DISABLE_TARGET_VALIDATION String overflow (greater than length permitted in column); Table: CustomAction, Column: Target #define? VBSCA_USE_FILEMAKE_TO_CREATE_BINARY_VBS Y ;;Use old VBS (and date/time) if only "insignificant" differences ;---------------------------------------------------------------------------- ;--- Logging Related -------------------------------------------------------- ;---------------------------------------------------------------------------- #define? VBSCA_LOG_TO_FILE.D Y ;;Logging OK in development #define? VBSCA_LOG_TO_FILE.P N ;;Logging may trigger the dodgy Norton Antivirus, if not issue (or you are doing file IO in any case) then turn on! #define? VBSCA_LOG_TO_FILE <$VBSCA_LOG_TO_FILE.[MMMODE]> #define? VBSCA_LOG_OK_ENVVAR MAKEMSI_LOG ;;Set this environment variable to N to disable logging #define? VBSCA_LOGDIR_ENVVAR MAKEMSI_LOGDIR ;;Set this environment variable to directory for logging #define? VBSCA_LOGDIR_EXP_4_DEFAULT "<??*TEMP>" ;;By default place in user temp directory (can be any VBS expression) #define? VBSCA_LOGDIR_EXP_4_DEFAULT CaGetEnv("TEMP", false) ;;By default place in user temp directory (can be any VBS expression) #define? VBSCA_LOGFILE_BASENAME_PREFIX MAKEMSI_VBSCA- #define? VBSCA_LOGFILE_BASENAME_MIDDLE <$ProdInfo.ProductName>(<$ProductVersion>) #define? VBSCA_LOGFILE_BASENAME_SUFFIX -" & WeekDayName(Weekday(date())) & " ;;Can help to reduce likelyhood that lots of logging will cause truncation #define? VBSCA_LOGFILE_EXTENSION .log #define? VBSCA_LOGFILE_EXP_4_DEFAULT_BASENAME "<$VBSCA_LOGFILE_BASENAME_PREFIX><$VBSCA_LOGFILE_BASENAME_MIDDLE><$VBSCA_LOGFILE_BASENAME_SUFFIX><$VBSCA_LOGFILE_EXTENSION>" ;;Any VB Expression ("BINARY" parameter is passed) #define? VBSCA_LOGFILE_MAX_AGE_IN_DAYS 100 ;;If older than this then whole file removed prior to logging starting (0=Do Nothing) #define? VBSCA_LOGFILE_MAX_SIZE_IN_K 300 ;;If bigger than this many K then shorten (before logging - so log can grow larger than this) #define? VBSCA_LOGFILE_REDUCE_TO_PERCENTAGE 75 ;;If log is too big then reduce it to what percentage of max size? #define? VBSCA_LOG_EXP_4_ADD_2_HEADER ;;Define to hold appropiate calls to "CaDebug" ;---------------------------------------------------------------------------- ;--- Allow overriding of default logging behaviour -------------------------- ;---------------------------------------------------------------------------- #define? VBSCA_DEBUG1 CaDebug 1, ;;Line 1 output goes to line 1, allow redirection, example: CaDebug 0, #define? VBSCA_DEBUG2 CaDebug 2, ;;Line 2 output goes to line 2 #define? VBSCA_DEBUG0 CaDebug 0, ;;Log output goes to log. ;---------------------------------------------------------------------------- ;--- Custom Action conditions ----------------------------------------------- ;---------------------------------------------------------------------------- #define? VBSCA_CONDITION_INSTALL_ONLY <$CONDITION_INSTALL_ONLY> #define? VBSCA_CONDITION_UNINSTALL_ONLY <$CONDITION_UNINSTALL_ONLY>
EXAMPLE - Very Simple INLINE Custom Action to Remove Trailing Backslash |
<$VbsCa Binary="!SimpleVbs"> InstallDir = session.property("INSTALLDIR") InstallDir = left(InstallDir, len(InstallDir)-1) 'MsgBox "DEBUG: The INSTALLDIR without a trailing backslash ===> " & InstallDir session.property("DIR_NO_SLASH") = InstallDir ;;You will see this action logged in any verbose log <$/VbsCa> <$VbsCaSetup Binary="!SimpleVbs" Seq="CostFinalize-" SeqTable="InstallExecuteSequence" CONDITION=^<$CONDITION_INSTALL_ONLY>^>
EXAMPLE - Simple IMMEDIATE Custom Action |
;--- Simple immediate CA ---------------------------------------------------- <$VbsCa Binary="ImmediateExample.vbs"> <$VbsCaEntry "EntryPoint"> dim Version : Version = session.property("ProductVersion") session.property("CREATE_NEW_PROPERTY") = "This product is version " & Version ;;Should see in "verbose" install log <$/VbsCaEntry> <$/VbsCa> ;--- Schedule it ------------------------------------------------------------ <$VbsCaSetup Binary="ImmediateExample.vbs" Entry="EntryPoint" Seq="<-LaunchConditions" CONDITION="<$CONDITION_INSTALL_ONLY>" Type="immediate FirstSequence" SeqTable="InstallUISequence InstallExecuteSequence">
See the "Remove Trailing Slashes from Directory Names" tip for some other languages.
EXAMPLE - DEFERRED - With CustomActionData |
;--- Set up the 2 parameters (CustomActionData) ----------------------------- #data "Fred" "Name1" 'Name 1 Value' ;;Parameter 1 (name + value) "Name2" "[INSTALLDIR]" ;;Parameter 2 #data ;--- Deferred Custom Action which accesses 2 passed parameters -------------- <$VbsCa Binary="TestCustomActionDataPassing.vbs" DATA="Fred"> <$VbsCaEntry "Install"> ;--- Do something ---------------------------------------------------- Show("Install: NAME1=" & VbsCaCadGet("Name1")) Show("Install: NAME2=" & VbsCaCadGet("Name2")) <$/VbsCaEntry> '======================= sub Show(Text) '======================= CaMsgBox "I", Text end sub <$/VbsCa> ;--- Set up the Deferred custom action passing the CustomActionData --------- <$VbsCaSetup Data="Fred" Binary="TestCustomActionDataPassing.vbs" Entry="Install" Seq="InstallFiles-" CONDITION=^<$CONDITION_INSTALL_ONLY>^>
EXAMPLE |
;--- Create a VBSCRIPT and add to the binary table -------------------------- #( '<?NewLine>' #define InstallationOnTrap ;--- This code must be called to "clean up" after failed install --------- 'clean up code statement 1 'clean up code statement 2 'clean up code statement 3 #) <$VbsCa Binary="TEST.vbs"> <$VbsCaEntry "Install" OnTrap="<$InstallationOnTrap>"> ;--- Do something ---------------------------------------------------- UserFunction("Called during Install...") ;--- Set the return code --------------------------------------------- '<$VbsCaEntryName> = 1603 ;;Error Return code <$/VbsCaEntry> <$VbsCaEntry "UnInstall"> ;--- Do something ---------------------------------------------------- UserFunction("Called during UNInstall...") <$/VbsCaEntry> '======================= sub UserFunction(Text) '======================= CaMsgBox "I", Text end sub <$/VbsCa> ;--- Call the above script during install and uninstall --------------------- <$VbsCaSetup Binary="TEST.vbs" Entry="Install" Seq="InstallFiles-" CONDITION=^<$CONDITION_INSTALL_ONLY>^> <$VbsCaSetup Binary="TEST.vbs" Entry="UnInstall" Seq="InstallFiles-" CONDITION=^<$CONDITION_UNINSTALL_ONLY>^>