Custom Extension Types with VSIX

Custom Extension Types with VSIX

Rate This
  • Comments 6

DISCLAIMER: While the following technique is supported in Visual Studio 2010, the interfaces and methods exposed by Microsoft.VisualStudio.ExtensionManager.dll are likely to change in future Visual Studio releases. If you create an extension that relies on Microsoft.VisualStudio.ExtensionManager.dll, there is no guarantee that your extension binary will work on future Visual Studio releases without code changes.

If you’ve used the VSIX Manifest editor when creating an extension for Visual Studio 2010, you may have noticed the various options when you add content to the VSIX container. Clicking the “Add Content” button will bring up a dialog that allows you to select a content type.

AddContentDialog

Most of the choices are well-known types that Visual Studio already knows how to consume:

  • Project/Item Template: A collection of VSTemplate zip files from which a user can create projects and project items.
  • Template Wizard: An assembly (distributed with one or more VSTemplates) that contains a template wizard extension to show UI or perform custom logic at template instantiation time.
  • VS Package: A PkgDef file containing configuration information for a VSPackage.
  • MEF Component: An assembly to be queried and consumed by the VS MEF Host for extending the core text editor and other MEF-based subsystems in the IDE.
  • Toolbox Control: An assembly containing one or more controls to publish on the Toolbox for use in the various UI designers in Visual Studio.

You may be wondering what the “Custom Extension Type” entry (highlighted above) is and why you would want to use it.

Let’s say you want to ship an extension to Visual Studio that is itself extensible. If the extensibility points you are exposing involve managed code, a MEF-based solution would be a reasonable option to consider. However, imagine that what you consume from your extenders is more like data or content rather than code. [For a real world example, consider the built-in Project/Item Template extension content types.] In this case, having these extension authors create an assembly (and having Visual Studio load and manage it at runtime) simply to provide data or content is too heavyweight.

This is where the content with a Custom Extension Type comes in handy. “OK”, you may be thinking. “But why couldn’t I just have end-users put these content files into a certain directory on the local machine where my extension would find them?” You certainly could. However, the advantage of using VSIX content with a Custom Extension Type is that the content can be managed by the end-user via the Extension Manager. Installing and removing the content is exactly the same user experience as for any other extension.

Walkthrough: Consuming Custom Extension Content

Let’s create an extension to demonstrate consuming custom content distributed in a VSIX. In this walkthrough, we’ll create a tool window called Image Browser that queries the Extension Manager for content of type WalkthroughImage. Then, we’ll create another extension that provides the content that our tool window will consume. (You must have the Visual Studio 2010 SDK installed to complete the walkthrough.)

  1. Open the New Project dialog to create a new Visual Studio Package from the Extensibility category under Visual C# called “ImageBrowser”.
  2. In the Visual Studio Package Wizard, select the “Tool Window” option on Page 3.
  3. Rename “My Tool Window” to “Image Browser” on Page 5.
  4. After completing the wizard, replace the content inside the <Grid> element in MyControl.xaml with the following:
    <ScrollViewer>
    <WrapPanel Name="wrapPanel1" />
    </ScrollViewer>

  5. Add a reference to Microsoft.VisualStudio.ExtensionManager.dll (located in <VSInstallDirectory>\Common7\IDE\PrivateAssemblies)
  6. In MyControl.xaml.cs, add the following method: 
    internal void AddImageFromPath(string path)
    {
    const int ImageWidth = 250;
    BitmapImage bitmapImage = new BitmapImage();
    bitmapImage.BeginInit();
    bitmapImage.UriSource = new Uri(path);
    bitmapImage.DecodePixelWidth = ImageWidth;
    bitmapImage.EndInit();
    this.wrapPanel1.Children.Add(new Image()
    {
    Source = bitmapImage, MaxWidth = ImageWidth
    });
    }

  7. Close MyControl.xaml.cs
  8. Open MyToolWindow.cs and add the following using statement:
    using Microsoft.VisualStudio.ExtensionManager;

  9. Add the following code at the end of the MyToolWindow constructor:
    //Query the Extension Manager for content of type "WalkthroughImage" const string WalkthroughImageContentType = "WalkthroughImage"; 
    IVsExtensionManager extensionManager = ServiceProvider.GlobalProvider.GetService(typeof(SVsExtensionManager)) as IVsExtensionManager;
    if (extensionManager != null)
    {
    foreach (string image in extensionManager.GetEnabledExtensionContentLocations(WalkthroughImageContentType))
    {
    ((MyControl)base.Content).AddImageFromPath(image);
    }
    }

  10. Press F5 to debug the extension in the Experimental instance. You can show the tool window you just created from Views –> Other Windows –> Image Browser, but there won’t be any images in the tool window just yet.
  11. Close the Experimental instance and return to your previous VS instance.

