The strange case of error 0x80070005 “Access Denied” using PEVerify.exe with an add-in referencing a Visual Studio assembly not in the GAC

It took me quite a lot of time to fix the problem of Error 0x80070002 “The system cannot find the file specified” using PEVerify.exe to verify add-in with referenced assemblies from Visual Studio not in the GAC. I found the problem yesterday Sunday afternoon when I was with my laptop at a Starbucks with no connection to Internet other than a very weak GPRS connection with my mobile phone, so I could only get on the web that the solution was to use the codeBase tag in a .config file. The file that I used was:

<?xml version="1.0" ?>
<configuration>
   <runtime>
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
         <dependentAssembly>
            <assemblyIdentity name="Microsoft.VisualStudio.Data.Interop" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
            <codeBase version="8.0.0.0" href="C:\Program Files\Microsoft Visual Studio 8\Common7\IDE" />
         </dependentAssembly>
      </assemblyBinding>
   </runtime>
</configuration>

Using this file I got this other error:

0x80070005 “Access Denied”

rather than:

0x80070002 “The system cannot find the file specified”.

So today with more Internet connectivity I have been investigating the problem. The only reference to this problem was Debugging Assembly Loading Failures, where Suzzane Cook stated the obvious, to check file locks without shared-read access and ACLs. But this was not the problem.

The fusion log showed this:

LOG: GAC Lookup was unsuccessful.
LOG: Attempting download of new URL file:///C:/Program Files/Microsoft Visual Studio 8/Common7/IDE.
LOG: Assembly download was successful. Attempting setup of file: C:\Program Files\Microsoft Visual Studio 8\Common7\IDE
LOG: Entering run-from-source setup phase.
ERR: Error extracting manifest import from file (hr = 0x80070005).
ERR: Failed to complete setup of assembly (hr = 0x80070005). Probing terminated.

So I was clueless until I found the string “ERR: Error extracting manifest import from file” in a .rc file inside  www.koders.com, the site that has the source code of some open source portions of the .NET Framework CLR and tools. The string led me to the identifier ID_FUSLOG_MANIFEST_EXTRACT_FAILURE which in turn led me to the following code in the bindhelpers.cpp file:

HRESULT BindToSystem(IAssemblyName *pNameSystem,
   LPCWSTR pwzSystemDirectory,
   IUnknown *pUnk,
   IAssembly **ppAsmOut,
   IAssembly **ppNIAsmOut,
   IFusionBindLog **ppdbglog)
{
   HRESULT hr = S_OK;
   IAssembly *pAsm = NULL;
   CAssembly *pCAsm = NULL;
   CNativeImageAssembly *pAsmNI = NULL;
   DWORD dwSize = 0;
   IAssemblyManifestImport *pAsmImport = NULL;
   INativeImageEvaluate *pNIEva = NULL;
   WCHAR wzManifestFilePath[MAX_PATH];
   IAssemblyName *pName = NULL;
   static BOOL bCalled = FALSE;
   CDebugLog *pdbglog = NULL;
   BOOL bFoundInDevOverride = FALSE;

   MEMORY_REPORT_CONTEXT_SCOPE("FusionBindToSystem");

   if (!pNameSystem || !ppAsmOut || CAssemblyName::IsPartial(pNameSystem) || !CAssemblyName::IsStronglyNamed(pNameSystem) || !pwzSystemDirectory) {
      return E_INVALIDARG;
   }

   *ppAsmOut = NULL;

   // should only be called once.
   if (bCalled) {
      *ppAsmOut = g_pSystemAssembly;
      if (g_pSystemAssembly) {
         g_pSystemAssembly->AddRef();
         return S_OK;
      }
      else {
         return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
      }
   }

   if (IsLoggingNeeded()) {
      CDebugLog::Create(NULL, pNameSystem, NULL, &pdbglog);
   }

   wzManifestFilePath[0] = L'';

   if (pUnk) {
      hr = pUnk->QueryInterface(IID_INativeImageEvaluate, (void **) &pNIEva);
      if (FAILED(hr)) {
         goto Exit;
      }
   }

   // temporary IAssemblyName for mscorlib
   g_pSystemAssemblyName = pNameSystem;
   g_pSystemAssemblyName->AddRef();

   // we are here because we cannot find the custom assembly,
   // or we are not asked for a custom assembly.

   if (!bFoundInDevOverride) {
      hr = CAssemblyName::CloneForBind(pNameSystem, &pName);
      if (FAILED(hr)) {
         goto Exit;
      }

      hr = CreateAssemblyFromCacheLookup(NULL, pName, ppAsmOut, NULL);
      if (FAILED(hr) && hr != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) {
         goto Exit;
      }

      if (hr == S_OK) {
         DEBUGOUT(pdbglog, 1, ID_FUSLOG_CACHE_LOOKUP_SUCCESS);
      }
      else if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)){
         DEBUGOUT(pdbglog, 1, ID_FUSLOG_ASSEMBLY_LOOKUP_FAILURE);
      }

      if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) {
         dwSize = MAX_PATH;
         hr = StringCchPrintf(wzManifestFilePath, MAX_PATH, L"%ws%ws.dll", pwzSystemDirectory, SYSTEM_ASSEMBLY_NAME);
         if (FAILED(hr)) {
            goto Exit;
         }

         DEBUGOUT1(pdbglog, 0, ID_FUSLOG_ATTEMPT_NEW_DOWNLOAD, wzManifestFilePath);
         hr = CreateAssemblyFromManifestFile(wzManifestFilePath, NULL, NULL, ppAsmOut);
         if (FAILED(hr)) {
            DEBUGOUT1(pdbglog, 1, ID_FUSLOG_MANIFEST_EXTRACT_FAILURE, hr);
            goto Exit;
         }
      }
   }

