Installing VSIX package via WiX installer

Introduction

WiX Toolset is a powerful set of tools used to create Windows installations packages. Unfortunately it’s learning curve is quite steep and the documentation is not it’s strong point. That’s why I decided to show you, step by step, how to create an installer for your VSIX packages. I will not cover all of the WiX features as this is not intended to be an exhaustive WiX guide but I will describe in detail what is necessary to deploy a VSIX package. Also I will add some interesting details that can be useful more in general when creating WiX installers. The end result should be a MSI installation file that will correctly install and uninstall your VSIX package. Let’s start.

It’s true that VSIX leverages an installer on it’s own. Still you should consider this approach if your installation is more complex and/or requires other components to be installed.

Prerequisites

In order to follow this example you will need any version of Visual Studio starting from 2010 till the most recent 2015. Also any sku except the Express is fine. You will need a Visual Studio SDK and WiX Toolset installed. The examples you will find are made w Visual Studio 2013 and WiX 3.9 R2. You can download them from here (SDK and WiX).

Creating the necessary projects

In order to start our practical example, let’s first create the necessary project that we are going to use by our installer later. Create a new project in Visual Studio and choose a “VSIX Project”.
I will name it MyAwesomeExtension.

MyAwesomeExtension

Once the project is created you will be presented by the vsixmanifest designer. You can leave all the defaults. Make sure only that the Product ID is set in the unique way and that, for commodity, it doesn’t contain spaces.

EmptyVSIXProjectWiX

This should be it for what concerns our extension. I will not focus on creating Visual Studio extensions and this is just enough to have an extension registered and working. If you hit F5 you should start another instance of Visual Studio, by default in Experimental Mode, and if you check inside Tools > Extensions and Updates menu you should find your newly created extension.

The next thing is adding a WiX Setup Project into your solution. I will simply call it Installer.

AddingInstaller

This was about it. In the next paragraph I will show you how to install your VSIX package using WiX.

WiX Toolset installer

First thing first. We are going to take advantage of a standard custom action offered by WixVSExtension. In order to do so, we need to reference the WixVSExtension.dll. You can find it inside the WiX installation folder which in my case is C:\Program Files (x86)WiX Toolset v3.9bin. Be aware that the Add reference panel for the WiX setup projects is custom and it slightly differs from the default one. Aside of having the necessary to help us installing (and uninstalling) VSIX packages, it also contains many other useful properties and custom actions that will ease interacting with Visual Studio. You can find a list of the properties and custom actions here.
After the reference to the project is added we need to include the WixVSExtension namespace in our main wxs file (by default Product.wxs). In the Wix element next to the default namespace add the following xmlns:VSExtension="http://schemas.microsoft.com/wix/VSExtension". The end result should look like this:



...

Now we are going to add another reference to our Wix project and it will point to our VSIX project. This is done for commodity so that we can point Wix to the output of our VSIX project. Once this is done we need to define a component that will leverage the custom action defined in WixVSExtension that will actually install our VSIX. Inside the fragment where an example of ComponentGroup is defined, we are going to remove all of the code inside it, comprehensive of ComponentGroup itself. Define the following:


  
    
    
  

Let’s analyze what we added.
First element we added is a Component, that we called for convenience C_MyAwesomeExtension, we assigned a unique identifier to our component (so that MSI can track this element) and we specified the folder in which this component should be deployed. I will not get into details of what a component is and how it works, I do suppose you already know that and if not you can find more info here.

Inside our component we specified two elements. The simpler one to understand is for sure the File element. We gave an id to the file that we do need in order to deploy our VSIX and named it by using the name of the compiled assembly. In order to retrieve the name I used a variable that was generated by Wix because of the reference to the project we added, appending to the result the .vsix string. Now, each time you reference a project Wix will create several variables dynamically and they will be at your service. A full list of them you can find at this link. In case we were referencing a project that will output an executable or a library, we could use the TargetFileName variable and omit the .visx. However as by default Wix doesn’t know nothing about VSIX project types and outputs, we need to use TargetName property and concatenate .vsix to it in order to get a file name with the correct extension.

