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]: TryMeCreate[START]OfMsiFromScratch.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.7  $
;          $Date:   16 Jan 2008 14:37:04  $
;       $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

    ;--- 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 for the Windows SDK (Windows Installer) area.This external link was OK when tested at 23 Aug 2008Please email me any feedback, additional information or corrections.
See this page online (look for updates)

[Top][Contents][Prev]: TryMe.RTF[Next]: TryMeCreate[START]OfMsiFromScratch.MM


MAKEMSI© is (C)opyright Dennis Bareis 2003-2008 (All rights reserved).
Thursday August 28 2008 at 11:28am
Visit MAKEMSI's Home PageThis external link was OK when tested at 13 Aug 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 23 Aug 2008