My Wix Journey - Day 6 @ 11:43pm EDT

As promised, here is my article:

"How To extract InstallShield Dialogs from an MSI"


First, we need our installation generated from a properly licenced copy of InstallShield.

In this case, our msi is called setup.msi.

With our copy of WiX 2.0.2912.0 installed and in the PATH, we run the following command against our setup.msi:

dark -s "setup.msi" setup.wxs

This will generate a WiX setup file named setup.wsx.  This file will contain the reverse-generated WiX code from our setup.msi file.

If we open the setup.wsx in our favorite XML editor, we should look for the following string:


<Dialog Id="InstallWelcome"


This will mark the beginning of the first dialog that we are interested in, the InstallWelcome dialog.  The

complete dialog is presented here:

<Dialog Id="InstallWelcome" Width="374" Height="266" Title="[ProductName] - InstallShield Wizard" NoMinimize="yes">
        <Control Id="Next" Type="PushButton" X="230" Y="243" Width="66" Height="17" Default="yes" Text="&amp;Next &gt;">
          <Publish Event="NewDialog" Value="LicenseAgreement"><![CDATA[1]]></Publish>
        </Control>
        <Control Id="Cancel" Type="PushButton" X="301" Y="243" Width="66" Height="17" Cancel="yes" Text="Cancel">
          <Publish Event="SpawnDialog" Value="CancelSetup"><![CDATA[1]]></Publish>
        </Control>
        <Control Id="Back" Type="PushButton" X="164" Y="243" Width="66" Height="17" Disabled="yes" Text="&lt; &amp;Back">
          <Publish Event="NewDialog" Value="SplashBitmap"><![CDATA[Display_IsBitmapDlg]]></Publish>
        </Control>
        <Control Id="Copyright" Type="Text" X="135" Y="144" Width="228" Height="73" Transparent="yes"

TabSkip="no">
          <Text>WARNING: This program is protected by copyright law and international treaties.</Text>
          <Condition Action="hide"><![CDATA[SHOWCOPYRIGHT="No"]]></Condition>
          <Condition Action="show"><![CDATA[SHOWCOPYRIGHT="Yes"]]></Condition>
        </Control>
        <Control Id="TextLine2" Type="Text" X="135" Y="55" Width="228" Height="45" Transparent="yes">
          <Text>The InstallShield(R) Wizard will install [ProductName] on your computer. To continue, click

Next.</Text>
        </Control>
        <Control Id="DlgLine" Type="Line" X="0" Y="234" Width="374" Height="0" />
        <Control Id="Image" Type="Bitmap" X="0" Y="0" Width="374" Height="234" Text="NewBinary5" />
        <Control Id="TextLine1" Type="Text" X="135" Y="8" Width="225" Height="45" Transparent="yes">
          <Text>{&amp;TahomaBold10}Welcome to the InstallShield Wizard for [ProductName]</Text>
        </Control>
      </Dialog>


The first line:
<Dialog Id="InstallWelcome" Width="374" Height="266" Title="[ProductName] - InstallShield Wizard" NoMinimize="yes">


This line is pretty self explanatory.  The Dialog Id is used to reference this dialog elswhere in the WiX setup. 

If you are like me, you'll want to remove the InstallShield string reference. 

The next several lines are Control Id's.  In this simple dialog, we only have the Next, Cancel, and Back buttons,

followed by the text controls for Copyright, and InstallShield TagLines.  We also have a Dialog Line for

appearance, along with the background bitmap.  We close with one last Text control.

Note that for most of the controls, things are pretty straightforward, with a declarative UI model.  However, the

Next button has an additional bit of XML that is of considerable importance:


<Publish Event="NewDialog" Value="LicenseAgreement"><![CDATA[1]]></Publish>


The Controls may publish several events, but for the purpose of the article we are only interested in the "SpawnDialog" event.

Let's break this down a little further:

<Publish Event="NewDialog"

This is the action to be taken if the "Next" button is pushed.

Value="LicenseAgreement"

This is the 'argument' for this action.  In the case of the NewDialog event, the argument is the name of the next screen to display.

<![CDATA[1]]>

This is the 'condition' under which this dialog should be executed.  This is blocked out into a !CDATA section, as

conditions often contain XML control characters like '<' or '>'.  A condition of '1' means 'true' or always.  A condition of '0' means never.  We may also use Windows Installer Properties instead of constants. Properties are similar to global variables, as explained in the MSDN MSI documentation.