Exit:

   if (pdbglog) {
      pdbglog->SetResultCode(FUSION_BIND_LOG_CATEGORY_DEFAULT, hr);
      DUMPDEBUGLOG(pdbglog, g_dwLogLevel);
      DUMPDEBUGLOGNGEN(pdbglog, g_dwLogLevel);
      if (ppdbglog) {
         *ppdbglog = pdbglog;
         pdbglog->AddRef();
      }
   }

   SAFERELEASE(g_pSystemAssemblyName);

   if (SUCCEEDED(hr)) {
      pCAsm = static_cast (*ppAsmOut); // dynamic_cast
      pCAsm->SetIsSystemAssembly(TRUE);

      g_pSystemAssembly = *ppAsmOut;
      g_pSystemAssembly->AddRef();
      g_pSystemAssembly->GetAssemblyNameDef(&g_pSystemAssemblyName);
   }

   if (FAILED(hr)) {
      SAFERELEASE(*ppAsmOut);
   }

   SAFERELEASE(pdbglog);
   SAFERELEASE(pAsmImport);
   SAFERELEASE(pAsm);
   SAFERELEASE(pAsmNI);
   SAFERELEASE(pNIEva);
   SAFERELEASE(pName);

   bCalled = TRUE;
   return hr;
}

I have marked in bold the relevant code. It was not until I saw the name of the function CreateAssemblyFromManifestFile when I realized that I had to specify the full file name and not the folder of the assembly in the .config file. Once modified to the following it worked without errors:

<?xml version="1.0" ?>
<configuration>
   <runtime>
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
         <dependentAssembly>
            <assemblyIdentity name="Microsoft.VisualStudio.Data.Interop" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
            <codeBase version="8.0.0.0" href="C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\Microsoft.VisualStudio.Data.Interop.dll" />
         </dependentAssembly>
      </assemblyBinding>
   </runtime>
</configuration>

The “access denied” error was misleading since it would be more useful to keep showing the “file not found” error.

Now, imagine the time that you could save diagnosing problems in extensions for Visual Studio if you could have access to the Visual Studio source code, even without being able to debug, just debugging with the brain as I did…

MZ-Tools Articles Series: PRB: PEVerify.exe causes problem verifying add-in with referenced assemblies from Visual Studio not in the GAC

I am currently working on a new version of MZ-Tools and yesterday I updated its build script. When running it, to my surprise, I found the following error in the step that verifies the assembly with the peverify.exe tool after the obfuscation step:

Error 0x80070002 “The system cannot find the file specified”