Same thing we did with the source attribute. With it we do specify where this file should be copied from in order to be placed inside the MSI installation file. As for the Name attribute, we are going to use some of auto generated variables to get to the correct path of our compiled VSIX.

VSExtension:VsixPackage element

Let’s focus on the main character of this article, the VSExtension:VsixPackage element. I will describe all of the attributes I used and also the one I haven’t and describe the behavior that they do produce.

File
File, as the name suggest, requires to be set to the file name that we used in our MSI tables and points to our VSIX installer. Simply said it needs to be the same as the Id attribute we used for the File element that we discussed earlier. In this way the custom action will know where is the VSIX file that we are planning to install.

PackageId
This is a very important value. Earlier I mentioned the Product ID, when we were creating our VSIX extension. Well that’s it, the unique product ID that is set inside vsixmanifest file in your extension. Make sure that it does not contain any spaces and if so add quote marks and escape them properly.

Target
You can specify one of the following values: integratedShell, professional, premium, ultimate, vbExpress, vcExpress, vcsExpress, vwdExpress. It will indicate which edition (SKU) of Visual Studio is required in order to register this extension.

TargetVersion
Specifies the version of Visual Studio for which to register the extension. Should contain a version number as at example 11.0 in case of Visual Studio 2012 or 14.0 in case of Visual Studio 2015.

Vital
In indicates if the failure of the installation of the VSIX extension will cause a rollback of the whole installation.

Permanent
Often underestimated and forgotten parameter. This is the reason of many complains about the extension not uninstalling on msi uninstall. And that’s all about it. If set to no, your extension will be uninstalled once you try to uninstall your product. If set to yes, your extension will not be removed in case the user uninstalls the product.

VsixInstallerPathProperty
As this custom action relies on VsixInstaller.exe to trigger the installation of the VSIX, it needs to know where the VsixInstaller.exe is located in order to use it. It is recommended not to set this attribute and let it be populated by the custom action itself. By default, the latest VsixInstaller.exe on the machine will be used to install the VSIX package.

Believe it or not this is sufficient to let the Wix install your VSIX extension. In our case we do target the Visual Studio 2013 and accepting any edition from professional above.

Behind the scene

So what’s the magic behind this custom action? The simplest way to verify what is happening is to compile our project and launch the installation. Before we are able to this there are two minor things we need to take care of. Inside our Feature element we need to change the ComponentGroupRef to ComponentRef and point the id to our C_MyAwesomeExtension component. Also to make the output a single file, we will tell Wix to integrate the cabinet inside the msi itself. To do so under the MediaTemplate element we are going to add the EmbedCab attribute and set it’s value to yes.




  

We can compile now our project and position our self in the build output directory. A file called Installer.msi should be there.
In order to see what is happening we can’t just double click our newly created msi. We need to launch the installation from the command prompt and request the verbose logging to be activated. To request the log file being emitted we need to launch the following command: msiexec /i Installer.msi /l*v install.log. This will tell the msi installer to install our application and output a verbose log inside the file named install.log.
If you execute this command, you will briefly see installation starting and that’s it. This is because we haven’t chosen any UI for this installation. It’s not in our scope showing how to create/choose and UI for the installer.
Let’s check our default install folder at C:\Program Files (x86)Installer. Bingo! Our extension is there. Now open your Visual Studio 2013 instance and check the Extensions and updates window. Again, MyAwesomeExtension is there!

MyAwesomeExtensionInstalled

Open the newly created log file to see what was done in order to achieve this. Open the install.log file and search for “/skuName:Pro /skuVersion:12.0”. The line you landed on is the command that was executed by our VSExtension:VsixPackage custom action. The full command is following:

C:\Program Files (x86)Microsoft Visual Studio 12.0Common7IDEVSIXInstaller.exe /q /skuName:Pro /skuVersion:12.0 “C:\Program Files (x86)InstallerMyAwesomeExtension.vsix” /admin

What happened here? Well nothing special. When you double click your vsix file, the vsix extension is associated with VSIXInstaller.exe and it will show you the following window:

MyAwesomeExtensionVSIXInstaller

