Shawny,

I apologize for not seeing this post earlier.  The wix-users list is pretty 
high-traffic.  Unfortunately, I can't follow up completely right now because 
the "whole file" is proprietary to my company.  I am, however, slowly working 
on some stuff which I will be release as open source probably around March.

In the end, I built an extension against Wix 3.0.4102, which allows multiple 
extensions at the compile and bind stages, that implements a custom boolean 
attribute on a component called "instance-transforms:Private" (see usage 
below).  The compiler extension class creates a new table called 
"InstanceTransforms_PrivateComponents", and adds each private component to that 
table.  A binder extension generates Component transform rows using a 
deterministic guid-changing algorithm (the same used internally by WiX for 
generating component guids, based on the UUID generation algorithm) in each 
embedded transform for each row joined from the WixInstanceTransforms table to 
the InstanceTransforms_PrivateComponents table.  This extension replaces the 
proposed WiX change; in WiX < 4102 I would have needed to change WiX, but at 
WiX 4102 it permitted multiple extensions to be loaded simultaneously, thus 
allowing my extension to coexist with other extensions.

I use a loop over a predefined set of instance ids while <?include?>-ing a 
per-instance file to generate the raw data in the .MSI file.  Please note that 
I had to strip some things from these sources so it may not compile.  Then 
other files specify "instance-transforms:Private" when they have private 
non-file data.  The result is an MSI that when installed via the GUI 
automatically installs the next available instance id.

InstanceTransforms.wxi:

<?xml version="1.0" encoding="utf-8"?>
<Include xmlns="http://schemas.microsoft.com/wix/2006/wi";
         xmlns:instance-transforms="http://XXX.com/wix/InstanceTransforms.xsd";>

  <!-- This property contains the instance id.  If its value is
  "Invalid", then this instance should NOT be installed! -->
  <Property Id="InstanceId"
            Value="Invalid"
            />

  <!-- We need some instance transforms.  Twent-five oughtta do it.
  If you add or delete from this list, also add or delete from the
  foreach loop below. -->
  <InstanceTransforms Property="InstanceId">
    <Instance Id="InstanceId01" ProductCode="xxx"/>
    <Instance Id="InstanceId02" ProductCode="xxx"/>
    <Instance Id="InstanceId03" ProductCode="xxx"/>
    <Instance Id="InstanceId04" ProductCode="xxx"/>
    <Instance Id="InstanceId05" ProductCode="xxx"/>
    <Instance Id="InstanceId06" ProductCode="xxx"/>
    <Instance Id="InstanceId07" ProductCode="xxx"/>
    <Instance Id="InstanceId08" ProductCode="xxx"/>
    <Instance Id="InstanceId09" ProductCode=" xxx "/>
    <Instance Id="InstanceId10" ProductCode=" xxx "/>
    <Instance Id="InstanceId11" ProductCode=" xxx "/>
    <Instance Id="InstanceId12" ProductCode=" xxx "/>
    <Instance Id="InstanceId13" ProductCode=" xxx "/>
    <Instance Id="InstanceId14" ProductCode=" xxx "/>
    <Instance Id="InstanceId15" ProductCode=" xxx "/>
    <Instance Id="InstanceId16" ProductCode=" xxx "/>
    <Instance Id="InstanceId17" ProductCode=" xxx "/>
    <Instance Id="InstanceId18" ProductCode=" xxx "/>
    <Instance Id="InstanceId19" ProductCode=" xxx "/>
    <Instance Id="InstanceId20" ProductCode=" xxx "/>
    <Instance Id="InstanceId21" ProductCode=" xxx "/>
    <Instance Id="InstanceId22" ProductCode=" xxx "/>
    <Instance Id="InstanceId23" ProductCode=" xxx "/>
    <Instance Id="InstanceId24" ProductCode=" xxx "/>
    <Instance Id="InstanceId25" ProductCode=" xxx "/>
  </InstanceTransforms>


  <!-- We need a component to represent the installed state of the instance.
  We can later detect the installation state of this component to determine
  whether or not the particular instance exists.
  -->
  <DirectoryRef Id="InstallDirectory">
    <Component Id="InstalledStateMarker"
               Guid="xxx"
               instance-transforms:Private="yes"  <--- This is my addition to 
