MAKEMSI quickly and reliably creates MSI files in a non-programmatic way
Have your say! Join the MAKEMSI discussion list or view archive! Suggest improvements. No question too simple or too complex.
[Bottom][Contents][Prev]: ME.MMH[Next]: Environment Variables (MAKEMSI Configuration)
Have your say! Join the MAKEMSI discussion list or view archive! Suggest improvements. No question too simple or too complex.
\->Source Code->Configuration / Options->Configuration Header Files->DENNIS.MMH

DENNIS.MMH

This is my "personal configuration file" which is doubling as an example of how you can and should configure the "Preferred MSI Interface for Building a Complete MSI".

Please see "ME.MMH" for a simpler example.

It is supplied as an example but please don't use it's contents as is (and rename it to "JohnSmith.mmh" or something more appropriate).

;----------------------------------------------------------------------------
;
;    MODULE NAME:   DENNIS.MMH
;
;        $Author:   USER "Dennis"  $
;      $Revision:   1.47  $
;          $Date:   28 Aug 2008 11:26:14  $
;       $Logfile:   C:/DBAREIS/Projects.PVCS/Win32/MakeMsi/DENNIS.mmh.pvcs  $
;
; Used by Dennis Bareis (me) to customise "DEPT.MMH" and "COMPANY.MMH" as well
; as to define common macros that I'll want to use in many packages.
;
; SEE "ME.MMH" for a much simpler and easier to understand example.
;
; #################################################################
; #### DO NOT USE FOR YOUR OWN MSIs (contains my branding etc) ####
; #################################################################
;
; This file serves two distinct purposes, it is used by me to build my MSIs
; as mentioned above but its secondary purpose is an an example file for
; MAKEMSI customisation.
; You should create a file similar to this one, in general I don't recommend
; using any of my MAKEMSI header files directly.
;
; There are hundreds of configurable options available this file only contains
; a fraction, the reason for this is probably obvious, I made te defaults
; how I thought they should be! If you need to change a MAKEMSI supplied file
; because you can't configure something let me know and I will try to solve the
; issue.
;
; Note that where I use a "#define?" I am specifically allowing and expecting
; that at times individual scripts may override this value.
; If a value shouldn't be overriden then the "#define" command should be
; used instead.
;
; Note that in this header I define platforms based on operating systems, in
; a company where the MSI is intended for internal deployment the platforms
; may be more like "BRANCH_SERVER" and "BRANCH_WORKSTATION".
;----------------------------------------------------------------------------


;----------------------------------------------------------------------------
;--- This header is not only for me but a SAMPLE distributed with MAKEMSI ---
;----------------------------------------------------------------------------
#if ['<??*COMPUTERNAME?>' = 'CN-DENNIS-9400']
    ;--- Running at home on my personal computer ----------------------------
    #define THIS_COMPUTER_IS_MINE   Y
#elseif
    ;--- Not my computer (so not me!) ---------------------------------------
    #define THIS_COMPUTER_IS_MINE   N
#endif


;----------------------------------------------------------------------------
;--- Set up some branding options -------------------------------------------
;----------------------------------------------------------------------------
#define? DEPT_NAME                       Dennis Bareis              ;;My name
#define? DEPT_ADDRESS                    Australia                  ;;Full address (45 Xyz Drive<$CRLF>SomePlace, 1234<$CRLF>Australia etc)
#define? COMPANY_CONTACT_NAME            <$DEPT_NAME>               ;;My name
#define? COMPANY_CONTACT_NAME_PHONE                                 ;;My phone contact (don't even think about it :-)
#define? DEPT_ARP_URL_PUBLISHER          <?PpwizardAuthorHomePage>  ;;My main web page
#define? DEPT_ARP_URL_TECHNICAL_SUPPORT  <?PpwizardAuthorHomePage>  ;;Default to my web site (root)


