I tried to use your post, but I have an error on InstanceTransformGuid XML Tag. I probably missing something, but what ?
Best regards, CrazyHT Josh Rowe wrote: > > Okay, I've figured out a lot about multiple instance transforms and the > sorts of contortions you have to go through to make them work. I even > figured out how to make a single MSI drive multiple instance transforms > without the need for a bootstrapping program, relying on the fact that the > InstallUISequence executes indepently from the InstallExecuteSequence. > But one thing remains in WiX to make this a lot easier: automatic > GUID-changing of components. In this message, I discuss how to create a > multiple instance transform, how to make a single MSI drive multiple > instance transforms, a common pitfall, and a feature request for WiX. > > I want a user, when they double-click an MSI file, to by default install a > new instance. First, obviously, we will need to define some instance > transforms: > > <Property Id="MYINSTANCE" > Value="DontUseThis" > Secure="yes" > /> > > <InstanceTransforms Property="MYINSTANCE"> > <Instance ProductCode="444e8aa6-c034-4294-b460-07c2d3262f72" > ProductName="Instance 1" > Id="Instance1"/> > <Instance ProductCode="ff0a0580-bc5d-4562-83ec-2edb3511254b" > ProductName="Instance 2" > Id="Instance2"/> > </InstanceTransforms> > > So far, so good. What if the new instance ProductName should be driven by > user selection items? No problem: > > <CustomAction Id="SetProductName" > Property="ProductName" > Value="[[ProductNamePropertyPrefix][MYINSTANCE]]" > /> > > <Property Id="ProductNamePropertyPrefix" > Value="ProductName_" > /> > > <Property Id="ProductName_DefaultInstance" > Value="Multiple Instance Transforms - Default instance" > /> > > <Property Id="ProductName_Instance1" > Value="Multiple Instance Transforms - Instance #1" > /> > > <Property Id="ProductName_Instance2" > Value="Multiple Instance Transforms - Instance #2" > > <InstallExecuteSequence> > <Custom Action="SetProductName" > Before="ValidateProductID"/> > </InstallExecuteSequence> > > Obviously, use whatever algorithm you want in the SetProductName custom > action. You will probably want a different install location, too: > > <Directory Id="INSTALLLOCATION" > Name="TestMultipleInstanceTransformUi"> > <Directory Id="InstanceDirectory"> > </Directory> > </Directory> > > <CustomAction Id="SetInstanceDirectory" > Property="InstanceDirectory" > Value="[INSTALLLOCATION][MYINSTANCE]\"/> > > <InstallExecuteSequence> > <Custom Action="SetInstanceDirectory" > Before="CostFinalize"><![CDATA[InstanceDirectory = > ""]]></Custom> > </InstallExecuteSequence> > > Okay, looking good. Now, the user can specify MSINEWINSTANCE=1 > TRANSFORMS=Instance1 on the msiexec command line to install a new > instance, right? But that seems a little in-depth for users to have to > worry about. For example, how do they know which instance names are > available? How can they reliably choose the next available instance id? > We can obviously do better. It turns out that the MSI system works in two > phases when a UI is presented. First, the InstallUISequence is executed > in the user's space. Second, the InstallExecuteSequence is executed in a > system process. The two sequences act completely independently; the > InstallUISequence's ExecuteAction just passes a set of property names to > the system msiexec service. So, we can make our parent process pass in > the right transform as follows: > > <CustomAction Id="SetTransforms" > Property="TRANSFORMS" > Value="{:[MYINSTANCE];}[TRANSFORMS]" > /> > > <CustomAction Id="SetMsiNewInstance" > Property="MSINEWINSTANCE" > Value="1"/> > > <InstallUISequence> > <Custom Action="SetTransforms" > Before="ExecuteAction"><![CDATA[ACTION = > "INSTALL"]]></Custom> > <Custom Action="SetMsiNewInstance" > Before="ExecuteAction"><![CDATA[ACTION = > "INSTALL"]]></Custom> > </InstallUISequence> > > Now we need a reliable way of setting MYINSTANCE. That's pretty simple, > too. We make our install register each instance id during the install, > and look for the first not-yet-registered instance: > > <Property Id="INSTANCE1INSTALLEDPRODUCTCODE"> > <RegistrySearch Id="LookForInstance1InstalledProductCode" > Key="[InstancesKey]\Instance1" > Name="ProductCode" > Root="HKLM" > Type="raw"/> > </Property> > > <Property Id="INSTANCE2INSTALLEDPRODUCTCODE"> > <RegistrySearch Id="LookForInstance2InstalledProductCode" > Key="[InstancesKey]\Instance2" > Name="ProductCode" > Root="HKLM" > Type="raw"/> > </Property> > > <Property Id="InstancesKey" > Value="Software\Manufacturer\TestMultipleInstance" > /> > > Now we have information about each registered instance. (More on actually > getting this registration information into the registry later.) A little > more tricky custom action work sets MYINSTANCE to the first unused > instance id: > > <CustomAction Id="SetMyInstance_Instance1" > Property="MYINSTANCE" > Value="Instance1" > /> > > <CustomAction Id="SetMyInstance_Instance2" > Property="MYINSTANCE" > Value="Instance2" > /> > > <InstallUISequence> > <Custom Action="SetMyInstance_Instance1" > Before="SetTransforms"><![CDATA[ACTION = "INSTALL" AND > MYINSTANCE = "DontUseThis" AND INSTANCE1INSTALLEDPRODUCTCODE = > ""]]></Custom> > <Custom Action="SetMyInstance_Instance2" > After="SetMyInstance_Instance1"><![CDATA[ACTION = "INSTALL" > AND MYINSTANCE = "DontUseThis" AND INSTANCE2INSTALLEDPRODUCTCODE = > ""]]></Custom> > </InstallUISequence> > > Now, when the ACTION = "INSTALL", just before the SetTransforms action is > called that sets the TRANSFORMS property, the MYINSTANCE property will be > set to the value of the first unused instance id. Assuming, that is, that > we actually got the instance information into the registry. This is where > it gets tricky. > > Multiple Instance Transforms don't really work out-of-the-box the way most > people would want to use them. MSI does not uninstall non-file-data for > components that are used by multiple product codes until the final client > product is uninstalled; MSI assumes that non-file data is shared. This > is, of course, bunk, but that's the way it works. If your component GUID > is shared by multiple product installs, then all but the last uninstall > will get an Action: FileAbsent for the shared components, thus not > uninstalling things other than files. So, if you perform multiple > installs of your wonderful multiple-instance transform that includes the > instance id in registry key names and then uninstall them, the registry > keys from all but the last package to be uninstalled will continue to > exist. Ditto for ServiceInstall elements, etc. So, each of your > instances needs a new GUID for each component that contains non-file-data > that must be uninstalled. Further, these components need to be installed > only with that particular instance. One naive way of doing this is to > declare multiple components with conditions on them: > > <Component Id="Registry_Instance1" > Guid="54412340-1f29-44f5-a733-157efb25c8a6"> > <Condition><![CDATA[MYINSTANCE = "Instance1"]]></Condition> > <RegistryKey Root="HKLM" > Key="[InstancesKey]\[MYINSTANCE]" > > > <RegistryValue Id="Presence_Instance1" > Action="write" > Name="ProductCode" > Value="[ProductCode]" > Type="string" > KeyPath="yes" > /> > </RegistryKey> > </Component> > > <Component Id="Registry_Instance2" > Guid="ffe23417-09ba-485f-912b-c063bebbac2a"> > <Condition><![CDATA[MYINSTANCE = "Instance2"]]></Condition> > <RegistryKey Root="HKLM" > Key="[InstancesKey]\[MYINSTANCE]" > > > <RegistryValue Id="Presence_Instance2" > Action="write" > Name="ProductCode" > Value="[ProductCode]" > Type="string" > KeyPath="yes" > /> > </RegistryKey> > </Component> > > That's just for registration data. Also add any ServiceInstall, > ServiceControl, other stuff, etc., and you'll see that this gets out of > hand very rapidly. > > Here is we get to the feature request for WiX. Wouldn't it be nice if the > InstanceTransforms element interacted with the Component element to > produce transformed rows for each component. For example, imagine if you > could specify: > > <Component Id="MyDisparateComponent" > Guid="fa6d4980-8780-4cff-b52c-5c3f57e05f48" > GenerateGuidForInstanceTransform="yes"> > <RegistryKey></RegistryKey> > </Component> > > Since component GUIDs are only referenced in the Component table and > nowhere else (except possibly ComponentSearch, but you have that problem > anyway), there isn't any reason InstanceTransforms shouldn't output rows > to change the GUIDs for those components that contain non-file-data that > the user would like to have uninstalled. This dramatically reduces the > amount of code necessary to go into a multiple instance installer file. > > Feel free to change the mechanism. You want explicit guids? How about: > > <Component Id="MyDisparateComponent" > Guid="fa6d4980-8780-4cff-b52c-5c3f57e05f48"> > <InstanceTransformGuid TransformId="Instance1" > Guid="dd2e906b-0192-43ce-86c2-9e9cec8b1049"/> > <InstanceTransformGuid TransformId="Instance2" > Guid="8a493697-8fdb-455c-a542-5bd4667e8473"/> > </Component> > > I thought a nice deterministic algorithm for computing the next GUID > requested by the GenerateGuidForInstanceTransform attribute would be nice > so that you wouldn't need to maintain this list on each component if you > didn't want to. > > Thoughts? > > jmr > > > ------------------------------------------------------------------------- > This SF.net email is sponsored by the 2008 JavaOne(SM) Conference > Don't miss this year's exciting event. There's still time to save $100. > Use priority code J8TL2D2. > http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone > _______________________________________________ > WiX-users mailing list > WiX-users@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/wix-users > > -- View this message in context: http://n2.nabble.com/Multiple-Instance-Transforms-Walkthrough%2C-Proposed-Simple-Addition-to-WiX-to-Make-Them-Easier-tp708828p3329391.html Sent from the wix-users mailing list archive at Nabble.com. ------------------------------------------------------------------------------ _______________________________________________ WiX-users mailing list WiX-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/wix-users