</Publish>

Of course, we need to close the tag.

That's a quick breakdown of the dialog.  Let's embed this dialog in our first WiX script.  First, we'll view a simple script without UI:


<?xml version='1.0'?>
<Wix xmlns='http://schemas.microsoft.com/wix/2003/01/wi'>
<!-- really, follow the advice here - this GUID is invalid - generate your own! -->
   <Product Id='INVALID_GUID-0000-0000-C000-000000000001' Name='My Product Name' Language='1033' Version='1.0.0.0'

Manufacturer='My Company'>
      <Package Id='INVALID_GUID-1234-0000-ABCD-000000000003' Description='My Setup' InstallerVersion='200'

Compressed='yes' />
      <Media Id='1' Cabinet='product.cab' EmbedCab='yes' />

      <Directory Id='TARGETDIR' Name='SourceDir'>
         <Directory Id='ProgramFilesFolder' Name='PFiles'>
            <Directory Id='MyCompany' Name='MCompany' LongName='My Company'>
               <Component Id='MyProductComponent' Guid='INVALID_GUID-374A-0000-EFAC-000000000067'>
<!-- Note: This is just an example - you wouldn't really link to a file in your system dir -->          
       <File Id='MyFile' Name='notepad.exe' KeyPath='yes' DiskId='1' src='C:\Windows\System32\notepad.exe'/>
               </Component>
            </Directory>
         </Directory>
      </Directory>

      <Feature Id='MyProductFeature' Title='My Product Feature' Level='1'>
         <ComponentRef Id='MyProductComponent' />
      </Feature>
   </Product>
</Wix>


This script would install notepad.exe into C:\Program Files\My Company\notepad.exe.  Please note that you must generate your own GUIDs for this script to compile.

 

For more explanation of this simple WiX script, please visit the WiX tutorial page at

http://www.tramontana.co.hu/wix/.

This script doesn't have a UI.  We'll add the Install Welcome screen we previously extracted from our InstallShield setup.

 

<?xml version='1.0'?>
<Wix xmlns='http://schemas.microsoft.com/wix/2003/01/wi'>
<!-- really, follow the advice here - this GUID is invalid - generate your own! -->
   <Product Id='INVALID_GUID-0000-0000-C000-000000000001' Name='My Product Name' Language='1033' Version='1.0.0.0'

Manufacturer='My Company'>
      <Package Id='INVALID_GUID-1234-0000-ABCD-000000000003' Description='My Setup' InstallerVersion='200'

Compressed='yes' />
      <Media Id='1' Cabinet='product.cab' EmbedCab='yes' />

      <Directory Id='TARGETDIR' Name='SourceDir'>
         <Directory Id='ProgramFilesFolder' Name='PFiles'>
            <Directory Id='MyCompany' Name='MCompany' LongName='My Company'>
               <Component Id='MyProductComponent' Guid='INVALID_GUID-374A-0000-EFAC-000000000067'>
<!-- Note: This is just an example - you wouldn't really link to a file in your system dir -->          
       <File Id='MyFile' Name='notepad.exe' KeyPath='yes' DiskId='1' src='C:\Windows\System32\notepad.exe'/>
               </Component>
            </Directory>
         </Directory>
      </Directory>

      <Feature Id='MyProductFeature' Title='My Product Feature' Level='1'>
         <ComponentRef Id='MyProductComponent' />
      </Feature>
        <UI>
             
            <InstallUISequence>
   <Show Dialog="InstallWelcome" After="CostFinalize"><![CDATA[Not Installed And (Not PATCH Or

IS_MAJOR_UPGRADE)]]></Show>                
            </InstallUISequence>


<Dialog Id="InstallWelcome" Width="374" Height="266" Title="[ProductName] - InstallShield Wizard"

NoMinimize="yes">
        <Control Id="Next" Type="PushButton" X="230" Y="243" Width="66" Height="17" Default="yes" Text="&amp;Next

&gt;">
          <Publish Event="NewDialog" Value="LicenseAgreement"><![CDATA[1]]></Publish>
        </Control>
        <Control Id="Cancel" Type="PushButton" X="301" Y="243" Width="66" Height="17" Cancel="yes" Text="Cancel">
          <Publish Event="SpawnDialog" Value="CancelSetup"><![CDATA[1]]></Publish>
        </Control>
        <Control Id="Back" Type="PushButton" X="164" Y="243" Width="66" Height="17" Disabled="yes" Text="&lt;

