\
Tips and Tricks
User Interface Tips
Progress Bar - Move Bar
This code demonstrates how you can move the progress bar during a
lengthy custom action.
While it demonstrates VBSCRIPT, the same details apply to all custom action
types.
Some facts (if you want to end at 100%):
The following demonstrates the basics of moving the progress bar.
<$VbsCa Binary="TestProgressBar.vbs">
;--- Progress Bar Initialization ----------------------------------------
<$VbCaProgressTickFunctions>
<$VbsCaEntry "DoDeferredInstallation">
;--- Define (to this script) the maximum that ProgressTicksUse() can consume ---
#define TICKS_DoDeferredInstallation 10000000
ProgressTicksAdd <$TICKS_DoDeferredInstallation>
;--- Now do some installation stuff ---------------------------------
dim i
for i = 1 to 10
;--- Do something that takes some time... -----------------------
MsgBox "Doing installation stuff #" & i, vbInformation, "DEBUG"
;--- Indicate we have done something (in this case 10% of the work) ---
ProgressTicksUse 1000000
next
;--- Use any left over ----------------------------------------------
ProgressTicksUse -1
<$/VbsCaEntry>
<$VbsCaEntry "AddTicksToWindowsInstaller">
;--- Need an IMMEDIATE CA to add to total tick count ----------------
ProgressTicksAdd <$TICKS_DoDeferredInstallation>
<$/VbsCaEntry>
<$/VbsCa>
<$VbsCaSetup Binary="TestProgressBar.vbs" Entry="AddTicksToWindowsInstaller" Seq="CreateShortcuts-" Condition="<$CONDITION_INSTALL_ONLY>" TYPE="IMMEDIATE">
<$VbsCaSetup Binary="TestProgressBar.vbs" Entry="DoDeferredInstallation" Seq="CreateShortcuts-" Condition="<$CONDITION_INSTALL_ONLY>">
The following shows the supporting code that needs to be included ASAP
after the "VbsCa command.
#define VERSION_VbCaProgressTickFunctions 06.232
#define? PROGRESSTICKS_DEBUG_MAX_MSGBOX 0 ;;Set to max number of dialogs you want to see (or click on!)
#define? PROGRESSTICKS_DEBUG_LOG Y ;;In Verbose and any "text" log
#( '<?NewLine>'
#define VbCaProgressTickFunctions
;--- Set up global variables reuired by Progress code --------------------
dim MaxMsgBoxes : MaxMsgBoxes = <$PROGRESSTICKS_DEBUG_MAX_MSGBOX>
dim TotalProgressTicks : TotalProgressTicks = clng(0)
<?NewLine><?NewLine>
<?NewLine><?NewLine>
;=====================================================================
function AddCommas(Numb)
;=====================================================================
AddCommas = FormatNumber(Numb, 0, True, True)
end function
<?NewLine><?NewLine>
;=====================================================================
sub TicksMsg(ByVal Msg)
;=====================================================================
;--- Output to verbose (and any "text") log -------------------------
err.clear()
#if ['<$PROGRESSTICKS_DEBUG_LOG>' <> 'N']
CaDebug 0, "[\[]PROGRESS TICKS[\]]: " & Msg
#endif
;--- Display message box --------------------------------------------
if MaxMsgBoxes <> 0 then
MaxMsgBoxes = MaxMsgBoxes - 1
MsgBox Msg, vbInformation, "PROGRESS BAR TICKS DIAGNOSTIC"
end if
end sub
<?NewLine><?NewLine>
;=====================================================================
function MsgRc(ByVal MsRc)
;=====================================================================
dim T : T = ""
if err.number <> 0 then
T = vbCRLF & "err.number = 0x" & hex(err.number) & " - " & err.description
end if
if MsRc <> 1 then
T = vbCRLF & "Session.Message RC = " & MsRc & " (expected 1)" & T
end if
if T <> "" then
T = vbCRLF & T
end if
MsgRc = T
end function
<?NewLine><?NewLine>
;=====================================================================
sub ProgressTicksAdd(Ticks2Add)
;=====================================================================
;--- Immediate of deferred? -----------------------------------------
on error resume next
dim Msg
if session.mode(msiRunModeScheduled) then
;--- Deferred ---------------------------------------------------
TotalProgressTicks = clng(TotalProgressTicks + Ticks2Add)
#(
TicksMsg "Setting tick limit only as this is a deferred Custom Action."
& vbCRLF & vbCRLF
& "Added " & AddCommas(Ticks2Add) & ", the new total is " & AddCommas(TotalProgressTicks)
#)
;--- Don't want ActionData messages to change bar ---------------
err.clear()
set oRec = Installer.CreateRecord(3)
oRec.IntegerData(1) = ActionInfo
oRec.IntegerData(2) = 0
oRec.IntegerData(3) = 0
MsgRc = session.message(msiMessageTypeProgress, oRec)
set oRec = Nothing
Msg = MsgRc(MsgRc)
TicksMsg "Preventing ActionInfo from moving bar." & Msg
else
;--- Tell Windows Installer how many ticks the CA will use ------
err.clear()
dim oRec : set oRec = Installer.CreateRecord(3)
oRec.IntegerData(1) = ProgressAddition
oRec.IntegerData(2) = Ticks2Add
oRec.IntegerData(3) = 0
dim MsgRc : MsgRc = session.message(msiMessageTypeProgress, oRec)
set oRec = Nothing
Msg = MsgRc(MsgRc)
TicksMsg "Added " & AddCommas(Ticks2Add) & " ticks to the Windows Installer progress bar as this is an immediate Custom Action." & Msg
end if
;--- Make sure err.number is 0 --------------------------------------
err.clear()
end sub
<?NewLine><?NewLine>
;=====================================================================
sub ProgressTicksUse(ByVal Ticks2Consume)
;=====================================================================
;--- We can't consume more ticks than we have added -----------------
on error resume next
dim Msg
dim UseTicks : UseTicks = Ticks2Consume
if UseTicks = -1 then
;--- Asked to use the rest --------------------------------------
UseTicks = TotalProgressTicks
elseif UseTicks > TotalProgressTicks then
;--- More than we have so just use what we have -----------------
UseTicks = TotalProgressTicks
end if
;--- Remember what we have left -------------------------------------
dim T
if UseTicks < 1 then
;--- No ticks left ----------------------------------------------
if Ticks2Consume = -1 then
T = "all remaining"
else
T = AddCommas(Ticks2Consume)
end if
TicksMsg "Asked to use " & T & " ticks, but none left"
exit sub
end if
TotalProgressTicks = clng(TotalProgressTicks - UseTicks)
;--- Output to progress bar -----------------------------------------
dim oRec : set oRec = Installer.CreateRecord(3)
oRec.IntegerData(1) = ProgressReport
oRec.IntegerData(2) = UseTicks
oRec.IntegerData(3) = 0
dim MsgRc : MsgRc = session.message(msiMessageTypeProgress, oRec)
set oRec = Nothing
Msg = MsgRc(MsgRc)
T = "Used " & AddCommas(UseTicks) & " ticks"
if Ticks2Consume <> UseTicks then
T = T & " (" & AddCommas(Ticks2Consume) & " requested)"
end if
T = T & ", total now " & AddCommas(TotalProgressTicks)
TicksMsg T & Msg
;--- Make sure err.number is 0 --------------------------------------
err.clear()
end sub
#)