How to convert Visual Studio 2012, 2010 setup project (vdproj) to WiX
In my last article I’ve shown you how to create a new WiX installer project. But, what if you already invested a good amount of time in creating a Visual Studio setup project (vdproj)? You could always create the setup project from scratch, but there has to be an easier way.
Lucky for us, there is a utility that comes bundled with the WiX toolset called Dark. According to the WiX website, Dark does the following:
Converts a Windows Installer database into a set of WiX source files. This tool is very useful for getting all your authoring into a WiX source file when you have an existing Windows Installer database. However, you will then need to tweak this file to accommodate different languages and breaking things into fragments.
The source Windows Installer project
For this example, I’ve created a very simple Add-in Express based Office add-in that adds a custom Ribbon Tab to Microsoft Word 2007, 2010 and 2013. Then, in Visual Studio 2010, I’ve created a new setup project (.vdproj) for the add-in by right-clicking on the project in the Visual Studio Solution Explorer and clicking on Create Setup Project.
I’ve kept the setup project standard and did not add anything after the New Setup Project wizard was completed. The setup project was built and a MyAddin1.msi and Setup.exe file generated.
Next, we’ll convert the newly built MSI file to a WiX source file (.wxs) using the Windows Installer Xml Decompiler also known as Dark.
Using Dark to get the WiX source file
Dark is a separate executable which you can find in the bin sub folder of the WiX installation folder, in my case the full path to the Dark.exe file is C:\Program Files (x86)\WiX Toolset v3.6\bin To use Dark, we need to open up a new Command Prompt window and change the working path to the one mentioned above. To see how to use Dark and the available list of options, simply type Dark and hit Enter.
We’ll keep things simple by copying the MyAddin1.msi file (which was generated when we built our setup project) to the Temp folder on our PC.
Next, in the Command Prompt window type the following command:
dark C:\Temp\MyAddin1.msi C:\Temp\MyAddin1.wxs
The first parameter is the MSI file that will act as the input, and the second parameter specifies the path and file name of the WiX source file that needs to be created.
Creating a new WiX setup project
Now that we’ve reverse engineered our existing MSI to a WiX source file, we need to create a new WiX Setup Project in order to build a new MSI. To do this, add a new Windows Installer XML Setup Project to your Office add-in solution in Visual Studio.
The WiX Setup Project automatically contains a Product.wxs source file; we’ll use this file to configure our new setup program.
Next, we need to add three references to our setup project:
- A reference to your add-in project;
- WixNetFxExtension, which contains a bunch of custom actions that will make it easier to include .Net in your setup package; and
- WixUIExtension – this assembly contains a set of pre-defined UI elements.
To add a reference to your setup project, click on the Add Reference… item in the Visual Studio Project menu.
After you’ve added the references, paste the content of the WiX source file, we’ve created using Dark, into the Product.wxs file inside the newly created WiX setup project in Visual Studio.
Fixing up Product.wxs
The first thing you’ll notice is that there are a bunch of Binary elements with their SourceFile attribute values set to "FILE NOT EXPORTED, USE THE dark.exe -x OPTION TO EXPORT BINARIES". You can use the –x switch to instruct Dark to extract all the binaries, but I chose not to in this example, as I wanted to show you how to do this manually. It is also much neater than having to rename a bunch of files with random GUIDs as names.
Remove all the Binary elements except the one where the ID is DefBannerBitmap and change its SourceFile attribute value to point to a Bitmap file that will act as the header of your setup. E.g.
<Binary Id="DefBannerBitmap" SourceFile="C:\temp\HeaderBanner.bmp" />
Next, we need to work through the list of files that need to be included in your setup project; you’ll find them inside the Directory element. We’ll need to change all the Source attribute values to point to the actual files.
<Directory Id="TARGETDIR" Name="SourceDir"> <Component Id="C__065924003BD749BC864364CB30199C11" Guid="{C908B576-2B12-E734-8D85-F84AE25C4444}"> <File Id="_065924003BD749BC864364CB30199C11" Name="adxloader64.dll" KeyPath="yes" DiskId="1" Source="$(var.MyAddin1.ProjectDir)Loader\" /> </Component> <Component Id="C__0AC4BB0B2D0448E3A2CF7CCB287D6D0E" Guid="{1D174771-8B40-6462-3FB3-DFDA68ECF136}"> <File Id="_0AC4BB0B2D0448E3A2CF7CCB287D6D0E" Name="adxregistrator.exe" KeyPath="yes" DiskId="1" Source="C:\Program Files (x86)\Add-in Express\Add-in Express for .NET\Redistributables\adxregistrator.exe" /> </Component> <Component Id="C__8EA103A45B3240E2B46A6F57B0813E32" Guid="{8472A48B-CA3D-17B0-44F9-22D323E5945F}"> <File Id="_8EA103A45B3240E2B46A6F57B0813E32" Name="adxloader.dll.manifest" KeyPath="yes" DiskId="1" Source="$(var.MyAddin1.ProjectDir)Loader\" /> </Component> <Component Id="C__9EA6EED144ED5B47648F1476EA34ED7D" Guid="{C6062172-3560-988A-F588-BF034DD60023}"> <File Id="_9EA6EED144ED5B47648F1476EA34ED7D" Name="Microsoft.Office.Interop.Word.dll" KeyPath="yes" Assembly=".net" AssemblyManifest="_9EA6EED144ED5B47648F1476EA34ED7D" AssemblyApplication="_9EA6EED144ED5B47648F1476EA34ED7D" DiskId="1" Source="$(var.MyAddin1.TargetDir)" /> </Component> <Component Id="C__A2755A83C577A0F6092F11AC40EB13EF" Guid="{A70D0D48-6EB7-8D24-7E46-91C92794CBEA}"> <File Id="_A2755A83C577A0F6092F11AC40EB13EF" Name="AddinExpress.MSO.2005.dll" KeyPath="yes" Assembly=".net" AssemblyManifest="_A2755A83C577A0F6092F11AC40EB13EF" AssemblyApplication="_A2755A83C577A0F6092F11AC40EB13EF" DiskId="1" Source="C:\Program Files (x86)\Add-in Express\Add-in Express for .NET\Bin\" /> </Component> <Component Id="C__D52786AC7149F0231627B093627B6775" Guid="{782F7F32-2E41-E2A1-0600-521EBDB2048E}"> <File Id="_D52786AC7149F0231627B093627B6775" Name="Extensibility.dll" KeyPath="yes" Assembly=".net" AssemblyManifest="_D52786AC7149F0231627B093627B6775" AssemblyApplication="_D52786AC7149F0231627B093627B6775" DiskId="1" Source="C:\Windows\assembly\GAC\Extensibility\7.0.3300.0__b03f5f7f11d50a3a\" /> </Component> <Component Id="C__DAF38BE32B2FE1EFD477FB2847703E4C" Guid="{29DE2CE7-B6B3-B17E-7D0B-D1C07D8006DD}"> <File Id="_DAF38BE32B2FE1EFD477FB2847703E4C" Name="Microsoft.Vbe.Interop.dll" KeyPath="yes" Assembly=".net" AssemblyManifest="_DAF38BE32B2FE1EFD477FB2847703E4C" AssemblyApplication="_DAF38BE32B2FE1EFD477FB2847703E4C" DiskId="1" Source="$(var.MyAddin1.TargetDir)" /> </Component> <Component Id="C__E369ACDA2B434E21BB456611DF57C948" Guid="{2BFDAA20-6B68-A2FE-9006-D2FF91336BE7}"> <File Id="_E369ACDA2B434E21BB456611DF57C948" Name="adxloader.dll" KeyPath="yes" DiskId="1" Source="$(var.MyAddin1.ProjectDir)Loader\" /> </Component> <Component Id="C__FA0D921C71C696B3B423E77B2276147B" Guid="{570831DE-5EB7-61B3-699B-012E4529BC81}"> <File Id="_FA0D921C71C696B3B423E77B2276147B" Name="Office.dll" KeyPath="yes" Assembly=".net" AssemblyManifest="_FA0D921C71C696B3B423E77B2276147B" AssemblyApplication="_FA0D921C71C696B3B423E77B2276147B" DiskId="1" Source="$(var.MyAddin1.TargetDir)" /> </Component> <Component Id="C__958E2FA67D97A5C49B66D90255B05F75" Guid="{6AB3926A-22C8-ED44-6FC0-66C4C7BF7083}"> <File Id="_958E2FA67D97A5C49B66D90255B05F75" Name="MyAddin1.dll" KeyPath="yes" Assembly=".net" AssemblyManifest="_958E2FA67D97A5C49B66D90255B05F75" AssemblyApplication="_958E2FA67D97A5C49B66D90255B05F75" DiskId="1" Source="$(var.MyAddin1.TargetPath)" /> </Component> <Directory Id="DesktopFolder" SourceName="User's Desktop" /> <Directory Id="ProgramMenuFolder" SourceName="User's Programs Menu" /> </Directory>
You can change the IDs of the File elements to make it easier to read and identify later. Just remember to also change the ID of the ComponentRef element inside the Feature element.
To make sure that you’ve made all the necessary changes, build your setup project and work through the errors if any. Once all the errors have been resolved and you’ve successfully built the setup project for your Office add-in, the MSI file will be inside the project’s bin folder.
Run the MSI and you will see your existing setup project.
Dark is smart enough to preserve the original UI of your MSI installer, therefore you will still see the same user interface for the setup program that you’re used to.
I’ve covered just a small portion on how you can convert your existing vdproj to a WiX project. If your vdproj is complex the process of converting it to WiX will obviously be more involved.
Updated on 21-Feb-2013:
Now I can suggest even a better alternative – VDProj to WiX Converter. This extension for Visual Studio 2012-2005 lets you convert your vdproj setups to WiX in 1 click!
Thank you for reading. Until next time, keep coding!
Available downloads:
This sample add-on was developed using Add-in Express for Office and .net:
Sample Visual Studio solution
2 Comments
Wix is a peice of shit I’ve an msi created .wsx with dark its xml more than 10,000 lines how will you add/edit new changes in it ???? that’s not a good solution I deleted it make msi in VS 2010 and work in vs 2012
Hi Afzal,
You are right, the WiX scheme is fairly complex and the resulting XML may be very large if your setup project contains a lot of components, files, etc. But since Visual Studio 2012 does not provide any built-in setup projects, WiX may be one of possible options.
Thank you for your feedback.