Wednesday, August 22, 2012

Updating a Visual Studio 2010 Extension for Visual Studio 2012


UPDATE - 16 January 2013

The contents of this article have been updated to correct a problem that existed at the time of publication. In addition, I have uploaded this updated Visual Studio extension to the Visual Studio Gallery.

Hello everyone. It's been way too long. It seems I'm always doing this and that and never have time to write down anything, anywhere—whether that be on this blog, or on Facebook. But today, I have something special for those of you who have that favorite Visual Studio 2010 Extension that they just can't live without, but it hasn't been updated for Visual Studio 2012.

In order to update the extension, you will need access to the extension's source code; so these instructions will have limited impact for most of you out there unless you can get your hands on the source code for that favorite extension.

Fortunately for me, the author of my favorite extension, AllMargins, did post his source code, especially since this extension is no longer available from the Visual Studio Gallery.

Install the Visual Studio 2012 and 2012 SDKs

Get Visual Studio Professional 2012 with MSDN from the Microsoft Store

In order to author extensions for Visual Studio, one must have the Visual Studio SDK installed. The same is true for modifying them. If you don't already have it installed, go out and download it and install it.

Prepare the Source Code for Visual Studio 2012

If you want to maintain backward compatibility for the extension, it would be best not to open the original Visual Studio 2010 solution in Visual Studio 2012. That's because Visual Studio Extension projects for Visual Studio 2010 are not compatible with Visual Studio 2012. Well, that's not exactly true. The real truth is that the VSIX manifest XML schema has changed between Visual Studio 2010 and Visual Studio 2012. The old schema still works for Visual Studio 2012, but Microsoft would have you use the new schema going forward. The problem is, if you use the new schema, you won't be able to use the extension in Visual Studio 2010. Don't worry though, Visual Studio 2012 will not upgrade the schema, just the project file(s); but in doing so, the projects will no longer open in Visual Studio 2010.

Why should you care? Well, for one, testing. You can't simply instruct VsixInstaller to install the extension to an experimental instance of Visual Studio, unfortunately. That really makes it hard to test the extension for more than one version of Visual Studio. Even so, you really should be testing your extension on a virtual machine with the installed version of Visual Studio to test it with and which does not have the Visual Studio SDK installed. If the Visual Studio SDK is installed on your test machine, your extension will always work but, you may find that it doesn't work users who don't have the Visual Studio SDK installed. Your extension should not explicitly require the Visual Studio SDK be installed (unless you're writing a Visual Studio Extension project template! Lol...).

If you want to be able to develop and test in both Visual Studio 2010 and Visual Studio 2012 on the same machine, here's my suggestion.

  1. Create a new empty solution called <Your Extension>.2012 in the same place as the original solution.
  2. Open Windows Explorer to the location of one of the projects that are in the Visual Studio 2010 solution.
    1. Select the project file and copy and paste it into the same folder. The file will be renamed 'Copy of <Your Project File>.csproj' (or .vbproj, if you use Visual Basic). Rename the file to <Your Project File>.2012.csproj.
    2. Back in Visual Studio 2012, add <Your Project File>.csproj to your solution.
  3. Add all the files that are part of the Visual Studio 2010 project to the newly created Visual Studio 2012 project.
  4. Repeat these steps for each of the other projects that were part of the original Visual Studio 2010 solution.

Now you can work on the source code in both Visual Studio 2010 and Visual Studio 2012, opening the respective solution for the version of Visual Studio you're using to make changes. When you build the Visual Studio 2012 solution, it will be deployed to the Visual Studio 2012 experimental instance. The same is true for 2010, the extension will be deployed to the Visual Studio 2010 experimental instance. Also, it allows you to work on a single code-base that should work in both environments so long as you don't use features exclusive to Visual Studio 2012.

While upgrading this extension to work with Visual Studio 2012, I discovered that there is an enumeration value in the VSIX XML schema for specifying the Express editions of Visual Studio. However, the only "extensions" that Express SKUs support are project/item template extensions.

We're now ready to start modifying the various files to make this extension compatible with Visual Studio 2012!

Update the *.vsixmanifest file

The first order of business in updating the extension is to modify the *.vsixmanifest file. Here's an example of one of the files from the AllMargins.vsix extension:

<?xml version="1.0" encoding="utf-8"?>
<Vsix xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Version="1.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2010">
    <Identifier Id="SettingsStore.dpugh.ce3ce74a-4966-4a66-b9ad-a3adf4f9e940">
        <Name>SettingsStore</Name>
        <Author>dpugh</Author>
        <Version>1.2</Version>
        <Description xml:space="preserve">This defines an API for persisting IEditorOptions across sessions.</Description>
        <Locale>1033</Locale>
        <MoreInfoUrl>http://code.msdn.microsoft.com/OverviewMargin/Release/ProjectReleases.aspx?ReleaseId=3957</MoreInfoUrl>
        <SupportedProducts>
            <VisualStudio Version="10.0">
                <Edition>Ultimate</Edition>
                <Edition>Premium</Edition>
                <Edition>Pro</Edition>
            </VisualStudio>
        </SupportedProducts>
        <SupportedFrameworkRuntimeEdition MinVersion="4.0" MaxVersion="4.0" />
    </Identifier>
    <References />
    <Content>
        <MefComponent>|%CurrentProject%|

    </Content>
</Vsix>

You need to update the SupportedProducts and SupportedFrameworkRuntimeEdition elements as follows:

<SupportedProducts>
  <VisualStudio Version="10.0">
    <Edition>Utimate</Edition>
    <Edition>Premium</Edition>
    <Edition>Pro</Edition>
  </VisualStudio>
  <VisualStudio Version="11.0">
    <Edition>Utimate</Edition>
    <Edition>Premium</Edition>
    <Edition>Pro</Edition>
  </VisualStudio>
</SupportedProducts>
<SupportedFrameworkRuntimeEdition MinVersion="4.0" />

By removing the MaxVersion attribute for the SupportedFrameworkRuntimeEdition element, we're telling Visual Studio that so long as the machine supports the .NET Framework 4.0, the extension can be used.

Also for good measure, I updated the Version value (e.g. 1.3) and updated the Description element noting that I changed the VSIX package and it is not the original. As an aside, every time you make a change to the extension that you wish to distribute, you must increment the value for the Version element.

Now I ran across a tricky problem with updating the AllMargins extension. This extension has several "sub-extensions" that are contained within the AllMargins extension itself. And some of these "sub-extensions" have yet other "sub-extensions". The long and short is, during testing, Visual Studio had a problem locating some of the required DLLs.

What I found out is that some of the sub-extension projects contained an additional file—a *.pkgdef file. This is an older file that was used with VSPackages back in the VSI days of Visual Studio 2005/2008. This file is not much unlike a *.reg file, though with a slightly different syntax.

This file for the SettingsStore sub-extension (for which the VSIX manifest file was shown above) looks like this:

[$RootKey$\BindingPaths\{8ADD56CC-E512-4CB0-AF58-33ECCC0B4912}]
"$PackageFolder$"=""

This creates the GUID under HKCU\Software\Microsoft\VisualStudio\<Maj. Version Num>_Config\BindingPaths key. $PackageFolder$ expands to the folder where the extension was installed by VSIXInstaller.

Apparently, in Visual Studio 2010, just placing this file within your VSIX package was enough for Visual Studio to go ahead and create the requisite registry keys and values. However, this does not work with Visual Studio 2012 and attempts to use extensions relying on this extension result in a System.IO.FileNotFoundException. In order to resolve this issue, you must place some additional content in your VSIX manifest file as shown below.

<References>
    <Reference Id="Microsoft.VisualStudio.MPF" MinVersion="10.0" />
        <Name>Visual Studio MPF</Name>
    </Reference>
    <!-- Any other references you may have -->
</References>
<Content>
    <MefComponent>|%CurrentProject%|</MefComponent><!-- Expands to the assembly name -->
    <VsPackage>SettingsStore.pkgdef</VsPackage><!-- Not required by VS2010, but is required by VS2012 in order for the file to be processed -->
</Content>

With all of that out of the way, save the file and we're done with the *.vsixmanifest file. If there are several VSIX extensions that make up the extension you're updating (as is the case for AllMargins.vsix), you will need to do this for each *.vsixmanifest file in the solution.

At this point, at the original date of publication (22 August 2012), I had you retarget the projects in the solution and replace some DLL references. If you want to maintain compatibility with Visual Studio 2010, this is not necessary. So I have removed that section of the original blog entry.

Recompile a Debug Build

