FixMergeModules.MM |
This shows the manipulation of an existing MSM (merge module) to fix some badly written Visual Studio .NET merge modules which amongst other issues refer to "TARGETDIR" in the "Component" table.
This typically causes some or all files to be installed into a root (usually "C:\") and the location can't be redirected.
Do MS test their merge modules? They certainly don't fix them or run them through their own validation suites... Years later still not fixed, just some vague promise, amazing...
This script will create a new "Directory" table entry and update any direct "TARGETDIR" references to refer to this new directory. After the fix the "DIR" parameter of the "MergeModule" command will work (as will "ORCA" etc).
;---------------------------------------------------------------------------- ; ; MODULE NAME: FixMergeModules.mm ; ; $Author: USER "Dennis" $ ; $Revision: 1.2 $ ; $Date: 01 Nov 2006 17:38:04 $ ; $Logfile: C:/DBAREIS/Projects.PVCS/Win32/MakeMsi/FixMergeModules.mm.pvcs $ ; COPYRIGHT: (C)opyright Dennis Bareis, Australia, 2003 ; All rights reserved. ; ; DESCRIPTION ; ~~~~~~~~~~~ ; This sample shows how some badly written VS .net modules can be fixed. ; ; The bug in this case is that "Component" table entries reference ; "TARGETDIR" which resulting in a merge module where files typically ; install into the root directory (C:\) and can't be redirected. ; The rule being broken is: ; ; Merge module tables other than the Directory table must ; not directly reference directory locations to TARGETDIR. ; The location of such a reference changes if the value ; of TARGETDIR is changed by the user ; ; This code creates a new Directory key with a random name and updates ; and "Component" tables entries that specify "TARGETDIR" to use the new ; directory entry. ; ; The code will report an error if at least one entry wasn't ; fixed (@OK='? >= 1'). ;---------------------------------------------------------------------------- ;---------------------------------------------------------------------------- ;--- Name must be passed from command line using "/Define:" switch... --- ;---------------------------------------------------------------------------- ;#define MSM TestMergeModule.msm #ifndef MSM #error ^You should have passed the name of the merge module to be fixed on the command line!^ #elseif ;--- User passed value (on command line) -------------------------------- #define MsmBefore <$Msm> #define? MsmAfter Fixed\<$Msm $$FilePart:name> ;;Put into "Fixed" directory (by default, let user override) #endif ;---------------------------------------------------------------------------- ;--- Load MAKEMSI support --------------------------------------------------- ;---------------------------------------------------------------------------- #define VALID_ValidateTheGeneratedMsi ;;Don't validate (do nothing) #include "OpenMsi.MMH" ;---------------------------------------------------------------------------- ;--- Generate a random Key -------------------------------------------------- ;---------------------------------------------------------------------------- #DefineRexx '' @@RandomDirKey = "TARGETDIR_FIX_" || random(1,99999); #DefineRexx ;---------------------------------------------------------------------------- ;--- Copy .MSM and Fix the Copy --------------------------------------------- ;---------------------------------------------------------------------------- <$Msi "<$MsmAfter>" Template="<$MsmBefore>"> ;--- Set up the directory entry which will replace "TARGETDIR" references --- <$Directory Key="<??@@RandomDirKey>" Parent="TARGETDIR" DIR="{.:Ignored}"> ;--- Update Component table ---------------------------------------------- <$Table "Component"> #( ;--- No componnet should reference "TARGETDIR" (replace with our new key) --- <$Row @Where="Directory_ = 'TARGETDIR'" ;;Look for entries which incorrectly refer to "TARGETDIR" @OK='? >= 1' ;;We will abort with error if we don't find at least one incorrect entry Directory_="<??@@RandomDirKey>" ;;Fix all found entries by pointing to our new directory entry > #) <$/Table> <$/Msi>