Same thing with our custom action, it calls directly VSIXInstaller.exe and triggers the quite mode (so no UI is shown) and passes the necessary parameters in order for VSIXInstaller.exe to preform the installation. Do you recognize the other parameters? That’s right, the do match what we have specified with the attributes on our VSExtension:VsixPackage element. Execept the last /admin parameter. It implies that the extension will be installed to the admin extension location. If you prefer it to be installed on per user basis, you will need to create a perUser installation, thus, set the Package InstallScope to perUser.

You can get through the log file and probably you will find plenty of interesting information, like the search for the VSIXInstaller.exe and the values that are set in order to accommodate it, etc.

The same thing is done for what concerns the uninstall. We can launch the uninstall with the following command: msiexec /x Installer.msi /l*v unistall.log. As you can see it is similar to the install except that instead of /i we used a /x parameter. Once you execute it you will be prompted for the confirmation:

MyAwesomeExtensionUninstall

By confirming that, the uninstallation will be preformed.

Get inside the log file and search again for /skuName:Pro /skuVersion:12.0. You will land on line that triggers the following command:

C:\Program Files (x86)Microsoft Visual Studio 12.0Common7IDEVSIXInstaller.exe /q /skuName:Pro /skuVersion:12.0 /u:”MyAwesomeExtension.majcica.com.420d4ff9-340c-4867-9247-c85ab370ec7b” /admin

Please notice that the /u parameter is passed which will indicate to VSIXInstaller.exe to remove the extension with product Id (and not the vsix file anymore) that matches the unique ID of our extension.

Tuning the installer

There are a couple of things we could take care of. One of them is to check if the requested Visual Studio is installed. This in order to prevent an eventual exception and a consequent installation failure. As this is fairly simple I will add the necessary info to this post.

Everything we need to know about the Visual Studio been installed. WixVSExtension puts on our disposition this info in form of a property. In case Visual Studio is installed, the property will be populated, otherwise will not. Only thing we need to do is to reference the property, which in our case is called VS2013DEVENV, and create a condition that verifies if it is set.




  

After adding this code inside the product element, compile, and launch your installation, you will get the following message, which eventually will interrupt and prevent the installation.

NoVS2013

Another thing I can think of is installing the extension to multiple versions of Visual Studio. You could declare several components, each one targeting the same file but different TargetVersion, and add a condition to each of them. Example:


  VS2012DEVENV
  



  VS2013DEVENV
  

Conclusion

I hope I answered all of the questions you may have regarding installing VSIX packages via Wix. If there is anything I omitted and you would like to know more about, please do not hesitate to ask in the comments.
For completeness I will now list the complete content on the Product.wxs file.



  
    

    

    
      

    
    

    
      
    
  

  
    
      
        
      
    
  

  
    
      
      
    
  

Happy coding!

Deploying snippets within VSIX package

Introduction

If you ask Google, “what are code snippets”, rapidly you will get the following answer:

Code snippets are ready-made snippets of code you can quickly insert into your code. For example, the for code snippet creates an empty for loop. Some code snippets are surround-with code snippets, which enable you to select lines of code, and then choose a code snippet which incorporates the selected lines of code.

I will not get into on how to create code snippets or getting in to details about how do they work. In case you are interested in that, you can read the following article on MSDN. What I’m interested to show here, is not such an obvious thing, that is, how to deploy you snippets via VSIX package and have it registered in Visual Studio as an extension (with all of the benefits of that choice).
Before I started with this task, I have only found a single article speaking about this procedure. On Mads Kristensen’s blog you will find a blog post titled Shipping Visual Studio snippets in an extension. You could now ask yourself, why are you then writing about this? Well, first of all, that blog has several technical issues (at the time of writing) and images are not visualized nor the layout is in place which makes it extremely hard to follow. As the second thing, in order to accomplish successfully this task, that guide misses several important steps which I will try to describe more in detail and moreover give you a working example of code.
There is another way of deploying code snippets and you can find on MSDN the following article about distributing code snippets via Visual Studio Content Installer. I will not go to describe the differences and pros and cons of this two methods. Both of them are valid ways of approaching this problem and based on your situation you should choose the direction to follow.

Background

