TryMeAddVersionKeywordAndLaunchCondition.MM |
This is one of the MAKEMSI samples which build a new MSI/MSM. This MSI makes use of these "TryMe.MM" files:
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 "OnlyOn" 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">