Article ID: 555321 - Last Review: May 31, 2005 - Revision: 1.0

INFO: Visual Studio .NET Add-In Commands Disappear On Next Session

Author: Carlos Quintero MVP
Expand all | Collapse all

SUMMARY

This article describes why commands created by Visual Studio .NET add-ins disappear on the next session and how to restore them.

SYMPTOMS

This article describes why commands created by Visual Studio .NET add-ins disappear on the next session and how to restore them.

MORE INFORMATION

Using the wizard provided by Visual Studio .NET to create add-ins ("Other Projects", "Extensibility Projects", "Visual Studio .NET Add-in" project kind) the 4th step allows you to create a "Tools" menu item through the checkbox under the question "Would you like to create UI for the user to interact with your Add-in?". Selecting this checkbox will cause the following code (VB.NET) to appear in your OnConnection method:
 
Public Sub OnConnection(ByVal application As Object, ByVal connectMode As Extensibility.ext_ConnectMode, _
   ByVal addInInst As Object, ByRef custom As System.Array) _
   Implements Extensibility.IDTExtensibility2.OnConnection
 
   applicationObject = CType(application, EnvDTE.DTE)
   addInInstance = CType(addInInst, EnvDTE.AddIn)

   If connectMode = Extensibility.ext_ConnectMode.ext_cm_UISetup Then

      Dim objAddIn As AddIn = CType(addInInst, AddIn)
      Dim CommandObj As Command
  
      Try
         CommandObj = applicationObject.Commands.AddNamedCommand(objAddIn, "MyAddin15", _
            "MyAddin15", "Executes the command for MyAddin15", True, 59, Nothing, 1 + 2)  
            '1+2 == vsCommandStatusSupported+vsCommandStatusEnabled

         CommandObj.AddControl(applicationObject.CommandBars.Item("Tools"))

      Catch e as System.Exception
      End Try
 
   End If

End Sub
 
As you can see, the command is created only when the connectMode parameter value is ext_cm_UISetup, and that happens only once in the whole life of the add-in: when the add-in is loaded for the first time for the current user. This is convenient because add-ins should not create commands on startup and destroy them on shutdown. Rather, they should be created only once to load faster and to preserve keyboard bindings created by the user for those commands.
 
Visual Studio .NET knows if it is the first time that the add-in is loaded (and therefore if it must pass the value ext_cm_UISetup in the connectMode parameter) through a Windows Registry key:
 
- For add-ins installed only for the current user, the registry key is HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\7.x\Addins\MyAddin.Connect\CommandPreload, where x = 0 for Visual Studio .NET 2002 and x = 1 for Visual Studio .NET 2003. A value of 1 in the CommandPreload entry indicates that the add-in wants to be loaded once with the ext_cm_UISetup flag. Once loaded that first time, the value of CommandPreload is set to the value 2, and the ext_cm_UISetup value won't be used again.
 
- For add-ins installed for all users, the registry entry is HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.x\Addins\MyAddin.Connect\CommandPreload, and the value to signal that the add-in wants to be loaded once is also 1. However, since this branch of the Windows registry is shared by all users, Visual Studio .NET uses another Registry entry to store if for a particular user the add-in must be loaded once or not. That Registry entry is HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\7.x\PreloadAddinState\MyAddin.Connect. If that Registry entry is missing or its value is 1, the add-in will be loaded once with the ext_cm_UISetup flag. After that, the value is changed to 0 and the ext_cm_UISetup value won't be used again. Notice that the value of CommandPreload never changes in this case.
 
When Visual Studio .NET is closed, it persists add-in command information on disk. That information is stored for each user in the file C:\Documents and Settings\<user>\Application Data\Microsoft\VisualStudio\7.x\1033\CmdUI.PRF. This persistence mechanism causes the following issue when you debug an add-in for the first time:
 
- You open a first instance of Visual Studio .NET and use the wizard to create an add-in as described above.
 