Before we start, make sure that you have downloaded and installed the Visual Studio SDK. It should match the version of Visual Studio you are using. For the 2013 version you can download it from here.
Once installed, beside other things, you will get some new project templates in Visual Studio, as shown in the following picture:

NewProjectExtensions
At this point we are going to create one snippet that we are going to deploy later on.
Create a text file with a snippet extension, in my case it will be called helloworld.snippet. The content of our file is the following

<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>Hello World</Title>
      <Author>Mario Majcica</Author>
      <Description>For demo purposes inserts a simple Hello World in your code</Description>
      <HelpUrl>http://blog.majcica.com/2014/10/27/deploying-snip…n-vsix-package/</HelpUrl>
      <SnippetTypes />
      <Keywords />
      <Shortcut></Shortcut>
    </Header>
    <Snippet>
      <References />
      <Imports />
      <Declarations />
      <Code Language="csharp" Kind="method body" Delimiter="$"><![CDATA[Console.WriteLine("Hello, World!")]]></Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>

This is the simplest code snippet ever!
Save it to a convenient location as we are going to use this file later. You can easily create you snippets by a dedicated tool. I found on Codeplex a great freeware tool called “Snippet Editor” which does the job very well.

Great job guys!

Creating the deployment project

Open Visual Studio and create a new VSIX Project. Once you click OK, a new project will be generated and you will be presented with the following screen:

EmptyVSIXProject
What you can see is a typical vsixmanifest designer window (can be different in case you are not using Visual Studio 2013). You can feel free to change this fields accordingly to your needs and you will find plenty of guides about this argument by simply ‘googling’ vsix package. We can close this window for now.
As a next thing we will add a folder in our solution and call it ‘Snippets’. Another sub-folder will be added in my case and I will call it ‘My snippets’. In this sub folder I will add the file we previously created, our helloworld.snippet. It should all look like this:

SnippetsSolution
We are still not done with it. For each code snippet file you added, we need to make sure that the prroperties are set in the right way, otherwise your snippets will not be a part of VSIX package. Right click you code snippet and chage the Build Action to ‘Content’ and Include in VSIX to ‘True’. Once done, it should look like this:

SnippetSettings
You will need to do the same for all the snippets that you added inside this project. Bare in mind that you can select multiple files in the Solution Explorer and do this operation only once.

Once this is done, the only thing we are missing is a way to register our snippets. A package definition can be really handy for this task.

Registering with pkgdef

A package definition (.pkgdef) file is way to encapsulate application configuration information in an easily editable, distributable, and deployable form. It was introduced in Visual Studio 2008 SP1 to support the configuration of Isolated Shell applications. From Visual Studio 2010, .pkgdef files take on a more expanded role and are much more integrated into both the IDE and the Shell (Integrated and Isolated).
Package definition file looks a lot like a .reg file as exported from the Registry Editor. There is one key difference: the root of the registry key (e.g., “HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\12.0“) has been abstracted into the token “$RootKey$”. This, and several other tokenized values for registry keys and paths, allows a given .pkgdef file to be reusable for multiple applications and portable to any machine.
Package files can be easy leveraged by VSIX projects. Once the pkgdef file is added inside the project it is sufficient to add it as an asset inside the VSIX manifest and the job is done. It means it will be executed by the installation process. Let’s check in detail how this is achieved.
First of all create a text file in root of your project and name it snippets.pkgdef. As a content specify the following

// C#
[$RootKey$\Languages\Code\Expansions\CSharp\Paths]
"MySnippets"="$PackageFolder\$Snippets\My Snippets"

As you can see I’m using several tokens (substitution Strings) as $RootKey$ and $PackageFolder$. You can find a list of these strings at the following address.
What this code does is creating a key in the registry, called MySnippets, in the path HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\12.0\Exp_Config\Languages\Code\Expansions\CSharp\Paths
(in our case, which is VS2013 and experimental version, so 12.0\Exp_Config key will defer based on your environment, this also means that the $RootKey$ is replaced dynamically with a different string, depending on the context). The value of my MySnippets key equals to $PackageFolder\$SnippetsMy Snippets where $PackageFolder$ will be substituted by the full path of the directory in which files are deployed.
Once the file is created we need to “wire” it to the VSIX package. Open your manifest designer and move to the Assets tab

