{"id":1973,"date":"2010-06-09T12:48:47","date_gmt":"2010-06-09T12:48:47","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/visualstudio\/2010\/06\/09\/vsix-best-practices\/"},"modified":"2022-10-12T15:22:04","modified_gmt":"2022-10-12T22:22:04","slug":"vsix-best-practices","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/visualstudio\/vsix-best-practices\/","title":{"rendered":"VSIX Best Practices"},"content":{"rendered":"<p>This post is about a new way to install extensions to Visual Studio, introduced in VS 2010, called the VSIX file. The information it contains will be of most interest to readers who develop Visual Studio extensions, but I encourage users who download and install those extensions to read it as well.<\/p>\n<p>A VSIX file conforms to the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/magazine\/cc163372.aspx\">ECMA Open Packaging Conventions (OPC) standard<\/a>. It\u2019s created as part of a VSIX project build in Visual Studio, and you can view its contents with any zip file utility. If you upload your VSIX to the <a href=\"http:\/\/visualstudiogallery.msdn.microsoft.com\/en-us\/\">Visual Studio Gallery<\/a>, your customer can install it right in Visual Studio, in the new <a href=\"http:\/\/weblogs.asp.net\/scottgu\/archive\/2010\/05\/03\/visual-studio-2010-extension-manager-and-the-new-vs-2010-powercommands-extension.aspx\">Extension Manager<\/a>:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/06\/8764.image_thumb_5D008069.png\"><img decoding=\"async\" style=\"border-width: 0px;\" title=\"image\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/06\/8764.image_thumb_5D008069.png\" alt=\"image\" width=\"915\" height=\"247\" border=\"0\" \/><\/a><\/p>\n<p>It can also be installed by downloading and double clicking on the file, and uninstalled either in the Extension Manager, or by simply deleting the associated files. You can find introductory information about VSIX <a href=\"https:\/\/learn.microsoft.com\/en-us\/archive\/blogs\/quanto\/\">here<\/a> and <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/dd997148.aspx\">here<\/a>.<\/p>\n<p>The VSIX feature comes with a lot of options. In most cases you don\u2019t have to understand them all. This post is a list of tips that will give you some guidance about how to use the new VSIX capabilities in the best way. Here\u2019s what I\u2019m going to talk about:<\/p>\n<ul>\n<li>How to package your extension into a VSIX in the simplest way<\/li>\n<li>How to install via MSI if you need to<\/li>\n<li>How to use VSIX versioning<\/li>\n<li>What to avoid<\/li>\n<\/ul>\n<p><strong>Packaging your extensions using VSIX<\/strong><\/p>\n<ul>\n<li><strong>Use <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/wd40t7ad.aspx\">strong names<\/a> for all your assemblies<\/strong>. You don\u2019t want your \u201cutil.dll\u201d to collide with somebody else\u2019s; if you don\u2019t use strong names the system won\u2019t distinguish between them, and somebody will get a run time error.<\/li>\n<li><strong>Distribute your whole product in one independent VSIX <\/strong>if you can. The feature does allow one VSIX to depend on another. But, save that for situations where each one is developed and shipped separately, because shipping a single VSIX will reduce the amount of information you have to understand.<\/li>\n<li><strong>If you ship more than one VSIX, and they share common assemblies<\/strong>, copy the common assemblies into each separate VSIX. This has the effect of shipping your whole product in one VSIX described above. There\u2019s no runtime harm in shipping copies of common assemblies \u2013 in memory the CLR will only load one:\n<a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/06\/2055.image_thumb_7A08464C.png\"><img decoding=\"async\" style=\"border-width: 0px;\" title=\"image\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/06\/2055.image_thumb_7A08464C.png\" alt=\"image\" width=\"719\" height=\"290\" border=\"0\" \/><\/a>\nBut be aware that it will load only one, and the first one loaded wins. So you should ship updates to all your VSIXs that contain common assemblies together.<\/li>\n<li><strong>If your product is extending another extension<\/strong>, then your VSIX needs to take a dependency on the target VSIX using either the Select Installed Extension or Manual Reference choice in the dialog below (which you raise by clicking the Add Reference button in the VSIX Manifest Editor).\n<a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/06\/5584.image_thumb_18DEBA2B.png\"><img decoding=\"async\" style=\"border-width: 0px;\" title=\"image\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/06\/5584.image_thumb_18DEBA2B.png\" alt=\"image\" width=\"972\" height=\"230\" border=\"0\" \/><\/a>\n<a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/06\/3580.image_thumb_64D89CB1.png\"><img decoding=\"async\" style=\"border-width: 0px;\" title=\"image\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/06\/3580.image_thumb_64D89CB1.png\" alt=\"image\" width=\"427\" height=\"443\" border=\"0\" \/><\/a>\nIn this case<\/p>\n<ul>\n<li>Read the Versioning section below to understand the best way to specify the version of your target VSIX in this dialog.<\/li>\n<li>Stay aware of your target extension\u2019s updates, and test to make sure your extension is still compatible with each update.<\/li>\n<\/ul>\n<\/li>\n<li><strong>If your VSIX publishes an API that another VSIX will use<\/strong>\n<ul>\n<li>Read the versioning section below to understand how your users will expect your versioning to behave.<\/li>\n<li>Maintain <a href=\"https:\/\/learn.microsoft.com\/en-us\/archive\/blogs\/jmstall\/binary-vs-source-compatibility\">binary compatibility<\/a> between versions if you can; this just makes life simpler for your extenders.<\/li>\n<li>Keep your extenders aware of approaching updates so they can test against them. Make sure they know in advance if you plan to release a version that breaks compatibility.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><strong>Installing via MSI<\/strong><\/p>\n<p>Some extensions still need to be installed by MSI: for example some of your files might have to be in a specific, well-known loca\ntion, you might have a component like an MSBuild task that VSIX install doesn\u2019t support, you might need to use binding redirection \u2013 see more information <a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/vsix-and-msi\/\">here<\/a>. There\u2019s no problem with doing that. In fact, we provide a way for an MSI installed extension to make itself visible in the new Extension Manager, so that the customer can see all his extensions in one place.<\/p>\n<p>To make your extension visible in the Extension Manager, your MSI install should create a subdirectory in the Extensions directory for the hosting product:<\/p>\n<blockquote><p>For a non-administrative, per-user install (recommended) in Visual Studio, the path will look like this:\nUsers<em>user id<\/em>AppDataLocalMicrosoftVisualStudio10.0Extensions<em>your companyextension nameversion<\/em>\nand for a per-machine install:\nProgram Files<em>VS 10.0 install directory<\/em>Common7IdeExtensions<em>your companyyour extension nameversion\n<\/em>An Isolated Shell application will define its own Extension directory.<\/p><\/blockquote>\n<p>In that folder, put the extension.vsixmanifest file built by your VSIX project, with an added element that marks it as installed by MSI:<\/p>\n<blockquote>\n<pre> &lt;Identifier Id=\"VSIXProject2.Microsoft IT.8532242f-afdc-44fa-82b2-0b6b5afc1c38\"&gt;\r\n\u00a0\u00a0\u00a0 &lt;Name&gt;VSIXProject2&lt;\/Name&gt;\r\n    <strong><span style=\"color: #008040;\">&lt;InstalledByMsi&gt;true&lt;\/InstalledByMsi&gt;<\/span><\/strong><\/pre>\n<p>\u2026\n&lt;\/Identifier&gt;<\/p><\/blockquote>\n<p>Note that although the user will then see the extension in the Extension Manager, since it\u2019s installed by MSI, he still needs to manage it through Windows Add\/Remove Programs.<\/p>\n<p><strong>Versioning<\/strong><\/p>\n<p>If your extension is self-contained (i.e. you distribute it in a single VSIX that doesn\u2019t have any dependencies on other ones), and no other VSIXs will depend on yours (i.e. your VSIX doesn\u2019t expose any APIs), you don\u2019t need to read this section. If your VSIX does offer or consume APIs, or you distribute multiple VSIXs with common shared assemblies, read on for more information.<\/p>\n<p>First, let\u2019s do a quick review of how versioning works in the CLR. For an assembly with a <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/wd40t7ad.aspx\">strong name<\/a>, its CLR identity comes from a combination of the file name on disk, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/51ket42z.aspx\">Assembly Version string<\/a>, an optional cultural attribute, and a digital signature. When one assembly references (i.e. consumes APIs from) another one, the consumer is targeted to a particular version of the referenced assembly at build time. (<a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/2fc472t2(VS.80).aspx\">Binding redirection<\/a> can change this at run time, but the VSIX installer doesn\u2019t support that yet.) The version string contains four segments: &lt;major version&gt;.&lt;minor version&gt;.&lt;build number&gt;.&lt;revision&gt; (for example \u201c1.2.123.0\u201d). The recommended convention for using the version string is that when an assembly\u2019s API breaks <a href=\"https:\/\/learn.microsoft.com\/en-us\/archive\/blogs\/jmstall\/binary-vs-source-compatibility\">binary compatibility<\/a>, the major version is incremented. (Note that I\u2019m talking about Assembly Version, which is part of the strong name, <em>not<\/em> Assembly File Version, which is purely informational \u2013 you can use Assembly File Version any way you like. See more information <a href=\"http:\/\/support.microsoft.com\/kb\/556041\">here<\/a>.)<\/p>\n<p>That\u2019s all background information. Now let\u2019s talk about using versioning with VSIX files. The first thing I\u2019m going to recommend, although it probably sounds a little unexpected, is that you <em>not<\/em> change the Assembly Version strings when you ship an update of your VSIX. This is because, as I mentioned above, the VSIX installer doesn\u2019t support binding redirection yet, so if you do change any segment of an assembly version number, you may break downstream VSIXs that depend on the old version number of your assembly. The VSIX file has its own mechanism for version management, and I recommend that you use that one instead, because its added flexibility gets you around the binding redirection issue.<\/p>\n<p><em>For a VSIX that uses an API from another VSIX:<\/em><\/p>\n<p>The syntax of a VSIX version string is the same as the assembly one, and we will use the recommended convention to indicate that a new release breaks binary compatibility with the old one: incrementing the major version number. The big advantage of the VSIX versioning mechanism is that if you\u2019re consuming an API from another VSIX, you can specify a range of version numbers of the target VSIX that you\u2019re compatible with. Let\u2019s see how this works. When you raise the Add VSIX Reference dialog in the VSIX Manifest Editor:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/06\/5584.image_thumb_18DEBA2B.png\"><img decoding=\"async\" style=\"border-width: 0px;\" title=\"image\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/06\/5584.image_thumb_18DEBA2B.png\" alt=\"image\" width=\"972\" height=\"230\" border=\"0\" \/><\/a><\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/06\/3580.image_thumb_64D89CB1.png\"><img decoding=\"async\" style=\"border-width: 0px;\" title=\"image\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/06\/3580.image_thumb_64D89CB1.png\" alt=\"image\" width=\"427\" height=\"443\" border=\"0\" \/><\/a><\/p>\n<p>in the Version fields just above, you can specify a range between minimum and maximum version numbers that you\u2019re compatible with. If the developer of the VSIX whose API you consume obeys the versioning conventions, you can specify a range like from Min 1.0 to Max 1.9999 to indicate that you will use any version of your dependency between those two. When the VSIX you depend on installs, for example, version 1.2, you will be compatible with it. When the user attempts to install 2.0, the installer will recognize the incompatibility:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/06\/5265.image_thumb_2CCE79F3.png\"><img decoding=\"async\" style=\"border-width: 0px;\" title=\"image\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/06\/5265.image_thumb_2CCE79F3.png\" alt=\"image\" width=\"314\" height=\"184\" border=\"0\" \/><\/a><\/p>\n<p>and display a warning dialog:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/06\/3438.image_thumb_11534ABE.png\"><img decoding=\"async\" style=\"border-width: 0px;\" title=\"image\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/06\/3438.image_thumb_11534ABE.png\" alt=\"image\" width=\"456\" height=\"343\" border=\"0\" \/><\/a><\/p>\n<p>If the user updates the extension you depend on anyway, your extension will be disabled because of the incompatibility, and he should look for an update from you that\u2019s compatible with the new version of the API.<\/p>\n<p>If for any reason you believe you are dependent on a specific version of the target extension, you can code that number as the Min and Max values to target only that version:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/06\/0572.image_thumb_02CE7BCB.png\"><img decoding=\"async\" style=\"border-width: 0px;\" title=\"image\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/06\/0572.image_thumb_02CE7BCB.png\" alt=\"image\" width=\"239\" height=\"209\" border=\"0\" \/><\/a><\/p>\n<p>If you only code the Min value, you will bind to anything equal or higher. I don\u2019t recommend that, because binary compatibility breakage (in the example below, from 1.x to 3.0) can lead to run time errors.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/06\/3531.image_thumb_62473C18.png\"><img decoding=\"async\" style=\"border-width: 0px;\" title=\"image\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/06\/3531.image_thumb_62473C18.png\" alt=\"image\" width=\"316\" height=\"185\" border=\"0\" \/><\/a><\/p>\n<p><em>For a VSIX that offers an API to other VSIXs:<\/em><\/p>\n<p>If you release an extension that offers an API, you should handle the versioning at the VSIX level. This means leaving the Assembly Version string unchanged across releases, and incrementing your VSIX version number (shown in the VSIX manifest editor below).<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/06\/3482.image_thumb_0D9401FB.png\"><img decoding=\"async\" style=\"border-width: 0px;\" title=\"image\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/06\/3482.image_thumb_0D9401FB.png\" alt=\"image\" width=\"439\" height=\"352\" border=\"0\" \/><\/a><\/p>\n<p>It\u2019s great for your consumers if your API can maintain binary compatibility across releases. If you need to break compatibility, increment the major version number. But at that point, when the VSIX installer upgrades your extension, all the consumers of your API will have to ship releases that are compatible with the new API.<\/p>\n<p><strong>Things to avoid<\/strong>:<\/p>\n<ul>\n<li style=\"list-style-type: none;\">\n<ul>\n<li>Embedding one VSIX inside another (using the Add payload selection in the Add VSIX Reference dialog).\n<a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/06\/1030.image_thumb_41C82B41.png\"><img decoding=\"async\" style=\"border-width: 0px;\" title=\"image\" src=\"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-content\/uploads\/sites\/4\/2010\/06\/1030.image_thumb_41C82B41.png\" alt=\"image\" width=\"396\" height=\"411\" border=\"0\" \/><\/a><\/p>\n<p>In the current version of Visual Studio, certain combinations of embedded VSIXs and version updates don\u2019t install properly. This feature should be avoided for now; the safest practice is to install VSIXs that have a dependency relationship separately.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><strong>Summary<\/strong><\/p>\n<p>In this article we looked at a set of recommendations for using the new VSIX feature. What I want to leave you with is: minimize complexity. Take advantage of the new VSIX features as you need them, but keep your life as simple as possible by using only the features you need. That way the VSIX install experience will be simple for your customers, which is the\u00a0 reason VSIX was invented.<\/p>\n<p>Please feel free to post comments and questions!<\/p>\n<p>Gary Horen<\/p>\n<p>Program Manager, Visual Studio Extensibility<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This post is about a new way to install extensions to Visual Studio, introduced in VS 2010, called the VSIX file. The information it contains will be of most interest to readers who develop Visual Studio extensions, but I encourage users who download and install those extensions to read it as well. A VSIX file [&hellip;]<\/p>\n","protected":false},"author":13,"featured_media":255385,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[155,1029],"tags":[85],"class_list":["post-1973","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-visual-studio","category-web","tag-asp-net"],"acf":[],"blog_post_summary":"<p>This post is about a new way to install extensions to Visual Studio, introduced in VS 2010, called the VSIX file. The information it contains will be of most interest to readers who develop Visual Studio extensions, but I encourage users who download and install those extensions to read it as well. A VSIX file [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/posts\/1973","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/users\/13"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/comments?post=1973"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/posts\/1973\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/media\/255385"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/media?parent=1973"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/categories?post=1973"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/visualstudio\/wp-json\/wp\/v2\/tags?post=1973"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}