A wrong way of checking the Visual Studio version where an add-in is loaded

Take a look at this code of an add-in that checks that it is loaded only in Visual Studio 2012 and try to figure out what’s wrong:

private DTE2 _applicationObject;
private AddIn _addInInstance;

public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
{
   const string REGISTRY_KEY_VS_11_0 = "SOFTWARE\MICROSOFT\VISUALSTUDIO\11.0";

   string addInRegistryRoot = null;

   _applicationObject = (DTE2)application;
   _addInInstance = (AddIn)addInInst;

   switch (connectMode)
   {
      case ext_ConnectMode.ext_cm_AfterStartup:
      case ext_ConnectMode.ext_cm_Startup:

         addInRegistryRoot = _applicationObject.RegistryRoot.ToUpper();

         if (!addInRegistryRoot.StartsWith(REGISTRY_KEY_VS_11_0))
         {
            System.Windows.Forms.MessageBox.Show("This add-in only works with Visual Studio 2012");
         }
         break;
   }
}

If you have discovered it, either you are quite expert on globalization issues or you are a Turkish developer. My MZ-Tools add-in had similar code that has worked correctly for years until a few weeks ago, when a developer reported that using the Turkish culture (user interface, language input keyboard, etc.) MZ-Tools refused to load. You can simulate that effect inserting the following line at the start the OnConnection method that sets the Turkish culture for the current thread:

System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.GetCultureInfo(“tr-TR”);

The reason is that in Turkish, the upper case of the character i is not I but İ (with a dot), as explained here. So _applicationObject.RegistryRoot.ToUpper() returns the following string:

“SOFTWARE\MİCROSOFT\VİSUALSTUDİO\11.0”

which is different from:

“SOFTWARE\MICROSOFT\VISUALSTUDIO\11.0”

Of course, the solution is to use _applicationObject.RegistryRoot.ToUpperInvariant() or an overloaded version of StartsWith() that uses the ordinal or invariant culture comparison ignoring the case.

So, if you make software for international markets, ensure that you run the Code Analysis feature of Visual Studio with the Microsoft Globalization Rules, because two rules are violated with the code above:

– CA1304: Specify CultureInfo (in _applicationObject.RegistryRoot.ToUpper())
– CA1307: Specify StringComparison (in sAddInRegistryRoot.StartsWith(REGISTRY_KEY_VS_11_0))

LearnVSXNow! (about Visual Studio packages), by Istvan Novak (DiveDeeper’s blog)

MVP fellow Istvan Novak wrote long time ago a long series of small articles about Visual Studio Extensibility (VSX) with packages on his DiveDeeper’s blog.

I have added a new section to my Resources about Visual Studio .NET extensibility page with sorted links to all of them:

LearnVSXNow!, by Istvan Novak (DiveDeeper’s blog)
http://www.mztools.com/resources_vsnet_addins.aspx#LearnVSXNow