After diagnosing the problem with the Assembly Binding Log Viewer, I found that the file in question was the Microsoft.VisualStudio.Data.Interop.dll assembly that this version of MZ-Tools will reference for one of its features. This file, on the contrary to others such as Microsoft.VisualStudio.Shell.Interop.8.0.dll, does not reside on the Global Assembly Cache (GAC) and, as any Visual Studio assembly, should not be distributed, the VS IDE will find it. However, when using the peverify.exe tool, that referenced assembly is not found.

Fortunately Microsoft has ways to fix for all these problems through a .config file. Long time ago I posted how to fix the problem PEVerify.exe causes problem with EnvDTE.dll verifying Visual Studio 2005 add-ins and this new article explains how to fix this other problem:

PRB: PEVerify.exe causes problem verifying add-in with referenced assemblies from Visual Studio not in the GAC
http://www.mztools.com/articles/2009/MZ2009013.aspx

Those strange cases of error 8013XXXX…

From time to time I blog about strange cases of errors when loading add-ins for Visual Studio. At least three of them have been about errors with hexadecimal codes such as 8013XXXX:

The strange case of <Unknown Error> 8013150A loading a Visual Studio add-in
https://www.visualstudioextensibility.com/2009/03/24/the-strange-case-of-lt-unknown-error-gt-8013150a-loading-a-visual-studio-add-in

The strange case of <Unknown Error> 8013141A loading a Visual Studio add-in
https://www.visualstudioextensibility.com/2008/11/28/the-strange-case-of-lt-unknown-error-gt-8013141a-loading-a-visual-studio-add-in

The strange case of error 80131018 loading a Visual Studio add-in
https://www.visualstudioextensibility.com/2007/03/23/the-strange-case-of-error-80131018-loading-a-visual-studio-add-in

When those errors happen, the description that Visual Studio shows is “Unknown Error”. I’m sure that Visual Studio could do a better job getting the description of such errors, but meantime you have to Google them, which usually gets no much meaningful information. If you ever encounter such error that you don’t get much information about, here is what you can do:

1) Those errors are coded in the corerror.h file. You have an online copy of that file at the Koders web site www.koders.com: enter “file:corerror.h” (without quotes) as your search term to get the file.

2) You will notice that the file contains a lot of error definitions such as EMAKEHR(0x101A)

3) So, you really need to search for the last 4 hexadecimal digits of your error. For example for the error 8013141A you would get:

#define CORSEC_E_INVALID_STRONGNAME     EMAKEHR(0x141a)         // Strong name validation failed

and then you know that the error is related to an invalid strong name.

If you are curious, the EMAKEHR macro is defined as:

#define FACILITY_URT            0x13
#endif
#ifndef EMAKEHR
#define SMAKEHR(val)            MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_URT, val)
#define EMAKEHR(val)            MAKE_HRESULT(SEVERITY_ERROR, FACILITY_URT, val)

So you now know where the 0x13 digits (3th and 4th) of all those errors come from.

Hope this helps.

The strange case of Add Resource New Image menu empty when an add-in is loaded in Visual Studio

These days I have been playing a lot with resource images in managed satellite dlls and one thing that I was noticing sporadically was that the Add Resource New Image menu on the toolbar of the document window of a resource.resx file was empty, while it should have the typical “Bmp image”, “Png image”, etc. menu entries. Since I was playing with 32-bit bitmaps images with transparency in the alpha channel that cannot be created with Visual Studio, most of the time I was using a 3rd party bitmap editor and using the Add Resource Add Existing File… menu. But nonetheless, I was intrigued by the missing submenus in the New Image menu. Today that I finished my investigation of the managed satellite dlls, I decided to investigate the issue.

The first thing that I noticed was that the issue was not reported on the web, or maybe only mentioned once without a solution, which was strange because I could reproduce the problem on two computers on mine. I was clueless when I discovered by chance that the problem happened only when I had my MZ-Tools add-in loaded in Visual Studio on startup. After a few minutes of debugging I isolated the problem: it happened when the toolbar of the add-in was created, so I was able to create a minimal add-in to reproduce the problem and report it to Microsoft:

The Add ResourceNew Image menu empty when VS add-in creates a toolbar
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=470755

The problem happens with VS 2005 and 2008, but it is fixed in VS 2010 Beta 1, likely due to its new WPF-based commandbars.

