Page tree
Skip to end of metadata
Go to start of metadata

Introduction

All you need to do in order for FireBreath to build a basic MSI installer is to install WiX and then run the prep script! You need WiX 3.0 or later. Also, for reasons beyond our control this installer will not work correctly with a DLL generated with Visual Studio 2005 or earlier. 2008 or 2010 should work fine.

WiX stands for the Windows Installer XML toolset, and can be used to generate installer executables from XML files. The XML files can be pretty gnarly, so make sure you familiarize yourself with the WiX documentation before embarking on this journey. You will need a working understanding of the Windows Installer concepts in order to be effective with WiX.

There is also a fantastic WiX tutorial here. It is very detailed and useful.

That said, FireBreath does much of the heavy-lifting for you. Most likely you'll just need to tell WiX about some pretty images to show during the install process, and let it know about any supplementary files to install along with your plugin.

WiX and your plugin

If you have generated your plugin project with the fbgen.py tool, then FireBreath automatically generates a WiX template for your plugin project. Look for the file in firebreath/projects/<your plugin>/Win/Wix/. The XML file should be named something like <your plugin>Installer.wxs.

Also, once you've installed the WiX toolset and rerun the prep script, it will create a Visual Studio project for the installer, in addition to the project it creates for the plugin itself.  These project files will both be in firebreath/build/projects/<your plugin>/.  The plug-in project is named <your plugin>.vcxproj, and the installer project is named <your plugin>_WiXInstall.vcxproj.  (Or *.vcproj for versions of Visual Studio prior to 2010.).  If the installer project is missing, and you had made sure to rerun the prep script after installing WiX, see the tip "Fix WiX Toolset 3.6 environment variable" below.

When you build <your plugin>.sln, it should (in addition to the plugin DLL) create an output file named <your plugin>.msi, which is the installer.  (Look in firebreath/build/bin/<your plugin>/<configuration>/.)  You can double-click it to run the installer; then restart your browser and check the list of installed plug-ins to confirm it's installed.

Inside your .wxs file

There are two versions of <your plugin>Installer.wxs: a source version that lives in firebreath/projects/<your plugin>/Win/Wix/, and an automatically generated version that will be written to firebreath/build/projects/<your plugin>/.  The source version generally contains variables (such as ${FBSTRING_PluginName}) that get translated into strings (such as MyCoolPlugin) in the generated version.  In this section, we examine the source version.

The file starts off with standard XML header information. We set up the encoding and XML version, and specify our XML schema.

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">

After this initialization we define our product entity:

<Product Id="*" Name="${FBSTRING_PluginName}" Language="1033" Version="${FBSTRING_PLUGIN_VERSION}" Manufacturer="${FBSTRING_CompanyName} UpgradeCode="<PRODUCT UPGRADE GUID HERE>">

Your product is the entity inside of add/remove programs that corresponds to your installed application (your plugin). The Id is specified by a GUID to make add/remove/upgrade actions possible (and they are automatically included in your installer). Every reference to ${someString} refers to CMake variables that are auto-populated during the prep phase.

Also defined in your plugin's .wxs file is the Directory where your plugin will be installed.

<Directory Id="TARGETDIR" Name="SourceDir">

This defines a file hierarchy, declared from the perspective of the target machine. After your installer is finished, the target machine's install directory will have the same state as is described here. Inside our TARGETDIR Directory entity we tell WiX where we want to install the plugin:

<Directory Id="${FB_WIX_INSTALL_LOCATION}">

By default, ${FB_WIX_INSTALL_LOCATION} will translate to AppDataFolder, meaning the user's Application Data Folder.  This has the benefit of not requiring administrative privileges, but the disadvantage that after installing your plugin it is only available to the user who installed it! To have the plugin instead be installed to Program Files you can change ${FB_WIX_INSTALL_LOCATION} from AppDataFolder to ProgramFilesFolder.

Under this directory, you can see that we are creating another directory, corresponding to your company (or organization) that has developed this plugin. We create a Windows installed Component, and we also add a registry key here to let Windows keep track of the files we've installed into the target machine.

