WiX tutorial

Lesson 5 Net and .NET

5.1 Framed by .NET

When you plan to distribute programs based on the .NET Framework, you have to make sure the user has the framework installed. Microsoft allows you to redistribute their framework but only in one form, its original Dotnetfx.exe file (see their description).

This also means that you can't build the framework into your own .msi package. There is no merge module or similar available. You have to provide a separate bootstrap installer, Setup.exe that looks for the installed framework and starts your redistributed copy of Dotnetfx.exe (or, alternatively, downloads and installs it from the Net). When finished, it will call your own installation package.

However, you don't have to write such a bootstrap installer yourself. The next version of WiX, 3.5 will have its own bootstrapper called Burn but until it is released, you can either use one provided by Microsoft or another, free, open source one, the dotNetInstaller. Or, as an alternative, you can write your own in the AutoIt scripting language.

If you need to determine the presence of the .NET Framework on the user's computer, you can use the WixNetFx extension module bundled with WiX. This extension sets a large number of properties (the complete list can be found in the WiX help file) for every version of the framework. The most important ones for us will be:

NETFRAMEWORKxx
Set if the specified version of the framework is installed.
NETFRAMEWORKxx_SP_LEVEL
Set to the Service Pack level of the framework.
NETFRAMEWORKxxINSTALLROOTDIR
Set to the installation folder of the framework.

All you have to do to read the value of any of these properties is to reference them using a PropertyRef tag.

<PropertyRef Id="NETFRAMEWORK10"/>
<Condition Message='This setup requires the .NET Framework 1.0 installed.'>
  <![CDATA[Installed OR NETFRAMEWORK10]]>
</Condition>

If you need to check for a Service Pack, you don't even have to check for the framework version itself, the SP property will only be set if the base framework is also present. However, you first need to check whether the property is set at all, then go on checking which value it actually has:

<PropertyRef Id="NETFRAMEWORK20_SP_LEVEL"/>
<Condition Message='This setup requires the .NET Framework 2.0 with Service Pack 1 installed.'>
  <![CDATA[Installed OR (NETFRAMEWORK20_SP_LEVEL AND NETFRAMEWORK20_SP_LEVEL = "#1")]]>
</Condition>

With later framework versions, extra properties are also available:

<PropertyRef Id="NETFRAMEWORK35_CLIENT"/>
<Condition Message='This setup requires the .NET Framework 3.5 client profile installed.'>
  <![CDATA[Installed OR NETFRAMEWORK35_CLIENT]]>
</Condition>

When you link the installer, don't forget to link against the WixNetFxExtension module:

candle.exe SampleDotNET.wxs
light.exe -ext WixNetFxExtension SampleDotNET.wixobj

You can download the complete SampleDotNET.

5.2 Launch the Internet

There are cases when you want to launch something in a browser, either locally or online. To do this, you can create an URL link on the user's disk. These files are actually formatted as .ini files, thus we can use IniFile to create them:

<Component>
  ...
  <IniFile Id='Launch' Action='addLine' Name='Launch.url' Directory='INSTALLDIR'
  Section='InternetShortcut' Key='URL' Value='http://www.acmefoobar.com' />
  ...
</Component>

To launch the default browser directly, first we have to query it, then use this path in the usual way to launch a custom action after we have finished the installation (but only when we install, not when we uninstall). Please, make sure you use this solution to make sure that the user's preferred browser will start: never hardwire any specific browser.

<Property Id="BROWSER">
  <RegistrySearch Id='DefaultBrowser' Type='raw' Root='HKCR' Key='http\shell\open\command' />
</Property>

<CustomAction Id='LaunchBrowser' Property='BROWSER' ExeCommand='www.something.com' Return='asyncNoWait' />

<InstallExecuteSequence>
  ...
  <Custom Action='LaunchBrowser' After='InstallFinalize'>NOT Installed</Custom>
</InstallExecuteSequence>

You can download the complete SampleBrowser.

To add a shortcut to the desktop or the Start menu that launches the default browser and jumps to a specific web site is even simpler. The only thing we have to look out for is to use a property for the URL: writing the URL directly into the Target attribute of the Shortcut would fail because the compiler would think it is the name of a local file to be deployed:

<Property Id="URL" Value="http://www.something.com" />

<Shortcut Id="WebShortcut" Name="Web URL" Description="Jump to our website" Target="[URL]" />

5.3 Web Directory

The WiX toolset has additional libraries that allow the installer to perform additional tasks like creating a web directory in IIS. To use these extensions, all you have to do is to link against the appropriate WiX library. The linker will include the necessary helper DLLs into the installation package automatically.

First, we have to create the web site with the files belonging to it:

<Directory Id='TARGETDIR' Name='SourceDir'>
  <Directory Id='ProgramFilesFolder' Name='PFiles'>
    <Directory Id='InstallDir' Name='Acme'>

      <Component Id='default.phpComponent' Guid='YOURGUID-5314-4689-83CA-9DB5C04D5742'>
        <File Id='default.htmFile' Name='default.htm' Source='default.htm' DiskId='1' KeyPath='yes' />
      </Component>

    </Directory>
  </Directory>

The next step is to create the virtual directory:

  <Component Id='TestWebVirtualDirComponent' Guid='YOURGUID-6304-410E-A808-E3585379EADB'>
    <WebVirtualDir Id='TestWebVirtualDir' Alias='Test' Directory='InstallDir'
      WebSite='DefaultWebSite'>
      <WebApplication Id='TestWebApplication' Name='Test' />
    </WebVirtualDir>
  </Component>

</Directory>

Finally, create an entry to reference the web site:

<WebSite Id='DefaultWebSite' Description='Default Web Site'>
  <WebAddress Id='AllUnassigned' Port='80' />
</WebSite>

When you link the installation package, you have to link it against the appropriate WiX library. As you pass more than one WiX object file to the linker, you also have to specify the name of the output file:

light.exe -out SampleWebDir.msi SampleWebDir.wixobj path\sca.wixlib

You can download the complete SampleWebDir.

5.4 Services Rendered

Services can be installed and started automatically.

<Component Id='ServiceExeComponent' Guid='YOURGUID-D752-4C4F-942A-657B02AE8325'
  SharedDllRefCount='no' KeyPath='no' NeverOverwrite='no' Permanent='no' Transitive='no'
  Win64='no' Location='either'>

  <File Id='ServiceExeFile' Name='ServiceExe.exe' Source='ServiceExe.exe'
    ReadOnly='no' Compressed='yes' KeyPath='yes' Vital='yes' Hidden='no' System='no'
    Checksum='no' PatchAdded='no' />

  <ServiceInstall Id='MyServiceInstall' DisplayName='My Test Service' Name='MyServiceExeName'
    ErrorControl='normal' Start='auto' Type='ownProcess' Vital='yes' />

  <ServiceControl Id='MyServiceControl' Name='MyServiceExeName'
    Start='install' Stop='uninstall' Remove='uninstall' />

</Component>
Copyright © 2004-2010, Gábor DEÁK JAHN, Tramontána
Comments and contributions are most welcome                   Comments and contributions are most welcome
A note: some people use a very braindead spam filtering idea actually generating extra amounts of spam: asking the sender to reply to an acknowledgment message in order to be placed on a whitelist and allowed through. All those who do so, unfortunately, will never receive a reply from me: I refuse this idea both in theory and practice.