MZ-Tools Articles Series (Updated): HOWTO: Creating custom pictures for Visual Studio .NET add-ins commands, buttons and toolwindows.

Recently I have migrated the next version of MZ-Tools for Visual Studio .NET that I am working on from COM-based add-in to XML-based add-in (giving up Visual Studio .NET 2002/2003 support). I tried to do it many months ago but I gave up because moving to XML-based add-in meant also moving from native resource DLL to managed resource DLL, and I didn’t want to do that at that time, I just wanted to get rid of COM. But tired of the two bugs in the Visual Studio 2005/2008 Add-In Managers with COM-addins (the former one only fixed in VS 2008 and the latter one reopened and again under investigation after strong discussion with Microsoft), and tired of the problems of COM and transparent bitmaps, etc. finally I have moved to a managed satellite DLL.

AFAIK, the only official documentation from Microsoft to build a managed satellite dll for a XML add-in is the following gem in MSDN, that involves using command-line tools such as resgen.exe (Resource File Generator) or al.exe (Assembly Linker) and Windows tools such as Notepad:

How to: Display a Custom Icon on the Add-in Button
http://msdn.microsoft.com/en-us/library/ms228771(VS.80).aspx

How they can sleep well with that is beyond me ;-). I am currently trying to convince the Program Manager in charge of this to support resources in the own dll of the add-in for VS 2010 so maybe in 2014 your add-in targeting VS 2010, VS 2012 and VS 2014 can get rid of the resource dll…

Of course there is a much better way to create a resource dll that doesn’t involve command-line tools, that is, a class library project in the same solution of the add-in that provides the resources. I have updated the following article to cover this scenario:

HOWTO: Creating custom pictures for Visual Studio .NET add-ins commands, buttons and toolwindows.
http://www.mztools.com/articles/2005/MZ2005007.aspx

I have updated also the section about toolwindow bitmaps to provide better information. I have not included yet information about VS 2010 but you have these other posts:

Solved: transparent bitmaps in add-in toolwindows of VS 2010 (Beta 1)

and

Solved: transparent bitmaps in add-in commands of VS 2010 (Beta 1)

I will update the article when the current two bugs under investigation are solved in some way or another and VS 2010 gets release candidate status.

Solved: transparent bitmaps in add-in toolwindows of VS 2010 (Beta 1)

In the previous post I explained how to get transparent bitmaps for add-in commands in VS 2010 Beta 1 and previous versions. Now it is the turn of toolwindow bitmaps. Again, if you have a .NET 2.0 add-in that uses XML registration and a managed
satellite DLL and targets VS 2005, 2008 and 2010 Beta 1, the situation is as
follows:

1) Toolwindow bitmaps for VS 2005:

  • Use either:
    • A 32-bit bitmap with transparency in the alpha channel.
    • A 24-bit bitmap with RGB=255,0,255 (magenta) as transparent color
  • Call EnvDTE.Window.SetTabPicture(bitmap.GetHbitmap) (for some reason passing bitmap.GetHbitmap().ToInt32 causes System.ArgumentException: Value does not fall within the expected range)
  • Call EnvDTE.Window.Visible = True (this must be done after setting the toolwindow picture)

2) Toolwindow bitmaps for VS 2008:

  • Use either:
    • A 32-bit bitmap with transparency in the alpha channel.
    • If the color depth of the screen is:
      • 16-bit, you can use a 24-bit bitmap with RGB=0,254,0 (almost pure green) or a 24-bit bitmap with RGB=255,0,255 (magenta) as transparent color
      • 24-bit: I couldn’t test this case on my computers.
      • 32-bit: you need to make the bitmap transparent calling bitmap.MakeTransparent(<background color>).
  • Call EnvDTE.Window.SetTabPicture(bitmap.GetHbitmap().ToInt32()) (for some reason passing just bitmap.GetHbitmap causes System.ArgumentException. You need to convert the IntPtr to integer)
  • Call EnvDTE.Window.Visible = True (this must be done after setting the toolwindow picture)

3) Toolwindow bitmaps for VS 2010 Beta 1:

Bottom line: if the bug mentioned above with VS 2010 and 32-bit bitmap with transparency in the alpha channel is fixed for VS 2010 final release (Update, August 6: VS 2010 Beta 2 will fix it), you will be able to use 32-bit bitmap with transparency in the alpha channel in the three VS versions, but taking into account that sometimes you need to use the IntPtr value returned by GetHBitmap, and others its Int32 value.

