Creating an installer for Visio with WiX

If you develop addins / templates / stencils for Visio, sooner or later you come to a question, how do you deploy them. Visio allows you to deploy your solution / template in such a way that template / stencil can be embed nicely in Visio user interface, thus showing up just like all other Visio built-in templates. For Visio developers, Visio SDK provides the Solution Publishing Tool, which is an official way to publish Visio-related components. However this nice tools has a number of limitations, in particular:

– It does not integrate well into automated build process, when you e.g. use a continuous integration using a build server.

– it uses scripting custom vbscript actions which may become a problem with some stupid anti-virus programs or in some very restricted environments.

Windows Installer Xml (WiX) builds Windows installation packages from XML source code, and integrates seamlessly into build processes. The toolset originates from Microsoft, which used it internally to build Microsoft Office installers. The tool is super-cool and rock-solid =)

This post explains the magic behind the Visio Solution Publishing tool and shows how you can do the same thing with WiX, by creating an installer which will install template and stencil. Also the post includes sample / template WiX solution to install Visio files, both for Visio x86 and Visio x64.

Creating installer includes basically the following steps:

– Downloading and installing WiX (version 3.6 was used to build the sample project)
– Creating WiX project in Visual Studio.
– Adding Visio template and stencil files to the project.
– Customizing the installer to add visio-specific actions (most challenging I think, so this post only focuses on this part, all other things are relatively easy I suppose, and well covered by the user manual and numerous tutorials)

So what does the Solution Publishing Tool actually do with the installer? It fills in the “PublishComponent” WindowsInstaller table, and adds trigger action for Visio to rebuild template cache by modifying ConfigChangeID registry key. You can find detailed information about the table in this Microsoft KB832029 and in this article. Since Visual Studio installation project is rather limited tool in fact, and does not support anything unusual like component publishing, this gap is was filled with this Solution Publishing Tool.

WiX does not impose any restrictions and provides full access to all features Windows Installer supports. Means, you can author these Visio publishing rules directly in installer, without need for the Solution Publishing Tool, which means that your project can be built from ground up in Visual Studio, or from command line. Including, in particular, even Microsoft TFS online (which  unexpectedly supports WiX builds).

Adding Visio publishing information to WiX installer.

Basically after adding Visio template/stencil file your WiX project will contain something like this:

<Component Id="StencilA" >
  <File Name="StencilA.vss" />
</Component>

To publish the stencil to Visio you need to add publishing information like this

<Component Id="StencilA" >
  <File Name="StencilA.vss" />
  <Category
    Id="{CF1F488D-8D6F-499C-A78D-026E1DF38101}"
    Qualifier="1033\StencilA.vss"
    AppData="X Stencils\Stencil-A" />
</Component>

This example above publishes an English stencil (id = guid of stencil, see below), named “StencilA.vss”, which should be made available under category “X Stencils” as “Stencil-A”.

The values of the fields for Visio are following (see the above KB article):

Attribut Value Example
Id Fixed code For templates: {CF1F488D-8D6F-499C-A78D-026E1DF38100}
For stencils: {CF1F488D-8D6F-499C-A78D-026E1DF38101}
Qualifier LocaleID\FileName 1033\flowchart.vstNote You cannot use multiples of the same file name in one Visio environment. Locale-ID\FileNamemust be unique so that Visio can recognize it. Therefore, use a unique file name in one Visio environment.
AppData MenuPath|AltNames Flowchart\Work Flow Diagram Shapes|Work Flow Diagram Shapes.vss;workflow.vss

Further description of values

Value Description Example
ComponentID A predefined value for the content type.
For templates:
{CF1F488D-8D6F-499C-A78D-026E1DF38100}
For stencils:
{CF1F488D-8D6F-499C-A78D-026E1DF38101}
LocaleID The decimal locale ID of the component. Common values include the following:1033 English
1031 German
1036 French
1049 Russian
1033
FileName The file name (without the path) of the template or stencil flowchart.vst
MenuPath For templates, the Menu-Path specifies where the template is displayed in the templates menu tree and in the Choose Drawing Type task pane. For stencils, the Menu-Path specifies where the stencil is displayed in the stencils menu tree.
If this value is an empty string, the template or stencil is not displayed in the menus.
If an underscore character (_) comes before any name in the menu path, the template is not displayed in the menus.The last portion of the menu path is also used in the file name in the Visio user interface. For templates, the file name is displayed in the most-recently used templates list. For stencils, the file name is displayed in the title bar of the stencil.
Flowchart\Work Flow Diagram Shapes.
AltNames A semicolon-delimited list of alternate names for the file. If this value is specified, the value overrides any alternate names that are stored in the file by theAlternateNames property of the Document object. Work Flow Diagram Shapes.vss;workflow.vss

Triggering Visio rebuild template cache.

To tell Visio that new stencils/templates were installed, we should trigger cache update. This can be done by modifying registry value ConfigChangeID, which can be found under this key:

HKEY_LOCAL_MACHINE\Software\Microsoft\Office\Visio

Visio Solution Publishing too does this by embedding a small script that adds 1 to the current id:

Action “VisSolPublish_BumpVisioChangeId32”

Dim WshShell, visChangeId
Set WshShell = CreateObject("WScript.Shell")
Key = "HKLM\Software\Microsoft\Office\Visio\ConfigChangeID"
On Error Resume Next
visChangeId = WshShell.RegRead()
If Err = 0 Then WshShell.RegWrite Key, visChangeId + 1, "REG_DWORD"

With WiX, you have several options to implement this:

– Do it exactly the same way as Solution Publishing tool, i.e. add the following code to your installer:

<!-- define script action to increment Visio counter -->

<CustomAction
  Id="SetConfigChangeID"
  Script="vbscript"
  Execute="deferred"
  Impersonate="no"
  Return="check" >
<![CDATA[
    Set WshShell = CreateObject("WScript.Shell")
    Key = "HKLM\Software\Microsoft\Office\Visio\ConfigChangeID"
    On Error Resume Next
    visChangeId = WshShell.RegRead(key)
    If Err = 0 Then WshShell.RegWrite key, visChangeId+1, "REG_DWORD"
]]>
</CustomAction>

<!-- execute script action on install -->

<InstallExecuteSequence>
  <Custom Action="SetConfigChangeID" After="InstallInitialize" />
</InstallExecuteSequence>

– Implement a custom action which does that without scripting (see sample solution for implementation details).

I have attached two sample solutions which can be used as reference (templates) to build your own installer. The first one uses VBScript approach (implements the action to bump ConfigChangeID with vb-script), the second one implements an custom action which does that. Basically the setup deploys 2 templates, and two stencils.

WiX-based Visio Setup Demo (using unmanaged custom action) (44.0 KiB)

WiX-based Visio Setup Demo (using VBScript custom action) (37.9 KiB)

The solutions should build an installer (x86 or x64 version depending on the selected configuration) which installs a pair of templates and a pair of stencils in English and German. The installer should install stencils under category “X Stencils” and the templates under category “X Templates”. Should work with All Visio versions (2003 – 2013).

21-09-2011 0-25-13

Leave a Reply