&amp;Back">
          <Publish Event="NewDialog" Value="SplashBitmap"><![CDATA[Display_IsBitmapDlg]]></Publish>
        </Control>
        <Control Id="Copyright" Type="Text" X="135" Y="144" Width="228" Height="73" Transparent="yes"

TabSkip="no">
          <Text>WARNING: This program is protected by copyright law and international treaties.</Text>
          <Condition Action="hide"><![CDATA[SHOWCOPYRIGHT="No"]]></Condition>
          <Condition Action="show"><![CDATA[SHOWCOPYRIGHT="Yes"]]></Condition>
        </Control>
        <Control Id="TextLine2" Type="Text" X="135" Y="55" Width="228" Height="45" Transparent="yes">
          <Text>The InstallShield(R) Wizard will install [ProductName] on your computer. To continue, click

Next.</Text>
        </Control>
        <Control Id="DlgLine" Type="Line" X="0" Y="234" Width="374" Height="0" />
        <Control Id="Image" Type="Bitmap" X="0" Y="0" Width="374" Height="234" Text="NewBinary5" />
        <Control Id="TextLine1" Type="Text" X="135" Y="8" Width="225" Height="45" Transparent="yes">
          <Text>{&amp;TahomaBold10}Welcome to the InstallShield Wizard for [ProductName]</Text>
        </Control>
      </Dialog>
        </UI>
   </Product>
</Wix>

 

The important thing to note is that our previous <Dialog> section is now placed within the new <UI> section of the setup XML.  We've also added an <InstallUISequence> in this same <UI> section.


The InstallUISequence tells the Windows Installer what order to run the UI elements in.  There are additional sections, such as the AdminUISequence, but we won't be covering that here.  They aren't required for a simple installation.

If we change our GUIDS to valid GUIDS, and save the file to the name Product.wxs, we may attempt to generate our MSI file by running:

candle.exe product.wxs
light.exe product.wixobj

We get an error:

C:\temp\Product.wixobj : fatal error LGHT0028: Unresolved reference: 'Dialog:CancelSetup' in section: '27A59EBD-4BCA-4C54-B625-42CE0438F9F5'


If we review our original script, we see that in the 'Next' and 'Cancel' Controls of the Dialog InstallWelcome, we

reference the 'LicenseAgreement' and 'CancelSetup' dialogs.  We haven't yet migrated these dialogs, so we will

comment these references out temporarily, so that we may compile:

<!-- Commented out to compile:
 
    <Publish Event="NewDialog" Value="LicenseAgreement"><![CDATA[1]]></Publish>

-->

And:

<!-- Commented out to compile:

    <Publish Event="SpawnDialog" Value="CancelSetup"><![CDATA[1]]></Publish>

-->


If we compile now, we get:

C:\temp\Product.wixobj : fatal error LGHT0028: Unresolved reference: 'Dialog:SplashBitmap' in section: '27A59EBD-4BCA-4C54-B625-42CE0438F9F5'

The offending line in the 'Back' Control.  If we examine this control carefully, we note that the 'Back' button is

Disabled='Yes'.  Since we can't ever go back to the SplashBitmap, we might as well remove the reference (This is a

logic bug in the original InstallShield screen logic.  As you spend time reverse engineering InstallShield setups,

you'll find may such errors).

The 'Back' control should now look like:

<Control Id="Back" Type="PushButton" X="164" Y="243" Width="66" Height="17" Disabled="yes" Text="&lt; &amp;Back"></Control>


While we are cleaning up,let's remove the extraneous conditions on the Copyright Text control.  After removing the

conditions, it should look like this:

<Control Id="Copyright" Type="Text" X="135" Y="144" Width="228" Height="73" Transparent="yes" TabSkip="no">
  <Text>WARNING: This program is protected by copyright law and international treaties.</Text>
</Control>


If we run the setup now, we see a pretty plain Welcome Screen.  We seem to be missing the InstallShield screen

background.  If we look closely at the Dialog XML, we notice that there is a reference to a bitmap control:

   <Control Id="Image" Type="Bitmap" X="0" Y="0" Width="374" Height="234" Text="NewBinary5" />


Where may we get this "NewBinary5"?

Well, NewBinary5 refers to a an entry in the Binary table of the MSI database.  If we go back to our original