WiX
             >
      <RegistryValue Id="Registry.InstalledStateMarker"
                     Root="HKLM"
                     Key="[InstallKey]"
                     Name="[InstanceId]"
                     Type="string"
                     Value="[_NAME]"
                   />
    </Component>
  </DirectoryRef>

  <!-- For each instance id, generate custom actions, properties, registry 
searches, etc.,
  for that instance. Doing it this way cuts down on a large amount of 
duplication of code. -->
  <?foreach InstanceId in 
01;02;03;04;05;06;07;08;09;10;11;12;13;14;15;16;17;18;19;20;21;22;23;24;25?>
    <?include DefineInstanceTransform.wxi?>
  <?endforeach?>

  <!-- This custom action sets the MSINEWINSTANCE property if we are 
installing. -->
  <CustomAction Id="SetMsiNewInstance"
                Property="MSINEWINSTANCE"
                Value="1"
                />

  <!-- This custom action sets the TRANSFORMS property to include the instance
  transform.  It must be run after the SetInstanceId01 action
  to guarantee that InstanceId is already set. -->
  <CustomAction Id="SetTransforms"
                Property="TRANSFORMS"
                Value="{:[InstanceId];}[TRANSFORMS]"
                />

  <InstallUISequence>
    <Custom Action="SetMsiNewInstance"
            Before="LaunchConditions">ACTION="INSTALL" AND InstanceId = 
"Invalid"</Custom>
    <Custom Action="SetTransforms"
            After="SetInstanceId01">ACTION="INSTALL" AND MSINEWINSTANCE = 
1</Custom>
  </InstallUISequence>

  <!-- This prevents the install from succeeding on the server side if
  no instance transform has been provided. -->
  <InstallExecuteSequence>
    <LaunchConditions After="AppSearch"/>
  </InstallExecuteSequence>

  <Condition Message="Cannot install non-instance transform version of this 
product.  ACTION: [ACTION] InstanceId: [InstanceId]"><![CDATA[InstanceId <> 
"Invalid"]]></Condition>

</Include>


DefineInstanceTransform.wxi:


<?xml version="1.0" encoding="utf-8"?>
<Include xmlns="http://schemas.microsoft.com/wix/2006/wi";>
  <!-- This file defines all the MSI gunk needed to support a single
  instance transform.

  This .wxi file requires the InstanceId variable to be defined to the
  "00"-formatted value of the instance id to support.  This file is
  included multiple times by InstanceTransforms.wxi to support each
  instance transform. -->

  <!-- Search for this instance's install state. -->
  <Property Id="INSTANCE$(var.InstanceId)INSTALLED">
    <RegistrySearch Id="Instance$(var.InstanceId)Installed"
                    Key="[InstallKey]"
                    Name="InstanceId$(var.InstanceId)"
                    Root="HKLM"
                    Type="raw"
                    />
  </Property>

  <!-- Choose a value of __Before. -->
  <?define __Before = LaunchConditions?>
  <?ifdef PreviousInstanceId?>
    <?define __Before = SetInstanceId$(var.PreviousInstanceId)?>
  <?endif?>

  <?define PreviousInstanceId = $(var.InstanceId)?>

  <!-- Create a custom action to set the InstanceId to this instance id. -->
  <CustomAction Id="SetInstanceId$(var.InstanceId)"
                Property="InstanceId"
                Value="InstanceId$(var.InstanceId)"/>

  <!-- This execute the custom action only if:
  1.  We are installing, as compared to uninstalling, repairing, etc., AND
  2.  The instance id is not installed.

  This results in the InstanceId property containing the value "InstanceId"
  for the smallest instance id that was not installed.
  -->
  <InstallUISequence>
    <Custom Action="SetInstanceId$(var.InstanceId)"
            Before="$(var.__Before)"><![CDATA[ACTION="INSTALL" AND NOT 
(INSTANCE$(var.InstanceId)INSTALLED)]]></Custom>
  </InstallUISequence>

</Include>

-----Original Message-----
From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of shawny
Sent: Tuesday, September 16, 2008 11:17 AM
To: wix-users@lists.sourceforge.net
Subject: Re: [WiX-users] Multiple Instance Transforms Walkthrough, Proposed 
Simple Addition to WiX to Make Them Easier


This is great and exactly along the lines of what I'm trying to do.  Can you
post the whole wix file?  And how have you approached the instance issue in
respect to having to declare MyInstance1, MyInstance2, etc in the project?
Is there a way to dynamically generate that?


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
WiX-users mailing list
WiX-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/wix-users

Reply via email to