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]: Upgrade Code Validation[Next]: XML Version File
Have your say! Join the MAKEMSI discussion list or view archive! Suggest improvements. No question too simple or too complex.
\->Source Code->Configuration / Options->Version File Based Launch Conditions

Version File Based Launch Conditions

This shows how you can configure launch conditions so that you can list them by name in a version file (for example you could specify "SERVER IIS WIN2003" if you'd defined the appropriate information).

This is an example of how the keyword could look in the version file if the computer must not be a server and must have Windows 2000 or greater installed:

; ONLYON = WORKSTATION WIN2000+

The "TryMeAddVersionKeywordAndLaunchCondition.MM" sample is the full self contained sample which can be executed to see it in action. The folllowing sections show the relevant fragments of this file as well as some explanations.

All of this code would generally be in a single "configuration" file such as my "DENNIS.MMH" header file.

Configuration

The code allows you to configure the conditions you'd like to be able to specify in the version file, for example you might wish to use "WINXP" if you want to ensure that the installer will only continue on WINXP based computers.

The following properties are associated with each "condition":

  1. Desc
    This is a short description of the test.

    When processing the list of "OnlyOn" parameters the existance of the "Desc" property is used to determine whether the "condition" is valid or not.

  2. Condition
    This is the test condition that the computer must match for this keyword or the install will not continue.

  3. Code
    Your test condition may require some work to set up the information. Your code should be specified here. A blank value indicates no setup is required.

  4. ErrInfo
    This information is only displayed in the resulting error message if the computer doesn't match requirements. This should be blank or contain "debug" text which typically displays property values etc. The string "{NL}" can be used to mark where a newline should occur.

The "OnlyOn" keyword can specify any number of parameters (test) however if more than one then all conditions must match.

Sample configuration follows:

;----------------------------------------------------------------------------
;--- Macro to get box type from Windows Registry ----------------------------
;----------------------------------------------------------------------------
#define? ComputerTypeProperty REGISTRY.PRODUCTTYPE
#(
    #define? ComputerTypeGet     ;;Useful macro (but also see the "MsiNTProductType" property)

    ;--- Only need to generate this code the first time! --------------------
    #ifndef @@ComputerTypeGet.CodeGenerated
        ;--- Get the value form the Windows Registry ------------------------
        <$RegistryRead
             Property="<$ComputerTypeProperty>"
                 HKEY="LOCAL_MACHINE"
                  KEY="SYSTEM\CurrentControlSet\Control\ProductOptions"
                 NAME="ProductType"
        >

        ;--- Flag code generated --------------------------------------------
        #define @@ComputerTypeGet.CodeGenerated
    #endif
#)


;----------------------------------------------------------------------------
;--- Define ONLYON=WORKSTATION ----------------------------------------------
;----------------------------------------------------------------------------
#define ONLYON.WORKSTATION.Desc      Windows Workstation
#define ONLYON.WORKSTATION.Code      <$ComputerTypeGet>
#define ONLYON.WORKSTATION.Condition <$ComputerTypeProperty> ~= "WinNT"
#define ONLYON.WORKSTATION.ErrInfo   <$WindowsTypeErrInfo>
#define? WindowsTypeErrInfo          ComputerType="[<$ComputerTypeProperty>]"


;----------------------------------------------------------------------------
;--- Define ONLYON=SERVER (of any type) -------------------------------------
;----------------------------------------------------------------------------
#define ONLYON.SERVER.Desc           Windows Server
#define ONLYON.SERVER.Code           <$ComputerTypeGet>
#define ONLYON.SERVER.Condition      "ServerNT, LanmanNT" ~>< <$ComputerTypeProperty>
#define ONLYON.SERVER.ErrInfo        <$WindowsTypeErrInfo>


;----------------------------------------------------------------------------
;--- Define ONLYON=WIN2000+ -------------------------------------------------
;----------------------------------------------------------------------------
#define ONLYON.WIN2000+.Desc         Version WIN2000 or newer
#define ONLYON.WIN2000+.Code
#define ONLYON.WIN2000+.Condition    VersionNT and (VersionNT >= 500)
#( '{NL}'
    #define ONLYON.WIN2000+.ErrInfo
    VersionNT=[VersionNT]            ;;Display version (blank if box on Win9x)
    Version9X=[Version9X]            ;;Display version (blank if box on WinNT+)
#)

Define "ONLYON" As a Valid Keyword

This code needs to be placed before version file processing takes place:

;----------------------------------------------------------------------------
;--- Add "OnlyOn" keyword to list of valid ".VER" file keywords -------------
;----------------------------------------------------------------------------
#( ""
    #define COMPANY_PRODINFO_VALID_KEYWORD_LIST_EXTRA
    ,OnlyOn        ;;New keyword starts with and keywords separated with ","
#)
#define? ProdInfo.Default.OnlyOn            ;;Set the keywords default (make it optional)


;----------------------------------------------------------------------------
;--- Add "OnlyOn" info to report's summary ----------------------------------
;----------------------------------------------------------------------------
#(  ''
   #define? HTMLSUMM_AFTER_BUILT_AT
   <TR>
       <TD align="center"<$HTMLSUMM_SUPPORTED_PLATFORMS_TT>>
           Supported<BR>Platforms
       </TD>
       <TD>
           <span<$HTMLSUMM_SUPPORTED_PLATFORMS_TT>>
                <$PLATFORM_MsiSupportedWhereHtml>
           </span>
           <$ONLYON_SUMMARY_TEXT>
       </TD>
   </TR>
   <$COMPANY_HTMLSUMM_AFTER_SUPPORTED_PLATFORMS>
#)

Process the Configured "ONLYON" Keywords Value

This code needs to be placed after version file processing has taken place:

;----------------------------------------------------------------------------
;--- Support Developer box ignoring of any "OnlyOn" checking ----------------
;----------------------------------------------------------------------------
#define? ONLYON_ALWAYS_OK_CONDITION.D  %VCSID <> ""                           ;;If PVCS environment set then its a development box!
#define? ONLYON_ALWAYS_OK_CONDITION.P
#define? ONLYON_ALWAYS_OK_CONDITION    <$ONLYON_ALWAYS_OK_CONDITION.[MMMODE]> ;;Blank or "0" (non-true) means don't ignore


;----------------------------------------------------------------------------
;--- Process "OnlyOn" keywords value ----------------------------------------
;----------------------------------------------------------------------------
#if ['<$ProdInfo.OnlyOn>' <> '']
   ;--- YES, we don't run on just any type of box -----------------------
   #DefineRexx ''
       ;--- Loop through all space separated "keywords" ---------------------
       @@Categories        = '<$ProdInfo.OnlyOn>';
       @@OnlyOnDesc        = ''
       @@OnlyOnCode        = d2c(10);
       @@OnlyOnCondition   = ''
       @@OnlyOnErrInfo     = ''
       @@UnknownCategories = ''
       call Info "Only Installs on: " || @@Categories;
       do while @@Categories <> ''
          ;--- Get next category --------------------------------------------
          parse var @@Categories @@Category @@Categories;

          ;--- Is it valid (previously defined)? ----------------------------
          @@MacBase  = 'ONLYON.' || @@Category || '.'
          if    Defined(@@MacBase || 'Desc') = 'N' then
                @@UnknownCategories = strip(@@UnknownCategories || ' ' || @@Category);
          else
          do
                ;--- Valid keyword, get details -----------------------------
                @@Desc = ReplaceMacros(MacroGet(@@MacBase || 'Desc'));
                if    Defined(@@MacBase || 'Condition') = 'N' then
                    error('The "ONLYON" keyword "' || @@Category || '" is missing a condition definition!');
                else
                    @@Condition = ReplaceMacros(MacroGet(@@MacBase || 'Condition'));

                if    Defined(@@MacBase || 'Code') = 'N' then
                    @@Code = '';
                else
                    @@Code = ReplaceMacros(MacroGet(@@MacBase || 'Code'));
                if    Defined(@@MacBase || 'ErrInfo') = 'N' then
                    @@ErrInfo = '';
                else
                    @@ErrInfo = ReplaceMacros(MacroGet(@@MacBase || 'ErrInfo'));

                ;--- Combine info -------------------------------------------
                if  @@OnlyOnDesc <> '' then
                do
                    ;--- Not the first item (seperator required) ------------
                    @@OnlyOnDesc      = @@OnlyOnDesc       || ' and '
                    @@OnlyOnCondition = @@OnlyOnCondition  || ' and '
                end;
                @@OnlyOnDesc      = @@OnlyOnDesc      || @@Desc;
                @@OnlyOnCondition = @@OnlyOnCondition || '(' || @@Condition || ')';
                if  @@Code <> '' then
                do
                    if  @@OnlyOnCode <> '' then
                        @@OnlyOnCode = @@OnlyOnCode || ' '
                    @@OnlyOnCode     = @@OnlyOnCode || @@Code;
                end;
                if  @@ErrInfo <> '' then
                do
                    if  @@OnlyOnErrInfo <> '' then
                        @@OnlyOnErrInfo = @@OnlyOnErrInfo || '{NL}'
                    @@OnlyOnErrInfo     = @@OnlyOnErrInfo || @@ErrInfo;
                end;
          end;
       end;
       if   @@UnknownCategories <> '' then
            error('The "ONLYON" keyword specified these unknown categories:',, '   ' || @@UnknownCategories);

       ;--- Must restrict the message to 255 characters (MSI schema retriction) ---
       if   length(@@OnlyOnErrInfo) > 255 then
            @@OnlyOnErrInfo = left(@@OnlyOnErrInfo, 252) || '...';

       ;--- We may have a condition which indicates alls OK in any circumstance ---
       @@OkCondition = strip(ReplaceMacros(MacroGet('ONLYON_ALWAYS_OK_CONDITION')));
       if   @@OkCondition <> '' then
       do
            ;--- We do have such a condition (useful for testing etc) -------
            @@OnlyOnCondition = '(' || @@OnlyOnCondition || ') or (' || @@OkCondition || ')'
       end;

       ;--- The condition can't be too long... ------------------------------
       @@FullCondition = 'not (' || @@OnlyOnCondition || ')'; ;;True means OK (we need true to mean NOT OK)
       if   length(@@FullCondition) > 255 then
            error('The ONLYON condition is ' || length(@@FullCondition) || ' bytes long (its limit is 255)!', 'The full condition is:',,@@FullCondition);

       ;--- Bit of a cludge -------------------------------------------------
       @@OnlyOnErrInfo = ReplaceString(@@OnlyOnErrInfo, "{NL}", "<$CRLF>");

       ;--- Want this info in the summary -------------------------------
       @@H =        '<p><b><i>'
       @@H = @@H || '<span title="This MSI has a launch condition (specified by the &quot;OnlyOn&quot; keyword).">'
       @@H = @@H || 'This product will only install on computers of type ' || @@OnlyOnDesc || '!'
       @@H = @@H || '</i></b>'
       if   @@OkCondition <> '' then
            @@H = @@H || '<br><span style="font:xx-small">Note that for testing purposes this launch condition can be removed by ensuring the following condition evaluates to true: ' || @@OkCondition
       @@H = @@H || '</span>'
       call MacroSet "ONLYON_SUMMARY_TEXT", @@H
   #DefineRexx

   ;--- Generate any required code (to set up for "Condition") --------------
   <??@@OnlyOnCode>

   ;--- Now perform the validation ------------------------------------------
   #(
       <$AbortIf
             Condition=^<??@@FullCondition>^
               Message=^We can't install <$ProdInfo.ProductName> as this computer is not <??@@OnlyOnDesc><$Crlf><$Crlf><$Crlf><??@@OnlyOnErrInfo>^
                   Seq="AppSearch-"
              SeqTable="InstallUISequence InstallExecuteSequence"
                   Key="TestOnlyOnConditionDieOnFailure"
       >
   #)
#endif
#define? ONLYON_SUMMARY_TEXT      ;;If not set above make empty


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]: Upgrade Code Validation[Next]: XML Version File


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.