generated setup.wxs, and do a search for NewBinary5, we see that one of the lines looks similar to this:

<Binary Id="NewBinary5" src="Binary\NewBinary5.ibd" />

Dark.exe will have created a file called NewBinary5.ibd in a binary subdirectory of the location where Dark was

originally run.  Copy this NewBinary5.ibd file to the same location you've placed your product.wxs.

Add the following line to your <UI> section, so that WiX will embed this file into your MSI:


<Binary Id="NewBinary5" src="NewBinary5.ibd" />
    

After this, we finally have a reproduction of the original InstallShield Welcome Dialog.  We may continue to add dialogs as needed, by either hand crafting them, our extracting them from our existing installations.


Here's the final script:

<?xml version='1.0'?>
<Wix xmlns='http://schemas.microsoft.com/wix/2003/01/wi'>
<!-- really, follow the advice here - this GUID is invalid - generate your own! -->
   <Product Id='27A59EBD4BCA4c54B62542CE0438F9F5' Name='My Product Name' Language='1033' Version='1.0.0.0'

Manufacturer='My Company'>
      <Package Id='90E7DDF747F445098914E98F99AC2841' Description='My Setup' InstallerVersion='200'

Compressed='yes' />
      <Media Id='1' Cabinet='product.cab' EmbedCab='yes' />

      <Directory Id='TARGETDIR' Name='SourceDir'>
         <Directory Id='ProgramFilesFolder' Name='PFiles'>
            <Directory Id='MyCompany' Name='MCompany' LongName='My Company'>
               <Component Id='MyProductComponent' Guid='7F7A882791C544dbAEC7CF134F819EF3'>
<!-- Note: This is just an example - you wouldn't really link to a file in your system dir -->          
       <File Id='MyFile' Name='notepad.exe' KeyPath='yes' DiskId='1' src='C:\Windows\System32\notepad.exe'/>
               </Component>
            </Directory>
         </Directory>
      </Directory>

      <Feature Id='MyProductFeature' Title='My Product Feature' Level='1'>
         <ComponentRef Id='MyProductComponent' />
      </Feature>
        <UI>

 <Binary Id="NewBinary5" src="NewBinary5.ibd" />
                  
            <InstallUISequence>
   <Show Dialog="InstallWelcome" After="CostFinalize"><![CDATA[Not Installed And (Not PATCH Or

IS_MAJOR_UPGRADE)]]></Show>                
            </InstallUISequence>


<Dialog Id="InstallWelcome" Width="374" Height="266" Title="[ProductName] - InstallShield Wizard"

NoMinimize="yes">
        <Control Id="Next" Type="PushButton" X="230" Y="243" Width="66" Height="17" Default="yes" Text="&amp;Next

&gt;">

<!--
          <Publish Event="NewDialog" Value="LicenseAgreement"><![CDATA[1]]></Publish>
-->

        </Control>
        <Control Id="Cancel" Type="PushButton" X="301" Y="243" Width="66" Height="17" Cancel="yes" Text="Cancel">

<!--
          <Publish Event="SpawnDialog" Value="CancelSetup"><![CDATA[1]]></Publish>

-->

        </Control>
        <Control Id="Back" Type="PushButton" X="164" Y="243" Width="66" Height="17" Disabled="yes" Text="&lt;

&amp;Back">
        </Control>
        <Control Id="Copyright" Type="Text" X="135" Y="144" Width="228" Height="73" Transparent="yes"

TabSkip="no">
          <Text>WARNING: This program is protected by copyright law and international treaties.</Text>
        </Control>
        <Control Id="TextLine2" Type="Text" X="135" Y="55" Width="228" Height="45" Transparent="yes">
          <Text>The InstallShield(R) Wizard will install [ProductName] on your computer. To continue, click

Next.</Text>
        </Control>
        <Control Id="DlgLine" Type="Line" X="0" Y="234" Width="374" Height="0" />
        <Control Id="Image" Type="Bitmap" X="0" Y="0" Width="374" Height="234" Text="NewBinary5" />
        <Control Id="TextLine1" Type="Text" X="135" Y="8" Width="225" Height="45" Transparent="yes">
          <Text>{&amp;TahomaBold10}Welcome to the InstallShield Wizard for [ProductName]</Text>
        </Control>
      </Dialog>
        </UI>
   </Product>
</Wix>

 

1 Comment

Comments have been disabled for this content.