- You debug the add-in. This opens a second instance of Visual Studio .NET where the add-in is loaded and the ext_cm_UISetup value is passed in the connectMode parameter of the OnConnection method. At this point, you can go to the "Tools", "Customize…" menu, "Commands" tab, "AddIns" category and check that the command of your add-in is there. You can also check that a menu item was added to the "Tools" menu with an smiley face.
 
- You close the debugged (second) instance of Visual Studio .NET. At this point, the command information is persisted to disk.
 
- You close the first instance of Visual Studio .NET. At this point, the command information of this instance is persisted to disk too, overwriting the information persisted by the second instance. As a consequence, the information about your command is lost, and since the ext_cm_UISetup value won't be used again since the add-in was already loaded, the add-in won't have the chance of recreating the command.
 
There are several ways to solve this problem, which are detailed here:
 
1) You can close all Visual Studio .NET instances, open a .NET DOS command prompt ("Microsoft Visual Studio .NET 2003", "Visual Studio .NET Tools", "Visual Studio .NET 2003 Command Prompt" and type:
 
devenv.exe /setup
 
That will reset the CommandPreload (user addins) or PreloadAddinState (all-user add-ins) flags in the Registry and will load Visual Studio .NET and its add-ins, closing again Visual Studio .NET and persisting command information for good. But be aware that some Visual Studio .NET customizations can be lost (buttons, command bars, etc.) using this approach.
 
2) You can close all Visual Studio .NET instances, reset the proper CommandPreload or PreloadAddinState flag by hand using the regedit.exe tool, load Visual Studio .NET, check that the command is there again, and close Visual Studio .NET to persist command information.
 
3) You can avoid altogether the ext_cm_UISetup flag and the described mechanism and instead you can check if your command exists (using the DTE.Commands collection) every time that your add-in is loaded. If it does not exist, you create it.
 

APPLIES TO
  • Microsoft Visual Studio .NET 2002 Enterprise Developer
  • Microsoft Visual Studio .NET 2002 Professional Edition
  • Microsoft Visual Studio .NET 2003 Enterprise Architect
  • Microsoft Visual Studio .NET 2003 Enterprise Developer
  • Microsoft Visual Studio .NET 2003 Professional Edition
Keywords: 
kbpubmvp kbpubtypecca kbhowto KB555321
Community Solutions ContentCOMMUNITY SOLUTIONS CONTENT DISCLAIMER
MICROSOFT CORPORATION AND/OR ITS RESPECTIVE SUPPLIERS MAKE NO REPRESENTATIONS ABOUT THE SUITABILITY, RELIABILITY, OR ACCURACY OF THE INFORMATION AND RELATED GRAPHICS CONTAINED HEREIN. ALL SUCH INFORMATION AND RELATED GRAPHICS ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT AND/OR ITS RESPECTIVE SUPPLIERS HEREBY DISCLAIM ALL WARRANTIES AND CONDITIONS WITH REGARD TO THIS INFORMATION AND RELATED GRAPHICS, INCLUDING ALL IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, WORKMANLIKE EFFORT, TITLE AND NON-INFRINGEMENT. YOU SPECIFICALLY AGREE THAT IN NO EVENT SHALL MICROSOFT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY DIRECT, INDIRECT, PUNITIVE, INCIDENTAL, SPECIAL, CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF USE, DATA OR PROFITS, ARISING OUT OF OR IN ANY WAY CONNECTED WITH THE USE OF OR INABILITY TO USE THE INFORMATION AND RELATED GRAPHICS CONTAINED HEREIN, WHETHER BASED ON CONTRACT, TORT, NEGLIGENCE, STRICT LIABILITY OR OTHERWISE, EVEN IF MICROSOFT OR ANY OF ITS SUPPLIERS HAS BEEN ADVISED OF THE POSSIBILITY OF DAMAGES.
 

Article Translations