I hope the information above is accurate because it is really messing to test all cases. Let me know if you can corroborate or not.

Solved: transparent bitmaps in add-in commands of VS 2010 (Beta 1)

After my rant of yesterday about Bitmap transparency nightmares at Microsoft too I have continued today with my testings and finally I got transparent bitmaps in commands of add-ins for VS 2010 Beta 1. If you have a .NET 2.0 add-in that uses XML registration and a managed satellite DLL and targets VS 2005, 2008 and 2010, the situation is as follows:

1) Command bitmaps for VS 2005 and VS 2008:

  • They need to use RGB=0,254,0 (almost pure green) as transparent color. This has been so since VS.NET 2002.
  • They do not support 32-bit bitmaps (which support built-in transparency through the alpha channel). You get white background instead.

2) Command bitmaps for VS 2010 Beta 1:

  • They do not use RGB=0,254,0 (almost pure green) as transparent color. You get a green background instead. This is a lack of backwards compatibility that I reported some weeks ago through Microsoft Connect. At the time of this writing, the bug is under investigation but it might well be closed as “by design” because it seems that Microsoft is finally solving the problem for good supporting built-in transparency with 32-bit bitmaps and removing old hacks such as magenta or green background as their own user interface guidelines suggest. Update (August 5): the last feedback from MS in the Microsoft Connect bug report indicates that RGB=0,254,0 will be supported also in VS 2010 Beta 2. Great news!
  • They do support 32-bit bitmaps (which support built-in transparency through the alpha channel). Support for 32-bit bitmaps in add-in commands is something new that didn’t work in previous versions of Visual Studio.

Bottom line: if nothing changes from Beta 1 to final release, your satellite managed Dll will need to include two sets of bitmaps: ones with 24-bit and RGB=0,254,0 background for VS 2005/2008 and other with 32-bit bitmaps with transparency in alpha channel for VS 2010 This is so because you don’t have any chance of manipulating the bitmap in your code when suplying bitmaps Ids to the AddNamedCommand method, on the contrary to the Window.SetTabPicture method of toolwindows (which will be the subject of another future post).

While it would be good to support the old way too a couple of VS releases, I don’t care suplying two sets of bitmaps because finally this is going in the good direction, that is, built-in transparency without magic tricks. See update above.

There is a little problem though: it can be tricky to get an editor that support 32-bit bitmaps correctly. First, some editors allow “4-bit”, “8-bit”, and “True Color” bitmaps, where it is not clear if “True Color” means 24-bit or 32-bit (with alpha channel). Most of the time it means 24-bit, though. Second, some editors don’t support 32-bit bitmaps at all: forget MS Paint and others such as the Visual Studio bitmap editor (it seems). For this purpose I have used the wonderful Axialis IconWorkshop icon editor. Other modern icon editors may work too. The procedure is the following:

  • Create a 16×16 icon with RGB/Alpha Channel (RGB/A – 32 bits) depth color
  • Draw your icon leaving the transparent background
  • Click FileExport…Bitmap Image. When prompted, select “Preserve Transparency information (saved to 32 bpp)”.

Now, if the add-in could supply the bitmaps in its own Dll rather than in a satellite Dll…

Bitmap transparency nightmares at Microsoft too

While trying to find a workaround for the Visual Studio 2010 Beta 1 problem with command bitmaps in add-ins, and sick about the issue of transparency in Visual Studio, today I have taken a look at the Microsoft Visual Studio 2010 User Interface Guidelines that are available here:

Microsoft Visual Studio 2010 User Interface Guidelines
http://code.msdn.microsoft.com/VS2010UX/Release/ProjectReleases.aspx?ReleaseId=2743

It’s impressive the level of effort and details that Microsoft puts to get the Visual Studio interface right from point of view of “look & feel”.