;----------------------------------------------------------------------------
;--- Set up sundry MAKEMSI options ------------------------------------------
;----------------------------------------------------------------------------
#define? DBG_ALL                             Y                          ;;Add MAKEMSI debugging to "console file"
#define? DEFAULT_FILE_WANT_FILEHASH          Y                          ;;My box can generate MD5 hashes!
#define? COMPANY_PREPROCESS_LICENCE_FILE     Y                          ;;Default is to preprocess licence files
#define? MERGEMOD_DLL_ACCEPTABLE_VERSIONS    "2.1"                      ;;Only want to accept "Msm.Merge2.1"
#if ['<$THIS_COMPUTER_IS_MINE>' = 'N']
    ;--- Other people shouldn't really be using my headaer but if so make if less likely to fail ---
    #define? COMMONFRAMEWORK_ZIP_SOURCE_FOR_BACKUP     N
#endif


;----------------------------------------------------------------------------
;--- I want to "mark" my development MSIs -----------------------------------
;----------------------------------------------------------------------------
#define? COMPANY_MSINAME_SUFFIX.D        (test)
#define? COMPANY_MSINAME_SUFFIX.P
#define? COMPANY_MSINAME_SUFFIX          <$COMPANY_MSINAME_SUFFIX.[MMMODE]>  ;;Adds "(test)" in development mode
#define? COMPANY_PRODUCT_NAME_PREFIX.D   !!!                                 ;;Developer friendy - sorts up front in ARP (in development mode)


;----------------------------------------------------------------------------
;--- Some options more as examples than anything else (sets to defaults anyway) ---
;----------------------------------------------------------------------------
#define? MAKEMSI_HTML_EXTENSION                      hta        ;;Default extension (HTML Application - gets around WINXP SP2 issue)
#define? SELFREG_ORDERED_KEY_PREFIX_REGISTRATION     SelfRegOrd.R.
#define? SELFREG_ORDERED_KEY_PREFIX_UNREGISTRATION   SelfRegOrd.U.

;--- IE Automation works well on my machine (well my retry code gets well used...) ---
#define? MSI_HTML2TEXT_FUNCTION_USES_IE_AUTOMATION   Y


;----------------------------------------------------------------------------
;--- The Graphics I want to use (at least by default) -----------------------
;----------------------------------------------------------------------------
#if ['<$THIS_COMPUTER_IS_MINE>' = 'Y']
    ;--- I don't want others to use my branding! ----------------------------
    #define? UISAMPLE_DIALOG_FILE_dlgbmp     LeftSide-Dennis.bmp   ;;My replacement graphic for the left hand side (vertical) bitmap
    #define? UISAMPLE_LEFTSIDE_TEXT                                ;;Disable "left side text"
    #define? UISAMPLE_BITMAP_WHITE_BANNER    PrettyBanner.bmp     ;;Use "white.bmp" if you just want it plain
    #define? UISAMPLE_BITMAP_BANNER_GRAPHIC  Aust_DB.bmp          ;;The graphic on the right of the "UISAMPLE_BITMAP_WHITE_BANNER"
    #define? COMPANY_PRODUCT_ICON            Aust_DB.ico          ;;Add-Remove (control panel) icon
#endif


;----------------------------------------------------------------------------
;--- Define the types of boxes that I support -------------------------------
;----------------------------------------------------------------------------
#(
    ;--- The VER file will refer to one or more of these platforms or groups ---
    #define COMPANY_DEFINE_DEPARTMENTS_PLATFORMS

   ;--- WINXP ---------------------------------------------------------------
   #define  PD_WINXP  Windows\XP
   <$Platform "WINDOWS_XP_SERVER" DESC=^Windows XP Server^ PLATDIR="<$PD_WINXP>\Servers">
   <$Platform "WINDOWS_XP_PRO"    DESC=^Windows XP PRO^    PLATDIR="<$PD_WINXP>\PRO">
   #(
       <$Platform "WINDOWS_XP"    DESC=^Windows XP (Server/PRO)^
                   Contains="WINDOWS_XP_SERVER WINDOWS_XP_PRO"
       >
   #)

   ;--- WIN2000 -------------------------------------------------------------
   #define  PD_WIN2000  Windows\2000
   <$Platform "WINDOWS_2000_SERVER" DESC=^Windows 2000 Server^ PLATDIR="<$PD_WIN2000>\Servers">
   <$Platform "WINDOWS_2000_PRO"    DESC=^Windows 2000 PRO^    PLATDIR="<$PD_WIN2000>\PRO">
   #(
       <$Platform "WINDOWS_2000"    DESC=^Windows 2000 (Server/PRO)^
                   Contains="WINDOWS_2000_SERVER WINDOWS_2000_PRO"
       >
   #)

   ;--- Others --------------------------------------------------------------
   <$Platform "WINDOWS_NT4" DESC=^Windows NT 4^ PLATDIR="Windows\NT4">
   <$Platform "WINDOWS_ME"  DESC=^Windows ME^   PLATDIR="Windows\ME">
   <$Platform "WINDOWS_98"  DESC=^Windows 98^   PLATDIR="Windows\98">
   <$Platform "WINDOWS_95"  DESC=^Windows 95^   PLATDIR="Windows\95">

   ;--- A generic one for testing (Maybe it will never be supported) --------
   <$Platform "TEST"       DESC=^Testing (NOT SUPPORTED)^ PLATDIR="Testing-Unsupported">

   ;--- Now create a group for all WINDOWS (groups can contain groups) ------
   #(
       <$Platform "WINDOWS_ALL" DESC=^Any Windows workstations or servers^
                   Contains="WINDOWS_95 WINDOWS_98 WINDOWS_ME WINDOWS_NT4 WINDOWS_2000 WINDOWS_XP"
       >
   #)
