Part 1: In this post I am covering the setup environment for creating the wix setup project, generate GUID, Link to Part 2.
Part 2 will cover generate MSI of the product by Wix variable defining, product details, organizing directory, components and shortcut for your projects, Link to Part 1 & Part 3.
Part 3 will cover the bundling, Link to Part 3 & Part 4.
Part 4 will cover providing custom UI to your setup and signing the bundle. Link to Part 3.
- Visual Studio. (http://go.microsoft.com/?linkid=9863608).
- Download and install wix toolset to your system, this will provide you the wix project template in visual studio. (https://wix.codeplex.com/).
How to create a wix setup project in visual studio?
Firstly you need to install the wix toolset find link in the prerequisites.
Then Add reference to the setup project.
There are many way to generate GUID, one of them is shown below with visual studio.
Creating installer for the desktop application with the help of the wix series Part 2
How to create MSI for your product by Wix?
Defining variable in the wix
<?define nameOfVariable = value ?>
If you want to create installer targeting x64 or x86 machine it depends on your requirement, here i am creating installer for x64 bit machine.
<?xml version="1.0" encoding="UTF-8"?> <?define ProcessorArchitecture = x64 ?> <?define Property_ProductVersion = "1.0.0.0" ?> <?define Property_Manufacturer = "Manufacture Name" ?> <?define Property_ProductName = "Product Name" ?> <!-- Set a specific product code based on the processor architecture build variable and you can also define your “if else” condition as follows--> <?if $(var.ProcessorArchitecture)=x64 ?> <?define Property_ProductCode = "YourGUIDGoesHere" ?> <?else ?> <?define Property_ProductCode = "YourGUIDGoesHere" ?> <?endif ?> <?define Property_UpgradeCode = "YourGUIDGoesHere" ?>
Defining Wix for your product.
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"> <Product Id="*" Name="$(var.Property_ProductName)" Language="1033" Version="$(var.Property_ProductVersion)" Manufacturer="$(var.Property_Manufacturer)" UpgradeCode="$(var.Property_UpgradeCode)"> <?if $(var.ProcessorArchitecture)=x64 ?> <Package Id="*" InstallerVersion="200" Compressed="yes" Platform="x64" InstallScope="perMachine" InstallPrivileges="elevated" Description="$(var.Property_ProductName)" Manufacturer="$(var.Property_Manufacturer)" /> <?else ?> <Package Id="*" InstallerVersion="200" Compressed="yes" InstallScope="perMachine" AdminImage="yes" InstallPrivileges="elevated" Description="$(var.Property_ProductName)" Manufacturer="$(var.Property_Manufacturer)"/> <?endif ?>
The media table defines the location that the MSI will look to find source files during
installation or repair scenarios. In this case, the source files are in a cab file that will be embedded directly into the MSI at build time. EmbedCab=”yes” means that it will generate a single msi of your product.
<MediaTemplate EmbedCab="yes" />
Define the directory structure for your product to get installed on which folder location on the target machine. This is a list of directories that are used by this product as installation locations or custom action file search locations.
<Directory Id="TARGETDIR" Name="SourceDir"> <!-- Define the directory structure for program files --> <!-- Install the application to the ProgramFiles64Folder for the 64-bit MSI.--> <?if $(var.ProcessorArchitecture)=x64 ?> <Directory Id="ProgramFiles64Folder" Name="Program Files"> <Directory Id="APPLICATIONROOTDIRECTORYMANU" Name="$(var.Property_Manufacturer)"> <Directory Id="APPLICATIONROOTDIRECTORY" Name="$(var.Property_ProductName)"> <Directory Id="APPLICATIONROOTDIRECTORYIMAGES" Name="Images"/> </Directory> </Directory> </Directory> <?else ?> <!-- Install the application to the ProgramFilesFolder for the 32-bit MSI.--> <Directory Id="ProgramFilesFolder" Name="Program Files"> <Directory Id="APPLICATIONROOTDIRECTORYMANU" Name="$(var.Property_Manufacturer)"> <Directory Id="APPLICATIONROOTDIRECTORY" Name="$(var.Property_ProductName)"> <Directory Id="APPLICATIONROOTDIRECTORYIMAGES" Name="Images"/> </Directory> </Directory> </Directory> <?endif ?> <!-- Define the directory structure program menu folder--> <Directory Id="ProgramMenuFolder"> <Directory Id="ApplicationProgramsFolderManufacturer" Name="$(var.Property_Manufacturer)"> <Directory Id="ApplicationProgramsFolder" Name="$(var.Property_ProductName)"/> </Directory> </Directory> <!-- Define the directory structure program menu folder--> <Directory Id="DesktopFolder" Name="Desktop"/> </Directory>
Once you have declared the directory structure for your product to be installed then its time to declare the component for those directories. For simplicity i am just taking one component for my product. “Source” is the path to the exe of the product in my case i have wpf project, so i am pointing it to the bin/release folder of the wpf project.
<!-- Add files to your installer package --> <DirectoryRef Id="APPLICATIONROOTDIRECTORY"> <!-- Add the 64-bit component to the 64-bit MSI--> <?if $(var.ProcessorArchitecture)=x64 ?> <Component Id="$(var.Property_ProductName).exe_$(var.ProcessorArchitecture)" Guid="YourGUIDGoesHere" Win64="yes"> <File Id="$(var.Property_ProductName).exe_$(var.ProcessorArchitecture)" Source="..\bin\Release\$(var.Property_ProductName).exe" KeyPath="yes" Checksum="yes" /> </Component> <?else?> <!-- component to the 32-bit MSI. --> <Component Id="$(var.Property_ProductName).exe_$(var.ProcessorArchitecture)" Guid="YourGUIDGoesHere"> <File Id="$(var.Property_ProductName).exe_$(var.ProcessorArchitecture)" Source="..\bin\Release\$(var.Property_ProductName).exe" KeyPath="yes" Checksum="yes"/> </Component>
Now its time to add component for the images folder that i create under the root of the application installed folder.
<DirectoryRef Id="APPLICATIONROOTDIRECTORYIMAGES"> <!-- Add the 64-bit component to the 64-bit MSI, and add the 32-bit registry --> <?if $(var.ProcessorArchitecture)=x64 ?> <Component Id="$(var.Property_ProductName)FolderImages_$(var.ProcessorArchitecture)" Guid="YourGUIDGoesHere" Win64="yes"> <File Id="SnapScreen1.png_$(var.ProcessorArchitecture)" Source="..\Images\SnapScreen1.png"/> </Component> <?else?> <!-- component to the 32-bit MSI.--> <Component Id="$(var.Property_ProductName)FolderImages_$(var.ProcessorArchitecture)" Guid="YourGUIDGoesHere">
Now its time to define the component for the shortcut of my product on desktop, start menu
<Component Id="ApplicationShortcut_$(var.ProcessorArchitecture)" Guid="YourGUIDGoesHere" Win64="yes"> <!--Create folders--> <CreateFolder Directory="ApplicationProgramsFolderManufacturer"/> <CreateFolder Directory="ApplicationProgramsFolder"/> <!--Remove folders--> <RemoveFolder Id="RemoveApplicationProgramsFolder" Directory="ApplicationProgramsFolder" On="uninstall"/> <RemoveFolder Id="RemoveApplicationProgramsFolderManufacturer" Directory="ApplicationProgramsFolderManufacturer" On="uninstall"/> <!--Create Shortcut at start menu item--> <Shortcut Id="ApplicationStartMenuShortcut_$(var.ProcessorArchitecture)" Name="$(var.Property_ProductName)" Description="$(var.Property_ProductName)" Target="[APPLICATIONROOTDIRECTORY]$(var.Property_ProductName).exe" WorkingDirectory="APPLICATIONROOTDIRECTORY" Directory="ApplicationProgramsFolder"/> <!--Create registry for the Shortcut at start menu item--> <RegistryValue Root="HKCU" Key="Software\$(var.Property_Manufacturer) \$(var.Property_ProductName)" Name="StartMenuShortcut" Type="integer" Value="1" KeyPath="yes"/> <!--Create Shortcut at desktop--> <Shortcut Id="desktopShortcut_$(var.ProcessorArchitecture)" Directory="DesktopFolder" Name="$(var.Property_ProductName)" Target="[APPLICATIONROOTDIRECTORY] $(var.Property_ProductName).exe" WorkingDirectory="APPLICATIONROOTDIRECTORY"/> <!--Create registry for the Shortcut at desktop--> <RegistryValue Id="regDesktopShortcut_$(var.ProcessorArchitecture)" Root="HKCU" Key="Software\$(var.Property_Manufacturer)\$(var.Property_ProductName)" Name="DesktopShortcut" Type="integer" Value="1"/> <!-- Add the uninstall shortcut to your installer package --> <Shortcut Id="UninstallProduct_$(var.ProcessorArchitecture)" Name="Uninstall $(var.Property_ProductName)" Description="Uninstall $(var.Property_ProductName)" Target="[System64Folder]msiexec.exe" Arguments="/x [ProductCode]" Icon="UnInstallAppIcon.ico"/> <RemoveFolder Id="ApplicationProgramsFolder" On="uninstall"/> <RegistryValue Root="HKCU" Key="Software\$(var.Property_Manufacturer) \$(var.Property_ProductName)" Name="StartMenuUninstalledShortcut" Type="integer" Value="1"/> </Component>
Now we add icons for the app and map that icons to the property of the product. that will be displayed in exe and launching shortcut as desktop, menu item. “SourceFile” is the path to the icon file for your product that you wanted to use later for your product, desktop shotcut, add/remove program file.
<Component Id="ApplicationShortcut_$(var.ProcessorArchitecture)" Guid="YourGUIDGoesHere" Win64="yes"> <!--Create folders--> <CreateFolder Directory="ApplicationProgramsFolderManufacturer"/> <CreateFolder Directory="ApplicationProgramsFolder"/> <!--Remove folders--> <RemoveFolder Id="RemoveApplicationProgramsFolder" Directory="ApplicationProgramsFolder" On="uninstall"/> <RemoveFolder Id="RemoveApplicationProgramsFolderManufacturer" Directory="ApplicationProgramsFolderManufacturer" On="uninstall"/> <!--Create Shortcut at start menu item--> <Shortcut Id="ApplicationStartMenuShortcut_$(var.ProcessorArchitecture)" Name="$(var.Property_ProductName)" Description="$(var.Property_ProductName)" Target="[APPLICATIONROOTDIRECTORY]$(var.Property_ProductName).exe" WorkingDirectory="APPLICATIONROOTDIRECTORY" Directory="ApplicationProgramsFolder"/> <!--Create registry for the Shortcut at start menu item--> <RegistryValue Root="HKCU" Key="Software\$(var.Property_Manufacturer)\$(var.Property_ProductName)" Name="StartMenuShortcut" Type="integer" Value="1" KeyPath="yes"/> <!--Create Shortcut at desktop--> <Shortcut Id="desktopShortcut_$(var.ProcessorArchitecture)" Directory="DesktopFolder" Name="$(var.Property_ProductName)" Target="[APPLICATIONROOTDIRECTORY]$(var.Property_ProductName).exe" WorkingDirectory="APPLICATIONROOTDIRECTORY"/> <!--Create registry for the Shortcut at desktop--> <RegistryValue Id="regDesktopShortcut_$(var.ProcessorArchitecture)" Root="HKCU" Key="Software\$(var.Property_Manufacturer)\$(var.Property_ProductName)" Name="DesktopShortcut" Type="integer" Value="1"/> <!-- Add the uninstall shortcut to your installer package --> <Shortcut Id="UninstallProduct_$(var.ProcessorArchitecture)" Name="Uninstall $(var.Property_ProductName)" Description="Uninstall $(var.Property_ProductName)" Target="[System64Folder]msiexec.exe" Arguments="/x [ProductCode]" Icon="UnInstallAppIcon.ico"/> <RemoveFolder Id="ApplicationProgramsFolder" On="uninstall"/> <RegistryValue Root="HKCU" Key="Software\$(var.Property_Manufacturer) \$(var.Property_ProductName)" Name="StartMenuUninstalledShortcut" Type="integer" Value="1"/> </Component>