Assets
Click on new to add a new asset and set it up in the following way

AddNewAsset
The asset should be of VsPackage type and source should be set to ‘File on filesystem’. For the path choose the path to your .pkgdef file.
Click OK and the job is done.
If you prefer to get here by editing the vsixmanifest without the designer, you can add following inside the PackageManifest element:


  

Deploy and test

We can quickly check if our extension is working as expected. A simple hit to F5 will launch Visual Studio in Experimental mode and deploy our extension. Let’s try it out.
First of all we will check if the extension is deployed. Go to the TOOLS -> Extensions and updates... menu. You should find your extension there. It should look lit similar to the following picture:

ExtensionsAndUpdates
If this is right, second thing to check is if the snippets are correctly registered. Go to the TOOLS -> Code Snippets Manager... or press CTRL + K, CTRL + B.
Once the Code Snippets Manager window opens, in the Language drop down, choose Visual C#, and you should see your snippets registered and visible to Visual Studio as show in the following picture

CodeSnippetManager
You can now build for release your project and distribute your SnippetsCollection.vsix package. All other files you will find in the bin folder are not necessary. Installation is straight forward and if you have decided to support multiple versions of Visual Studio, the only thing you will get prompted is for which version of Visual Studio you whish to install your extension.

Considerations

This article shows a graceful way to distribute your code snippets. It is also a neat solution when it comes to the maintenance as just by increasing the version of the VSIX package you will be able to deploy your changes. If you decide to distribute your VSIX packages through a private gallery, you will make the installation and update as simple as possible for all of your users.
You can read more about this argument here and here.
You also may consider deploying your wsix as part of an installer and soon I will write more about this argument.
In case of debugging problems you can check one of my previous post Resetting the Visual Studio Experimental instance.
If any do not hesitate to comment.

Resetting the Visual Studio Experimental instance

Recently, I got into developing a couple of extensions for Visual Studio. As many of you know, once you create Visual Studio Package project (or any VSIX project), by default your application will be set to start debugging in a Visual Studio Experimental instance.

To safeguard your Visual Studio development environment from untested extensions that might change it, the Visual Studio provides an alternative Visual Studio instance that you can use to experiment. You are going to develop new extensions by using Visual Studio as usual, but you will run them by using this experimental instance.

This behavior is set as default by the Visual Studio Package project template and you can see it the following screenshot:

ExperimentalInstanceSettings

As you can see, we are pointing to the Visual Studio executable (we can vary that parameter for testing our extension with different versions of Visual Studio) and we are passing the following command line arguments to it:

/RootSuffix Exp

This is sufficient to start Visual Studio in Experimental instance mode and once you hit F5 and start debugging you will notice that the started instace of visual studio in the application title bar contains the “Experimental Instance” suffix.

ExperimentalInstanceDebugging

The default location of the experimental instance depends on the Visual Studio version number. For example, for Visual Studio 2013, the location is

%localappdata%\Microsoft\VisualStudio\12.0Exp\

All the files in the directory location are considered part of that instance. Any additional experimental instances will not be loaded by Visual Studio unless the directory name is changed to the default location.

Till here all fine, but what happens once you have “ruined” your experimental instance environment?
Well, you will need to reset it. Although you can find all of this information on MSDN, it isn’t linked or clear enough on how to proceed.

Inside the

C:\Program Files (x86)\Microsoft Visual Studio 12.0\VSSDK\VisualStudioIntegration\Tools\Bin

folder you will find a utility called CreateExpInstance. Open your command prompt and position yourself in just mentioned directory (this is the default path for Visual Studio 2013 SDK, the same applies also for Visual Studio 2012, just change your path accordingly).

All you need to do now is to execute the following command

CreateExpInstance /Reset /VSInstance=12.0 /RootSuffix=Exp

Once the cleanup is performed, the next experimental instance you lunch will found itself in a clean environment. In case you are working with Visual Studio 2012 change the VSInstance parameter to 11.0.

You can find more details about the CreateExpInstance Utility here.