<Component Id="CompanyDirComp" Guid="*">
    <RemoveFolder Id="RemoveCompanyDir" On="uninstall" />
    <RegistryValue Root="HKCU" Key="SOFTWARE\${COMPANY_NAME}" Name="Uninstall" Type="string" Value="${FBSTRING_PLUGIN_VERSION}" KeyPath="yes" />
 </Component>

To install your own files with the plugin's automatically generated .dll file, add them into the following section, following the same rules as the rest of the XML:

<!-- Put Additional files here: -->
<!-- example:
<Component Id="UniqueComponentId" Guid="UniqueGUID">
    <File Id="uniqueFileId" KeyPath="yes" Source="SourceDir\filename.ext" />
</Component>
/example -->
<!--  -->

Lastly ensure that your components have been added to an appropriate Feature. Features are discrete installable units that the user can choose to install or not when they run the installer executable.  If your component (indicated here by UniqueComponentId) is not an optional feature, add it to MainPluginFeature:

<Feature Id="MainPluginFeature" Title="${FBSTRING_ProductName}" Level="1">
    <ComponentRef Id="InstallDirComp"/>
    <ComponentRef Id="CompanyDirComp"/>
    <ComponentRef Id="UniqueComponentId"/>
    <ComponentGroupRef Id="PluginDLLGroup"/>
</Feature>

Adding your own built libraries based on the current build configuration

When adding your own extra Dll dependancies, you probably want to include the Dll that corresponds to the configuration you are building the plugin for.

ie. Building for Debug, include the Debug version of my Dll.

You can add the following to your CMakeLists.txt or Win/projectDef.cmake which simply defines a Wix variable that you can use in your .wxs file:

set (WIX_LINK_FLAGS ${WIX_LINK_FLAGS} -dBuild=${CMAKE_CFG_INTDIR})

You can now define your File in the .wxs along the following lines:

<File Id="myStuff.dll" Source="${YOUR_OWN_PATH_VARIABLE}\myStuff\$(var.Build)\myStuff.dll" />

If you are installing it per-user, include the below as well right after the above:

<RegistryValue Root="HKCU" Key="SOFTWARE\${COMPANY_NAME}\myStuff" Name="Uninstall" Type="string" Value="1.0.0" KeyPath="yes" />

Adding a Default UI

To add a prewritten user interface, you can user the WiXUI Dialog Library. Adding a minimal UI is as easy as adding:

Minimal UI
<UI>
 <UIRef Id="WixUI_Minimal" />
</UI>

to the end of the <product> tag inside of the WiX source file (.wxs) located in the Win\wix\  folder inside of your project. Refer to the WixUI manual for additional interface options. 

Adding Custom Installer Images

Images for the default installer UI’s can be overridden using WixVariables. For further information about customizing the WiX UIs, including the dimensions of the images, see the documentation.  Below is an example of overriding the banner and the main background images of a customized installer.

Custom Installer w/ Images
<Product>
   . . .
 
   <!-- Loads images from a folder called Bitmaps located in the Win directory of your project -->
   <!-- Upper banner image: 493px x 58px -->
   <WixVariable Id="WixUIBannerBmp" Value="${CMAKE_CURRENT_SOURCE_DIR}/Win/Bitmaps/bannrbmp.bmp" />
   <!-- Background images: 493px x 312px -->
   <WixVariable Id="WixUIDialogBmp" Value="${CMAKE_CURRENT_SOURCE_DIR}/Win/Bitmaps/dlgbmp.bmp" />
 
   <!-- A minimalistic UI that shows the progress bar and an exit screen-->
   <UI Id="UserInterface">
 
     <Property Id="WIXUI_INSTALLDIR" Value="TARGETDIR" />
     <Property Id="WixUI_Mode" Value="Custom" />
 
     <TextStyle Id="WixUI_Font_Normal" FaceName="Tahoma" Size="8" />
     <TextStyle Id="WixUI_Font_Bigger" FaceName="Tahoma" Size="9" Bold="yes" />
     <TextStyle Id="WixUI_Font_Title" FaceName="Tahoma" Size="9" Bold="yes" />
 
     <Property Id="DefaultUIFont" Value="WixUI_Font_Normal" />
     <DialogRef Id="ProgressDlg" />
     <DialogRef Id="ErrorDlg" />
     <DialogRef Id="FilesInUse" />
     <DialogRef Id="FatalError" />
     <DialogRef Id="UserExit" />
 
     <Publish Dialog="ExitDialog" Control="Finish" Event="EndDialog" Value="Return" Order="999">1</Publish>
 
   </UI>
   <UIRef Id="WixUI_Common" />
 </Product>

 