#)


;----------------------------------------------------------------------------
;--- I want local build logs & platform logs updated only for production ----
;----------------------------------------------------------------------------
#define? DENNIS_LOCAL_LOG_ROOT <??*APPDATA>\MAKEMSI.LOGS
#(  ';'
    ;--- Local files for Development Mode Build -----------------------------
    #define? DENNIS_MAKEMSI_LOCAL_LOGS_FOR_DEVELOPER_MODE

    <$DENNIS_LOCAL_LOG_ROOT>\ALL.LOG                              ;;Dev+Prod
    <$DENNIS_LOCAL_LOG_ROOT>\DEVELOPER.LOG                        ;;Dev Only
    <$DENNIS_LOCAL_LOG_ROOT>\Product\{ProductName}.LOG            ;;Dev+Prod
    <$DENNIS_LOCAL_LOG_ROOT>\Product\Developer\{ProductName}.LOG  ;;Dev Only
#)
#(  ';'
    ;--- Local files for Production Mode Build ------------------------------
    #define? DENNIS_MAKEMSI_LOCAL_LOGS_FOR_PRODUCTION_MODE

    <$DENNIS_LOCAL_LOG_ROOT>\ALL.LOG                              ;;Dev+Prod
    <$DENNIS_LOCAL_LOG_ROOT>\PRODUCTION.LOG                       ;;Prod Only
    <$DENNIS_LOCAL_LOG_ROOT>\Product\{ProductName}.LOG            ;;Dev+Prod
    <$DENNIS_LOCAL_LOG_ROOT>\Product\Production\{ProductName}.LOG ;;Prod Only
