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

Reply via email to