Adding .NET detection

WiX (as of version 3.5) provides built-in detection of installed .NET framework versions. If your plugin is based on .NET code, you need two things to detect the prerequisites during installation. First, you have to include an additional WiX extension library (WixNetFxExtension) in your plugin CMakeLists.txt file by adding:

set (WIX_LINK_FLAGS ${WIX_LINK_FLAGS} -ext WixNetFxExtension)

Next, you need to reference the appropriate properties in your plugin's .wxs file. The following code will check if .NET version 3.0 or higher is installed:

<PropertyRef Id="NETFRAMEWORK30" />
<PropertyRef Id="NETFRAMEWORK35" />
<PropertyRef Id="NETFRAMEWORK40CLIENT" />
<PropertyRef Id="NETFRAMEWORK40FULL" />
<Condition Message='This product requires the .NET Framework 3.0 or higher version installed.'>
    <![CDATA[Installed OR (NETFRAMEWORK30 OR NETFRAMEWORK35 OR NETFRAMEWORK40CLIENT OR NETFRAMEWORK40FULL)]]>
</Condition>

Setting up the registry

The built-in WiX installer automatically registers your plugin for both NPAPI and ActiveX browsers, so no special steps should need to be taken by the plugin developer for this step. For more information on how NPAPI registration works, read this documentation at the Mozilla Developer Network.

Fix WiX Toolset 3.6 environment variable

If you've installed WiX 3.6, the default WiX installer will set a WIX environment variable with a backslash ('\') at the end.  For example:

echo %WIX%
C:\Program Files\WiX Toolset v3.6\

This trailing backslash will cause the wix.cmake to fail, although you might not notice a problem while cmake is running.  One symptom is that <your plugin>_WiXInstall.vcxproj is not generated, so building the plug-in solution won't create an installer.

To fix the problem, simply remove the backslash at the end of the WIX environment variable and then re-run the prep script.  You can edit the variable using the Windows Control Panel (Start/Control Panel/System/Advanced/Environment Variables/System variables).  Or, to automate this, you can instead use a script such as this one created by Ritter Runkel, which modifies the environment variable and then calls the prep script:

@echo off
setlocal
rem --- check for trailing backslash
set _test=%WIX:~-1,1%
if NOT %_test% == \ (
    goto OK
)
rem --- remove trailing backslash
set WIX=%WIX:~0,-1%
:OK
set WIX_ROOT_DIR=%WIX%
rem --- call the "prep" script
call fb/prep2010.cmd prj build "-DVERBOSE=1"
echo.
endlocal
echo on

If you use Ant for your builds, you can include something like this in your build script to remove the trailing backslash:

<property name="env.wix.path" value="${env.WIX}"/>
<scriptdef name="fix-wix-path" language="javascript">
<![CDATA[
var wixPath = project.getProperty("env.wix.path");
if (wixPath.endsWith("\\")) {
project.setProperty("wix.path", wixPath.substring(0, wixPath.length() - 1));
} else {
project.setProperty("wix.path", wixPath);
}
]]>
</scriptdef>
<target name="-warn-wix" unless="env.WIX">
<echo>WiX does not appear to be installed!</echo>
</target>
<target name="prep-project" depends="-warn-wix" if="env.WIX">
<mkdir dir="build"/>
<fix-wix-path/>
<exec executable="cmd">
<env key="WIX" value="${wix.path}"/>
<arg value="/c"/>
<arg value="fb/prep2010.cmd"/>
<arg value="prj"/>
<arg value="build"/>
</exec>
</target>

 

 

 

 

  • No labels