Walkthrough: Creating an Extension with Custom Content

 

Now let’s create another extension that will provide content to our tool window we just created. We’ll create a VSIX containing the sample images included in Windows 7 so that they display in our Image Browser tool window.

  1. In the Solution you created in the previous walkthrough, add a New Project to the solution.
  2. In the New Project dialog, select the “VSIX Project” template from under Visual C# –> Extensibility or Visual Basic –> Extensibility. (There won’t be any code to compile, so the language choice here doesn’t matter.)
  3. Name the project SampleImagePack and Click OK.
  4. In the VSIX Manifest Designer after the project is created, click the “Add Content” button.
  5. Choose “Custom Extension Type” for the content type.
  6. In the Type field, enter “WalkthroughImage”.   (without the quotes)
  7. For the source, choose the File radio button and navigate to the Sample Pictures in Windows. (They are located in the Public Pictures folder.)
  8. Select one of the images in the folder.
  9. Click OK in the Add Content dialog.
  10. Repeat steps 4-9 for each image you wish to add.
  11. Press F5 to debug both the Image Browser tool window extension and the SampleImagePack extension in the Experimental instance.
  12. Show the image browser tool window from View –> Other Windows –> Image Browser and notice that the images added to the SampleImagePack are now displayed in the ImageBrowser control.
  13. (optional) You can repeat the steps above to create multiple image pack VSIX’s which will be merged together in the Image Browser tool window.

When you bring up the tool window, you should see something like this:

Image Browser

We’re looking forward to seeing how you use this functionality for your own extensions! As always, please let us know what you think.

aaronm3_2[1]

Aaron Marten - Developer, Visual Studio Platform

Short Bio: Aaron has been on the Visual Studio team for over 6 years with a focus on extensibility. For Visual Studio 2010, Aaron worked on the Extension Manager and the Visual Studio SDK. In addition to contributing to the Visual Studio blog, he also writes about extending the IDE on his own blog at http://blogs.msdn.com/aaronmar.

Leave a Comment
  • Please add 2 and 6 and type the answer here:
  • Post
  • Sorry for posting this here, but it might also be of interest for others:

    Lisa Feigenbaum, Microsoft’s Program Manager for the VB Community,mentioned an a Visual Studio extension that enables rich WPF-based visualizations of XML doc comments:

    http://blogs.msdn.com/vseditor/archive/2009/05/13/visualizing-xml-doc-comments.aspx

    Question: where can we find this extension, any references?

    Thank you in advance.

  • @Will

     I sent Lisa an e-mail about your question, I got an automatic reply that she is in Orlando at a Visual Studio launch event until the 23rd, so not sure how quickly she will get back to you (I included a link to this comment section).  I imagine it may be the case of something whipped up internally as a proof of concept, otherwise it seems she would have linked the extension in the article.  In general you can find extensions in the VS Gallery, either through VS (the Extension Manager on the Tools menu) or through this link

    http://visualstudiogallery.msdn.microsoft.com/en-us/

    Ryan

  • Great article Ryan! When I saw the title I thought it may be about something long and painful, well quite the opposite, short and sweet! Now I know I don't need to pull out all my hair to write a VS2K10 extension :)

  • @Will:

    The screenshots Lisa included are genuine (i.e. not mockups), but the extension they're demonstrating is more of a prototype.  We're hoping to clean it up, publish it as a .vsix, and make the code available as a sample at some point, but unfortunately it's not available today and I can't promise a specific timeline yet.

    Brittany Behrens

    Program Manager, VS Platform - Editor

  • In a specific scenario that I have, I need to include all files in a specified  folder into the VSIX package. However, the list of files that this folder would contain will be known only when the VSIX package is built on the Build Server. Right now, if I know the list of files to add, I could add the <Content> element in the project file (one for each file) and set its  <IncludeInVSIX> to true. But since the list of files to include are not known until the VSIX package is built, do you know of any specific way that I can use either in the project file or in the source.extension.vsixmanifest to indicate that all files in the folder must be included in the VSIX package ?. Thanks in advance for your help

  • @Umesh,  You could include all the items via a wildcard in MSBuild. (msdn.microsoft.com/.../ms171453.aspx)  For example, put the following in an ItemGroup in your project file:

    <Content Include="*.txt">

     <IncludeInVSIX>true</IncludeInVSIX>

    </Content>

Page 1 of 1 (6 items)