You should now recompile the solution using a Debug build. This will automatically install the extension(s) into the Visual Studio experimental instance(i.e. it won't muck up your Visual Studio that you use for everyday coding). Make sure that everything works correctly. If all is well, you're ready for the final step.

Recompile in Release Mode

If your testing above went OK, then change the build mode from Debug to Release and recompile. Then simply navigate to the bin\Release directory under the project folder for the extension and double-click the VSIX file to install it.

Now, in this case, I was not required to change a single line of code. This may not be the case for every extension you wist to upgrade. YMMV.

Enjoy using Visual Studio 2012

That's it! Enjoy using Visual Studio 2012 with your beloved extension.

5 comments:

  1. Hi Craig.
    Thank you your article.
    Do you have complied files on running Visual Studio 2012 Express.
    Best regards.

    ReplyDelete
    Replies
    1. Hazir, at the moment, I do not. Here's what I do know about support for Visual Studio Express editions. Officially, Microsoft says that extensions are not supported for Express Editions. So you would not be able to go to the Visual Studio Gallery and install any extensions. However, looking through the VSIX specification, it seems that Express Editions can be supported.

      In short, while the "official" stance is Express editions are not supported, it may be possible to support those editions (but again, perhaps there's something inside Visual Studio that prevents the loading of additional MEF components).

      If you have access to the AllMargins source code, you can try updating the source.extension.manifest files, adding the <Edition>Express_All</Edition> element to the //SupportedProductss/Visual Studio element. Then rebuild the project.

      If the VSIX Installer still doesn't want to install the extension (due to the feature being locked out by Microsoft), you can always try to unzip the extension (VSIX packages are merely ZIP files) into the following folder: %USERPROFILE%\AppData\Local\Microsoft\VisualStudio\11.0\Extensions.

      Make sure to put the files in a sub-folder of the above, such as AllMargins.

      I've actually been working on this extension now for the last two weeks. The source code available on line is version 2.3, but the last publicly released version on Visual Studio Gallery was v2.6. I'm in the process of updating the source code to match version 2.6. Later, I hope to add more features (like the ability to change options/colors right in Visual Studio|Tools|Options). While I'm messing with the code, I'll see if I can't figure out how to make this work on Express Editions, but I make no promises.

      If you try anything I suggested above, let me know how it turns out. Did it work? Did you get any errors? I'd be interested to know.

      Delete
  2. Hi Craig.
    Thank you your attention.
    I have the license of Visual Studio 2010 Premium. I havent had the license of Visual Studio 2012 yet. So I want to use some html5 specific properties of VS 2012 version. And I want to say that you can use some extensions in Visual Studio Express 2012 for Web. For example I have used DevColor and Highlight extensions in VS Express. I just copied the folders in "C:\Users\Administrator\AppData\Local\Microsoft\VisualStudio\11.0\Extensions" to the extension folder of Visual Studio Express "C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\VWDExpressExtensions"
    DevColor and Highlight worked in VS Express. But AllMargin didnt work. And I get some error in the editor of VS Express. It didnt format the code in *.cs files. So I returned to Visual Studio 2010. And I want to say something more that AllMargins works also in Visual Studio 2012 RC.

    Regards.

    ReplyDelete
    Replies
    1. Hazir:

      Just for kicks and grins, I tried publishing the updated AllMargins extension on Visual Studio Gallery with Visual Studio Express support. The gallery would not allow the extension to upload saying that Visual Studio Express editions only support Project Template and Item Template type extensions.

      As you have noted, you copied the folder where an extension was installed on a different version of Visual Studio to your current Express edition of Visual Studio 2012. While this is unsupported, you may want to try this with the AllMargins extension. Furthermore, the extension may have worked on Visual Studio vNext RC due to the fact that certain aspects of the RC were not yet updated. I assure you that extensions that are not updated for Visual Studio 2012 will not be able to be installed on Visual Studio 2012 (and I doubt they would run even if they were manually installed).

      Today, I just posted the updated AllMargins extension as AllMargins 2012 on Visual Studio Gallery. I hope you find it useful and that you'll be able to get it to work with Express editions. If you get it to work, reply to this comment what you did to get it to work. Others may find your experience most useful!

      Delete
  3. Hi

    I am implementing Visual studio 2012 Set up project. Which will install some Extensions. I should run below command from visual studio command prompt, after I ran our custom installer to view changes .This will reset visual studio.
    devenv /setup



    Now i am looking for any alternative solution to restart Visual studio once i Install/Uninstall in background i want to rest vs 2012.I don't want to use

    Process. Start

    Default option available in extension manager



    I want to reset Vs 2012 along with installation or Un-Installation of our Custom installer, so that i can view changes.

    ReplyDelete