But the thing that I would like to comment about is the section 11.01.01 “Creating High Color Artwork” and subsequent ones , which I have read with a mixed feeling of joy and horror: it’s incredible how many different ways to get bitmap transparency are used in Visual Studio:

  • Icons (with built-in transparency)
  • 24-bit bitmaps with transparent color RGB=255,0,255 (magenta)
  • 24-bit bitmaps with transparent color RGB=0, 255, 0 (lime green)
  • Any of the two previous at the same time
  • 24-bit bitmaps with transparent color RGB=0, 254, 0 (almost lime green).
  • 32-bit bitmaps with built-in transparency (alpha channel)
  • The bottom-left pixel (x: 0, y: height – 1. Which sometimes needs to be magenta too!
  • Code to make bitmaps transparent
  • Etc.

Then, do not use Microsoft Paint, it can alter the bitmap header and color table. When using Photoshop, do not click File \ Save. Do not click File \ Export. Do click File \ Save As. And be aware of copy/paste operations… BTW, any mention to Visual Studio resource editor?

All that explained, you find this little gem: “high-color artwork integrates seamlessly into Visual Studio 80% of the time. If you’re the unfortunate developer who falls into the 20% case, this section is for you.”

The section is 11.02.04 “Debugging High-Color Artwork”, where you are provided with some images (I’m still figuring out how to extract them from a IE-only .mht file) that you can use to diagnose your transparency problem against 7 different causes (including one that can put your bitmap upside down!), that can appear combined, and that can be something new…

If this is the scenario inside Microsoft Visual Studio, it’s no wonder that add-ins (which are not part of Visual Studio on the contrary to packages) have always problems in each new version of Visual Studio for the two only things that they need transparency: command pictures and toolwindow pictures.

All this mess is caused by a problem that was solved when VS.NET 2002 was developed:

“Historically, developers only had twenty colors to work with: base 16 and four shades of gray. In Visual Studio 2002 that increased to 255 colors; however, most artwork was left at twenty colors. Because of the twenty-color limitation, early developers were forced to get creative in their use of images and palettes.”

(it seems that they were too creative…)

and then:

“Even though high-color has been around for many years now, we still need to work to remove these historic hacks and assumptions.”

To the Microsoft Visual Studio Team: how about removing all them for this very Visual Studio 2010 version? Keep it really simple: either icons, or 32-bit bitmaps (built-in transparency in both cases). No more magic colors. No more magic pixels coordinates. Given that we are forced to change our add-ins to get transparency on each VS version, you could sacrifice backwards compatibility and get this fixed for good.

The poor exception information adding commands, buttons, commandbar buttons, etc.

If you have coded many add-ins or a complex add-in, chances are that you have encountered the dreaded System.ArgumentException “Value does not fall within the expected range.” when adding commands, buttons, commandbars, etc. Most of the AddXXX methods of the automation model receive so many parameters (many ones optional) that one little mistake and you get that exception. The problem is that you can’t know where is the little mistake because you aren’t provided the offending parameter and a hint of the problem.

I have filed a suggestion to Microsoft to make our debugging time easier:

Provide better error information in automation model (EnvDTE) for add-ins
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=469337

You can vote for it if you hate to waste your time guessing…

devenv.exe /resetaddin doesn’t fully reset the add-in

Although I don’t use permanent commandbars in my MZ-Tools but temporary ones, I became aware of a bug when writing the samples that use permanent user interface of the article HOWTO: Adding buttons, commandbars and toolbars to Visual Studio .NET from an add-in, and I mentioned it in this article and this post. The bug is that executing devenv.exe /resetaddin resets commands and CommandBarButtons, but not permanent commandbars.

Today I finally have reported it to Microsoft, just in case they want to fix it for VS 2010:

devenv.exe /resetaddin doesn’t reset permanent add-in commandbars
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=469322

If you are affected by this problem, vote for it there.

As a workaround, remove the commandbar by code in the ext_cm_UISetup phase of the OnConnection method before adding it again.

BTW, if you are curious about where VS persists information of commands, commandbars, etc., it is the file CmdUI.prf stored here (Windows XP):

C:\Documents and Settings\<user>\Application Data\Microsoft\VisualStudio\<version>\1033

where <user> is your Windows user name and <version> is:

  • 7.0 (VS.NET 2002)
  • 7.1 (VS.NET 2003)
  • 8.0 (VS 2005)
  • 9.0 (VS 2008)
  • 10.0 (VS 2010)

Deleting that file removes all the commands, buttons, commandbars, etc. of add-ins or user customizations.