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]: TryMe.RTF[Next]: TryMeConditionDialogs.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->TryMeAddVersionKeywordAndLaunchCondition.MM

TryMeAddVersionKeywordAndLaunchCondition.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

Please see the "Version File Based Launch Conditions" section for more information.

;----------------------------------------------------------------------------
;    MODULE NAME:   TryMeAddVersionKeywordAndLaunchCondition.MM
;
;        $Author:   USER "Dennis"  $
;      $Revision:   1.8  $
;          $Date:   07 Nov 2008 18:48:00  $
;       $Logfile:   C:/DBAREIS/Projects.PVCS/Win32/MakeMsi/TryMeAddVersionKeywordAndLaunchCondition.MM.pvcs  $
;
; DESCRIPTION
; ~~~~~~~~~~~
; Adds the "ONLY" on keyword to the version file which allows keyword
; specification of launch conditions.
;
; The MAKEMSI documentation "sucks" up some of this code to display the
; following logical (marked) sections of code:
;   * 4MakeMsiDocumentation-OnlyOn-CONFIGURATION
;   * 4MakeMsiDocumentation-OnlyOn-ADDONLYONKEYWORDTOVERANDHTML
;   * 4MakeMsiDocumentation-OnlyOn-CODE
;
; For the purposes of this sample everything is in this file, in "real life"
; nearly all of the following would be placed in a centralised location such
; as my "Dennis.mmh" file.
;----------------------------------------------------------------------------


;--- For this sample configuration -------------------
#define ONLYON_ALWAYS_OK_CONDITION                       ;;Never ignore the "OnlyOn" conditions
#define ProdInfo.Default.OnlyOn    WORKSTATION WIN2000+  ;;I wish to reuse "TRYME.VER" so "simulate" use of the "OnlyOn" keyword!



;---[4MakeMsiDocumentation-OnlyOn-CONFIGURATION]----
;----------------------------------------------------------------------------
;--- 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+)
#)
;---[4MakeMsiDocumentation-OnlyOn-CONFIGURATION]----



;---[4MakeMsiDocumentation-OnlyOn-ADDONLYONKEYWORDTOVERANDHTML]----
;----------------------------------------------------------------------------
;--- 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>
#)
;---[4MakeMsiDocumentation-OnlyOn-ADDONLYONKEYWORDTOVERANDHTML]----



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


;---[4MakeMsiDocumentation-OnlyOn-CODE]----
;----------------------------------------------------------------------------
;--- 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
;---[4MakeMsiDocumentation-OnlyOn-CODE]----



;----------------------------------------------------------------------------
;--- Do Stuff ---------------------------------------------------------------
;----------------------------------------------------------------------------
<$DirectoryTree Key="INSTALLDIR" Dir="c:\program files\TryMe (makemsi sample)\<$MAKEMSI_MM_BASENAME>" CHANGE="\" PrimaryFolder="Y">
<$Files "TryMe.*" DestDir="INSTALLDIR">


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]: TryMe.RTF[Next]: TryMeConditionDialogs.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.