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]: TryMeWithMultipleMedia.MM[Next]: TryMeUseMergeModule.MM
Have your say! Join the MAKEMSI discussion list or view archive! Suggest improvements. No question too simple or too complex.
\->MAKEMSI Installs...->Samples Installed by MAKEMSI->Samples - Build New MSI/MSM->TryMeUpdateRegistry00-99.MM

TryMeUpdateRegistry00-99.MM

This is one of the MAKEMSI samples which build a new MSI/MSM. This MSI makes use of these "TryMe.MM" files:

  1. TryMe.ver
  2. TryMe.rtf

In some ways this would have been easier and clearer using a DLL or VBSCRIPT custom action, however this demonstrates a pure Windows Installer solution (as a general rule don't use "external" custom actions where standard Windows Installer behaviour will do):

;----------------------------------------------------------------------------
;    MODULE NAME:   TryMeUpdateRegistry00-99.MM
;
;        $Author:   USER "Dennis"  $
;      $Revision:   1.1  $
;          $Date:   25 May 2007 18:01:30  $
;       $Logfile:   C:/DBAREIS/Projects.PVCS/Win32/MakeMsi/TryMeUpdateRegistry00-99.MM.pvcs  $
;
; DESCRIPTION
; ~~~~~~~~~~~
; This example demonstrates a purely Windows Installer mechanism to do something
; that might otherwise require a DLL or VBSCRIPT based custom action.
;
; The requirement is that there is a key which is allowed to have up to 100
; string values whose names are "DATA00" to "DATA99", the install needs to
; find an "empty" (missing) location and place a value there.
;
; I chose to defined 100 components only one of which will ever install.
; The other major option was to define a single component and then use the
; registry value "DATA[USEXX]", however this would require the extra step of
; saving "USEXX" away so that it is available at "repair" time (or preventing
; repair of these values).
;
;
; The main logic is:
;     * For ALL 100 values read the current registry value ("" for missing).
;       The "AppSearch" action performs the search.
;     * Find the lowest numbered location where there is no value.
;       Put value in the "USEXX" property.
;     * Install the component/registry with that number.
;     * If no "gap" found (no component would install) then abort with message.
;
; I chose a single loop 00-99 rather than having multiple loops.
; I have also supplied self descriptive key names to components, registry
; and other resources to make it easier to examine and understand ("desk check")
; the generated code.
;----------------------------------------------------------------------------


;--- Include MAKEMSI support (with my customisations and MSI branding) ------
#define VER_FILENAME.VER  TryMe.Ver      ;;I only want one VER file for all samples! (this line not actually required in "tryme.mm")
#include "ME.MMH"


;--- Define default location where file should install and add files --------
<$DirectoryTree Key="INSTALLDIR" Dir="c:\program files\TryMe (makemsi sample)\<$MAKEMSI_MM_BASENAME>" CHANGE="\" PrimaryFolder="Y">
<$Files "<?InputFile>" DestDir="INSTALLDIR">            ;;Add this ".mm" script


;--- Define Registry where we wish to find a "gap" --------------------------
#define REG_HKEY_DATA      HKLM
#define REG_KEY_DATA       Software\SomePlace
#define REG_00_99_PREFIX   DATA                   ;;SZ values in range DATA00 - DATA99


;--- Look for a registry "hole" ---------------------------------------------
#define COND_GAP_NOT_YET_FOUND     USEXX = ""               ;;A gap not yet found
#define COND_REGISTRY_MISSING      VALUE4_DATA<$@@xx> = ""  ;;The "RegRead" did not find the registry value (or its value is "", can't tell...)
#{  for @@i = 0 to 99                                       ;;For loop (0, 1, 2, ..., 99)
    ;--- Need number in form '00' - '99' ------------------------------------
    #evaluate+ ^@@xx^ ^right('0<??@@i>', 2)^      ;;Gets last (rightmost) 2 bytes of "00" to "099"

    ;--- Read registry value (00-99) to property ("VALUE4_DATAxx") ----------
    #(
        <$RegistryRead
                HKEY=^<$REG_HKEY_DATA>^
                 Key=^<$REG_KEY_DATA>^
                Name=^<$REG_00_99_PREFIX><$@@xx>^
            Property=^VALUE4_DATA<$@@xx>^
             Default=""                           ;;Stop error message when value doen't exist
            >
    #)

    ;--- Set "USEXX" to first hole found (string "00" to "99") --------------
    #(
        <$PropertyCa "USEXX"
                Value="<$@@xx>"
            Condition=^<$COND_GAP_NOT_YET_FOUND> and <$COND_REGISTRY_MISSING>^
                  Seq="AppSearch-"
             SeqTable="InstallUISequence InstallExecuteSequence"
                 Type="FirstSequence"
                  Key="SET_USEXX_TO_<$@@xx>"
        >
    #)

    ;--- Create component for each possble location so we don't need to save property ---
    <$Component Condition=^USEXX = "<$@@xx>"^ "INSTALLS_IFF_GAP_AT_<$@@xx>" Create="Y" Directory_="<$AnyDir>">   ;;Only 1 component (or ZERO if aborting below) will match and therefore install.
    #(
        <$Registry
                  HKEY=^<$REG_HKEY_DATA>^
                   Key=^<$REG_KEY_DATA>^
                  Name=^<$REG_00_99_PREFIX><$@@xx>^
                 Value=^[INSTALLDIR]^                 ;;The value we want to set "DATAXX" to
          MsiFormatted="VALUE"                        ;;The above "Value" parameter contains MSI formatting
               KeyPath="Y"
                RowKey="INSTALLS_IFF_GAP_AT_<$@@xx>"
            >
    #)
    <$/Component>
#}



;--- Abort if no hole found (DATA00 - DATA99 are ALL set) -------------------
#(
   ;--- Test for non-existance of property (INSTALL time only) --------------
   <$AbortIf
       Condition=^USEXX = ""^
         Message=^All registry values at "<$REG_HKEY_DATA>\<$REG_KEY_DATA>\<$REG_00_99_PREFIX>00" to "<$REG_00_99_PREFIX>99" have already been alocated (no gap).^
        SeqTable="InstallUISequence InstallExecuteSequence"
             Seq="AppSearch-"                   ;;Sequence after all the "PropertyCa" commands above
            Type="FirstSequence"
             Key="AbortIfNoGapFound"
   >
#)


Microsoft awarded me an MVP (Most Valuable Professional award) in 2004, 2005, 2006, 2007, 2008 & 2009 for the Windows SDK (Windows Installer) area.Please email me any feedback, additional information or corrections.
See this page online (look for updates)

[Top][Contents][Prev]: TryMeWithMultipleMedia.MM[Next]: TryMeUseMergeModule.MM


MAKEMSI© is (C)opyright Dennis Bareis 2003-2008 (All rights reserved).
Saturday May 28 2022 at 3:11pm
Visit MAKEMSI's Home Page
Microsoft awarded me an MVP (Most Valuable Professional award) in 2004, 2005, 2006, 2007, 2008 & 2009 for the Windows SDK (Windows Installer) area.