The "Schedule" Command |
This command is not related to the scheduling of custom actions but is used to begin the specification of a task schedule which ends with the /Schedule command. Between these two commands is most of the "JT.EXE" or "SCHTASKS.EXE" command line used to create a schedule.
See the appropriate commands documentation for more information but don't use any switches that set the schedules name as this is done by this command!
Near the end of the MSI build a single custom action script is generated which contains the install and uninstall code for all specified schedules (although each task schedule is scheduled separately in the MSI).
See the "Schedule Tips" section for more information including problem solving.
Also have a look at "TryMeTemplate-SimpleSchedule.MM" for an example of creating a simple single schedule msi.
This command takes these parameters:
All characters used must be valid in a normal Windows filename or the install will fail.
The passed filename would frequently include msi formatting to point to the installed tool but it also goes through "VbsCaCadReplace()" processing.
If the name does not include a path then its existance is not validated and its assumed to be able to be found in the "PATH" directories (note that the SYSTEM account will have a very small "PATH"). It is best to install it along with your package as the tools are not large (if I'd suggest that it be installed in a directory which is not to be included in any search "PATH" or at least given a more unique filename).
WinNT seems to generate weird "permission denied" errors on longer command lines (about 500 chars?) so it is advisable to use the "@ file" mechanism to shorten it (see schedule options).
The Task name or command line parameters will be able to refer to any of the parameters you supply in the #data structure specified here.
Normal msi formatting takes place on both the name and value columns of the #data.
You must not supply a blank value (use "1" for "always"), also any condition you supply here is on top of any defined by the "SCHEDULE_INSTALL_MIN_CONDITION" and "SCHEDULE_UNINSTALL_MIN_CONDITION" definitions.
If the "calculation" was very simple (for example scriptless) then you might use RegistryRead or similar commands to obtain environmental information and possibly "PropertyCa" to set a propery you pass in the "data" parameters structure. This parameter allows for more complex manipulations without the need for a separate custom action.
This parameter allows to examine the workstations environment (perhaps its registry) to adjust schedule triggers etc. If you use this parameter you should supply the name of a macro, this macro should contain a VBSCRIPT function of the same name (and may also contain other functions and subroutines it requires).
The function should return the modified command line and is passed the original command line. You should not vary the macro's contents for multiple schedules as all schedules are processed by a single VBSCRIPT based custom action.
The command line is passed through the "VbsCaCadReplace()" function to replace any symbols you may have passed in #data structures. MSI formatting does not take place.
By default the symbol name's start is marked by "(*" and end with "*)". The symbol is case sensitive and must have been supplied in #data specified with the "DATA" parameter.
Windows does not have any decent command line processing so it can be difficult to enter command lines etc that require double quotes (I have certainly had this issue with "JT.EXE"), for this reason it is probably not a bad idea to keep things simple and either use 8.3 filenames and/or execute a batch file which does all the work (the batch file contains all the tricky quoting or other manipulations). I recommend the output be $LinkTo ID=^Logging Whole Batch File Execution^ Text="redirected/logged"> as a debugging aid.
Main Schedule Related Options |
Please see the "options for commands" section of the manual.
#define? SCHEDULE_JT_USE_TMPFILE_TO_SHORTEN_CMDLINE_INSTALL N ;;Use "@ file" mechanism for JT.EXE installs? (shortens command line - Good for WinNT) #define? SCHEDULE_JT_DEBUG_SWITCHES_INSTALL /PJ ;;Dump schedule with triggers so it appears in the logs #define? SCHEDULE_BINARY_KEY Installs_<??@@ScheduleCnt>_Schedules ;;Name of the Binary table entry holding the schedule VBS #define? SCHEDULE_INSTALL_SEQ StartServices-RegisterUser ;;After files installed! #define? SCHEDULE_UNINSTALL_SEQ ProcessComponents-RemoveDuplicateFiles ;;Before files removed! #define? SCHEDULE_INSTALL_MIN_CONDITION VersionNT and (<$CONDITION_EXCEPT_UNINSTALL>) ;;Use "1" to disable, this PLUS any condition your supply must be met #define? SCHEDULE_UNINSTALL_MIN_CONDITION VersionNT and (<$CONDITION_UNINSTALL_ONLY>) ;;Use "1" to disable, this PLUS any condition your supply must be met #define? SCHEDULE_CAD_SYMBOL_START (* ;;(*CadSymbolName*) - Start #define? SCHEDULE_CAD_SYMBOL_END *) ;;(*CadSymbolName*) - End #define? SCHEDULE_CREATION_IS_CRITICAL Y ;;Schedule creation command must succeed for install to succeed? You'd generally leave this value alone...
EXAMPLE - USING JT.EXE |
Note that "%COMSPEC%" environment variable reference in the following example is expanded by the target boxes command process when the scheduling tool is executed.
;---------------------------------------------------------------------------- ;--- Create INSTALLDIR ------------------------------------------------------ ;---------------------------------------------------------------------------- <$DirectoryTree Key="INSTALLDIR" Dir="c:\program files\TryMe (makemsi sample)\<$MAKEMSI_MM_BASENAME>" CHANGE="\" PrimaryFolder="Y"> ;---------------------------------------------------------------------------------------------- ;--- Our schedules will be created by JT.EXE (so unless already on box we must install it!) --- ;---------------------------------------------------------------------------------------------- <$Files "jt.exe" DestDir="INSTALLDIR"> ;-------------------------------------------------------------------------------------------------------------- ;--- Any information that can't be hard coded (install directory etc) must be passed to the schedule script --- ;-------------------------------------------------------------------------------------------------------------- #data "CAD_SCHEDULE" "INSTALLDIR" "[INSTALLDIR]" ;;Want to know the installation directory "Schedule1Comment" "Runs simple CMD.EXE task" ;;Comment for schedule #1/2 "Schedule2Comment" "Runs VBS (logs progress)" ;;Comment for schedule #2/2 #data ;---------------------------------------------------------------------------- ;--- Create Schedule #1: A simple "silly" schedule -------------------------- ;---------------------------------------------------------------------------- <$Schedule "SillySchedule1 - (*Schedule1Comment*)" DATA="CAD_SCHEDULE" JT.EXE=^[INSTALLDIR]JT.EXE^> ;--- Task Information ---------------------------------------------------- /SJ WorkingDirectory = "(*INSTALLDIR*)" ApplicationName = "%COMSPEC%" Parameters = "/C echo %DATE% %TIME%: SillySchedule1 says hello... >> \SillySchedule1.log 2>&1" Comment = "This is a comment for the schedule (INSTALLDIR = '(*INSTALLDIR*)')" MaxRunTime = 3600000 ;;1 hour in milliseconds KillIfGoingOnBatteries = 0 SystemRequired = 1 ;--- Create a trigger (you can create more than one) --------------------- /CTJ Type = Weekly TypeArguments = 1,.M.W.F. ;;Every Monday, Wenesday and Friday StartTime = 06:00 ;;6:00am MinutesDuration = 600 ;;For 10 hours MinutesInterval = 60 ;;Repeated every one hour HasEndDate = 0 ;;Never Ends EndDate = 00/00/0000 KillAtDuration = 1 ;;Terminate if still running (after "MinutesDuration") Disabled = 0 ;;Not Disabled ;--- Security Info (use system account) ---------------------------------- /SC "" NULL <$/Schedule>
The above was an extract from the sample file "TryMeTaskSchedules.MM".
EXAMPLE - USING SCHTASKS.EXE |
The following example installs "SCHTASKS.EXE". As Windows XP already has this file as you may guess this file would be patched to support Windows 2000 and the target platform is Windows 2000+.
;--- We will include "SCHTASKS.EXE" (required by "SCHEDULE" command) -------- <$Files "schtasks.exe" DestDir="INSTALLDIR"> ;;This assumes target platform may include WIN2000... ;--- Define some data we need ----------------------------------------------- #data "CAD_SCHEDULE" "INSTALLDIR" "[INSTALLDIR]" ;;Want to know the installation directory (could use "FileFind" on WINXP boxes...) "Fred" "FredsValue" ;;We will refer to this in the schedule name #data ;--- Define a "silly" schedule ---------------------------------------------- <$Schedule "SillyScheduleBuiltWithSCHTASKS - <$ProdInfo.ProductName> - (*Fred*)" DATA="CAD_SCHEDULE" SCHTASKS.EXE=^[INSTALLDIR]SchTasks.EXE^> /SC WEEKLY ;;Weekly /MO 1 ;;Every week /D "MON WED FRI" ;;Run on these days of the week /TR "%COMSPEC% /C echo %DATE% %TIME%: SillyScheduleBuiltWithSCHTASKS >> c:\SillyScheduleBuiltWithSCHTASKS.log 2>&1" /ST 06:00:00 ;;At 6am /RU system ;;Run under system account <$/Schedule>
EXAMPLE - TWEAK |
The following is an incomplete example demonstrating the use of the "TweakFunction" parameter:
#( '<?NewLine>' #define TriggerTime ;;Must contain function of the same name function TriggerTime(ClBefore) ;--- Work out what time we want to trigger the schedule ------------- dim TheTime : TheTime = "07:11" ;--- Now change the value we have "marked" -------------------------- dim Marker : Marker = "{TriggerTime}" if instr(ClBefore, Marker) = 0 then ;--- Our correct usage validation failed ------------------------ VbsCaRaiseError "TriggerTime()", "The defined schedule command line did not contain the marker text """ & Marker & """, its value was: " & ClBefore end if TriggerTime = replace(ClBefore, Marker, TheTime) end function #) <$Schedule "SomeSchedule" TweakFunction="TriggerTime" DATA="CAD_SCHEDULE" JT.EXE=^[INSTALLDIR]JT.EXE^> ;--- Task Information ---------------------------------------------------- /SJ ... ;--- Create a trigger ---------------------------------------------------- /CTJ ... StartTime = {TriggerTime} ;;Value determined at install time ... <$/Schedule>
Note that I kept my function simple in the above but I'd normally make good use of "CaDebug()" and other functions to make it easier to detect problems.