#)
#(  ';'
    ;--- Development Build --------------------------------------------------
    #define? PLATFORM_LOG_FILES.D

    ;--- Only local files (don't touch platform logs) -----------------------
    <$DENNIS_MAKEMSI_LOCAL_LOGS_FOR_DEVELOPER_MODE>
#)
#(  ';'
    ;--- Production build ---------------------------------------------------
    #define? PLATFORM_LOG_FILES.P

    ;--- Logs in other directories ------------------------------------------
    <$DENNIS_MAKEMSI_LOCAL_LOGS_FOR_PRODUCTION_MODE>

    ;--- The normal log files in platform directories (prod only) -----------
    <$PLATFORM_DEFAULT_LOG_FILES>
#)
#define? PLATFORM_LOG_FILES <$PLATFORM_LOG_FILES.[MmMode]>


;---[ReadMeMacros4MakemsiDoco]----
;----------------------------------------------------------------------------
;--- ReadMe Macros (creates and adds readme.txt to current component) -------
;----------------------------------------------------------------------------
#(
    ;--- Define README start macro ------------------------------------------
    #define ReadMe

    ;--- Open the output file (following lines placed in the file) ----------
    #define+ @@ReadmeName  <$MAKEMSI_OUT_LOG_DIR_RELATIVE>\ReadmeFiles\Readme-<$Component?>.TXT  ;;Only once per-component!
    #define+ @@IsKeyFile   {$KeyFile=^N^}
    <$FileMake "<$@@ReadmeName>">

    ;--- Want to keep blank lines! ------------------------------------------
    #option  PUSH LeaveBlankLines=ON

    ;--- You add readme text lines between the "<$readme>" and  "<$/readme>" tags ---
#)
#(
    ;--- Define README end macro --------------------------------------------
    #define /ReadMe

    ;--- Restore options to original state ----------------------------------
    #option  POP

    ;--- Close the file -----------------------------------------------------
    <$/FileMake>

    ;--- Add the file to the current component ------------------------------
    <$File Source="<$@@ReadmeName>" Destination="{$Destination=^ReadMe.TXT^}" KEYPATH=^<$@@IsKeyFile>^>
#)
;---[ReadMeMacros4MakemsiDoco]----


#if ['<$THIS_COMPUTER_IS_MINE>' = 'Y']
;---[4Doco-SuspendCpuIntensiveTasks]----
;----------------------------------------------------------------------------
;--- Define list of resource intensive background applications --------------
;----------------------------------------------------------------------------
#( ';'
    #define @@SuspendProcessList
    seti@home.exe                      ;;Little Green Men...
    *_windows_intelx86*                ;;BOINC - All BOINC processes have this naming convention? (not all have ".exe" extension!)
    WCGrid_Rosetta.exe                 ;;Cancer Research etc
    GIANTAntiSpywareMain.exe           ;;Microsoft AniSpyware
    CopernicDesktopSearch.exe          ;;Can interfere with builds
    ud_ligfit_Release.exe              ;;United Devices

    ;--- Not suspending (as this stops explorer etc working while building msi) ---
    ;YahooDesktopSearch.exe             ;;Can interfere with builds (suspending can stop Explorer etc opening)
                                        ;;Commented out if it still hangs until the piece of cr.p
#)


;----------------------------------------------------------------------------
;--- Stop CPU intensive processes as soon as possible -----------------------
;----------------------------------------------------------------------------
;---[4Doco-HookIntoExample]---
#(
    ;--- Code we wish to execute early in build (but after logging locations known) ---
    #define SuspendCpuIntensiveTasks

    ;--- Need to perform latter when the logging directory is known! --------
    #evaluate ^^ ^<$Rexx4SuspendCpuIntensiveTasks>^
#)
#include "HookInto.MMH"             ;;We haven't already included the MAKEMSI headers...
<$HookInto "MAKEMSI_HOOK_ASAP_AFTER_LOG_DIRECTORIES_DEFINED" Before="SuspendCpuIntensiveTasks">
;---[4Doco-HookIntoExample]---
#DefineRexx 'Rexx4SuspendCpuIntensiveTasks'
    ;--- Create logging directory -------------------------------------------
    @@MainDir = '<$MAKEMSI_OTHER_DIR>\SuspendResume'
    @@LogDir = @@MainDir || '\Logs'
    call AddressCmd 'rd "' || @@LogDir  || '" /q /s >nul <$Stderr2Out>'
    call AddressCmd 'rd "' || @@MainDir || '" /q /s >nul <$Stderr2Out>'
    call MakeDirectoryTree @@LogDir;

    ;--- Set up files -------------------------------------------------------
    @@ProcessFile = @@MainDir || '\MatchingProcesses.txt';
    @@SuspendCmd  = @@MainDir || '\Suspend.CMD';     ;;Only for user invokation (if user aborted - may need to be manually executed)
    @@ResumeCmd   = @@MainDir || '\Resume.CMD';      ;;Only for user invokation (if user aborted - may need to be manually executed)
    call FileDelete @@ProcessFile;
    call FileDelete @@SuspendCmd;
    call FileDelete @@ResumeCmd;

    ;--- Initialize "emergency" Batch file (user invoked if required) -------
    @@Batch = "@echo off" || '0A0A'x;
    @@Batch = @@Batch || '@REM ***' || '0A'x;
    @@Batch = @@Batch || '@REM *** Provided for your use (not actually used by MAKEMSI due to AntiSpyware programs)' || '0A'x;
    @@Batch = @@Batch || '@REM ***' || '0A0A'x;
    @@Batch = @@Batch || '@REM *** List of MASKS ***' || '0A'x;

    ;--- Produce a file containing the matching tasks (those running any matching the mask) ---
    call ArraySplit '@@ProcessMasks', '<$@@SuspendProcessList>', ';'
    @@PvExe = "PV.EXE --quiet"
    do  @@i = 1 to @@ProcessMasks.0
        ;--- Add this wilcard process mask to the list ----------------------
        @@PvExe = @@PvExe || ' "' || @@ProcessMasks.@@i || '"';
        @@Batch = @@Batch || "@REM MASK #" || @@i || ': ' || @@ProcessMasks.@@i || '0A'x;
    end
    @@Batch = @@Batch || '0A0A'x;

    ;--- Process matching (running) processes -------------------------------
    address system @@PvExe || ' > "' || @@ProcessFile || '" 2>&1'
    @@ProcessCnt = 0;
    do  while lines(@@ProcessFile) <> 0
        ;--- All lines should have a tab (process name ends with tab) -------
        @@Line   = linein(@@ProcessFile);
        @@TabPos = pos('09'x, @@Line);

        ;--- Now Extract the Name of the process ----------------------------
        if  @@TabPos <> 0 then
        do
            ;--- Looks OK ---------------------------------------------------
            @@ProcessCnt  = @@ProcessCnt + 1;
            @@ProcessName = left(@@Line, @@TabPos-1);

            ;--- Create Batch file resume command ----------------------------
            @@Batch = @@Batch || 'PsSuspend.exe {Action} "' || @@ProcessName || '"' || '0A'x;

            ;--- Add to the Process list ------------------------------------
            @@Process.@@ProcessCnt = @@ProcessName;
        end;
    end;
    call FileClose @@ProcessFile;
    @@Process.0 = @@ProcessCnt;

    ;--- Actually create the batch files ------------------------------------
    @@Batch = ReplaceString(@@Batch, '0A'x, '0D0A'x);
    call FileLineOut @@SuspendCmd, ReplaceString(@@Batch, "{Action} ", "");
    call FileLineOut @@ResumeCmd,  ReplaceString(@@Batch, "{Action}",  "-r");
    call FileClose @@SuspendCmd;
    call FileClose @@ResumeCmd;     ;;We won't actually run the batch files automatically due to SpyWare programs etc...

    ;--- Schedule RESUME at end of PPWIZARD's processing --------------------
    call ScheduleCleanupCode 'ResumeCpuIntensiveTasks';

    ;--- SUSPEND ignoring return codes/failure (but log for debug) ----------
    do  @@i = 1 to @@Process.0
        @@LogFile = @@LogDir || '\Suspending-' || @@Process.@@i || '.log'
        address system 'PsSuspend.EXE "' || @@Process.@@i || '" > "' || @@LogFile || '" 2>&1'
    end
#DefineRexx


;----------------------------------------------------------------------------
;--- This RESUME code was scheduled in the SUSPEND step above ---------------
;----------------------------------------------------------------------------
#DefineRexx 'ResumeCpuIntensiveTasks'       ;;Define "resume" code (not yet executed)
    ;--- RESUME ignoring return codes/failure (but log for debug) -----------
    do  @@i = 1 to @@Process.0
        @@LogFile = @@LogDir || '\Resuming-' || @@Process.@@i || '.log'
        address system 'PsSuspend.EXE -r "' || @@Process.@@i || '" > "' || @@LogFile || '" 2>&1'
    end
#DefineRexx
;---[4Doco-SuspendCpuIntensiveTasks]----
#endif


;---[4Doco-FindWscript.exe]----
;----------------------------------------------------------------------------
;--- Macro to find "WSCRIPT.EXE"
;--- MS stupidly places this file in logically different locations
;--- ("C:\windows" in WIN98). Also just to make it more difficult it is not
;--- possible to search by attribute, or search path and thus not possible
;--- to avoid possible incorrect matches in fixpack backup directories.
;--- All in all nearly a handful of reasons to swear at MS in one go....
;----------------------------------------------------------------------------
#(
    #define WSCRIPT.EXE

    ;--- Can't do this! Can find files in "$NtServicePackUninstall" type directories ---
    ;<$FileFind File="WSCRIPT.EXE" Property="WSCRIPT.EXE" PATH="[WindowsFolder]" Depth="1">   ;;Danger, Danger...

    ;--- Thanks MS... -------------------------------------------------------
    <$FileFind File="WSCRIPT.EXE" Property="WSCRIPT.EXE.WF" PATH="[WindowsFolder]" Depth="0" Default="">
    <$FileFind File="WSCRIPT.EXE" Property="WSCRIPT.EXE.SF" PATH="[SystemFolder]"  Depth="0" Default="">
    <$PropertyCa "WSCRIPT.EXE" Value="[WSCRIPT.EXE.WF]" Seq="AppSearch-" Condition="WSCRIPT.EXE.WF and (<$CONDITION_EXCEPT_UNINSTALL>)" SeqTable="InstallUISequence InstallExecuteSequence">
    <$PropertyCa "WSCRIPT.EXE" Value="[WSCRIPT.EXE.SF]" Seq="AppSearch-" Condition="WSCRIPT.EXE.SF and (<$CONDITION_EXCEPT_UNINSTALL>)" SeqTable="InstallUISequence InstallExecuteSequence">
    <$AbortIf
        Condition="not WSCRIPT.EXE and (<$CONDITION_EXCEPT_UNINSTALL>)"
          Message=^The file "WSCRIPT.EXE" was not found in the "[WindowsFolder]" or "[SystemFolder]" directories!^
         SeqTable="InstallUISequence InstallExecuteSequence"
              Seq="AppSearch-"
    >
#)
;---[4Doco-FindWscript.exe]----

#(
    #define CSCRIPT.EXE

    ;--- Can't do this! Can find files in "$NtServicePackUninstall" type directories ---
    ;<$FileFind File="CSCRIPT.EXE" Property="CSCRIPT.EXE" PATH="[WindowsFolder]" Depth="1">

    ;--- Thanks MS... -------------------------------------------------------
    <$FileFind File="CSCRIPT.EXE" Property="CSCRIPT.EXE.WF" PATH="[WindowsFolder]" Depth="0" Default="">
    <$FileFind File="CSCRIPT.EXE" Property="CSCRIPT.EXE.SF" PATH="[SystemFolder]"  Depth="0" Default="">
    <$PropertyCa "CSCRIPT.EXE" Value="[CSCRIPT.EXE.WF]" Seq="AppSearch-" Condition="CSCRIPT.EXE.WF and (<$CONDITION_EXCEPT_UNINSTALL>)" SeqTable="InstallUISequence InstallExecuteSequence">
    <$PropertyCa "CSCRIPT.EXE" Value="[CSCRIPT.EXE.SF]" Seq="AppSearch-" Condition="CSCRIPT.EXE.SF and (<$CONDITION_EXCEPT_UNINSTALL>)" SeqTable="InstallUISequence InstallExecuteSequence">
    <$AbortIf
        Condition="not CSCRIPT.EXE and (<$CONDITION_EXCEPT_UNINSTALL>)"
          Message=^The file "CSCRIPT.EXE" was not found in the "[WindowsFolder]" or "[SystemFolder]" directories!^
         SeqTable="InstallUISequence InstallExecuteSequence"
              Seq="AppSearch-"
    >
#)


;---[4Doco-DebugWaitMacro]----
;----------------------------------------------------------------------------
;--- Macro for inserting Debug Pauses (ver 06.113) --------------------------
;----------------------------------------------------------------------------
#( '<?NewLine>'
    #define DebugWait

    ;--- Validate parameters and keep count ---------------------------------
    {$!:TEXT,SEQ,SEQTABLE,TYPE,CONDITION}
    #RexxVar RxDebugWaitCnt + 1     ;;Inc Count (need diff binaries as text may/will differ)

    ;--- Don't do anything in production mode! ------------------------------
    #if ['<$MmMode>' = '<$MMMODE_PRODUCTION>']
        ;--- In production mode warn first time -----------------------------
        #if [RxDebugWaitCnt = 1]
            #info ^DebugWait not inserted in production mode!^
        #endif
    #elseif
        ;--- Not Production mode --------------------------------------------
        <$VbsCa Binary="DebugWait_<??RxDebugWaitCnt>.vbs">
           <$VbsCaEntry "MessageBox">
               ;--- Will display whether or not in "silent" mode --------------------
               MsgBox "{$Text=^Waiting...^}" & vbCRLF & vbCRLF & "Defined at <??RxMmLocation>", vbInformation, "DebugWait: <$ProdInfo.ProductName> v<$ProductVersion>"
           <$/VbsCaEntry>
        <$/VbsCa>
        <$VbsCaSetup Binary="DebugWait_<??RxDebugWaitCnt>.vbs" Entry="MessageBox" Seq="{$Seq}" CONDITION=^{$Condition=~<$CONDITION_INSTALL_ONLY>~}^ Type="{$Type=^Deferred^}" SeqTable="{$SeqTable=^InstallExecuteSequence^}">
    #endif
#)
#RexxVar RxDebugWaitCnt = 0         ;;Init count
;---[4Doco-DebugWaitMacro]----


;---[4Doco-DebugCauseFailureMacro]----
;-----------------------------------------------------------------------------
;--- DEBUG MACRO: RollBack (use to abort install/repair/uninstall activity ---
;-----------------------------------------------------------------------------
#( '<?NewLine>'
    #define DebugRollback                   ;;Version 08.241

    ;--- Validate parameters and keep count ---------------------------------
    {$!:SEQ,SEQTABLE,TYPE,CONDITION}
    #RexxVar RxDebugRollBackCnt + 1     ;;Inc Count (need diff binaries as conditions, scheduling may/will differ)

    ;--- Don't do anything in production mode! ------------------------------
    #if ['<$MmMode>' = '<$MMMODE_PRODUCTION>']
        ;--- In production mode warn first time -----------------------------
        #if [RxDebugRollBackCnt = 1]
            #info ^DebugRollback not inserted in production mode!^
        #endif
    #elseif
        ;--- Not Production mode --------------------------------------------
        <$VbsCa Binary="DebugRollback_<??RxDebugRollBackCnt>.vbs">
           <$VbsCaEntry "FailedOnPurpose">
               #(
                    VbsCaRaiseError "FailedOnPurpose()",
                                    "<$DebugCauseFailureMsg>" & vbCRLF &
                                    vbCRLF &
                                    "MSI       : <$ProdInfo.ProductName> v<$ProductVersion> (build <?CompileTime>)"  & vbCRLF &
                                    "Sequenced : {$Seq=^<-InstallFinalize^}  (in {$SeqTable=^InstallExecuteSequence^})"  & vbCRLF &
                                    "Condition : {$Condition=~<$CONDITION_INSTALL_ONLY>~}"  & vbCRLF &
                                    "CA Type   : {$Type=^Deferred^}"  & vbCRLF &
                                    "Defined   : <??RxMmLocation>"
               #)
           <$/VbsCaEntry>
        <$/VbsCa>
        <$VbsCaSetup Binary="DebugRollback_<??RxDebugRollBackCnt>.vbs" Entry="FailedOnPurpose" Seq="{$Seq}" CONDITION=^{$Condition}^ Type="{$Type}" SeqTable="{$SeqTable}">
    #endif
#)
#RexxVar RxDebugRollBackCnt = 0         ;;Init count
#(
    #define? DebugCauseFailureMsg
    We are causing a failure on purpose,
    perhaps to test rollback or because we want to test an install
    over and over again without needing to uninstall all the time!
#)
#define DebugCauseFailure <$DebugRollback {$?}>             ;;Create an alias for the macro.
;---[4Doco-DebugCauseFailureMacro]----







;----------------------------------------------------------------------------
;--- Include MAKEMSI support ------------------------------------------------
;----------------------------------------------------------------------------
#include "DEPT.MMH"


Microsoft awarded me an MVP (Most Valuable Professional award) in 2004, 2005, 2006 & 2007 for the Windows SDK (Windows Installer) area.This external link was OK when tested at 15 Nov 2008Please email me any feedback, additional information or corrections.
See this page online (look for updates)

[Top][Contents][Prev]: ME.MMH[Next]: Environment Variables (MAKEMSI Configuration)


MAKEMSI© is (C)opyright Dennis Bareis 2003-2008 (All rights reserved).
Saturday November 15 2008 at 2:05pm
Visit MAKEMSI's Home PageThis external link was OK when tested at 7 Nov 2008

HTML page dated Mon, 29 Jan 2007 00:11:11 GMT
Microsoft awarded me an MVP (Most Valuable Professional award) in 2004, 2005, 2006 & 2007 for the Windows SDK (Windows Installer) area.This external link was OK when tested at 15 Nov 2008