MZ-Tools Articles Series: updated articles

I have updated the following MZ-Tools Series articles to fix/explain better some things, provide C# code some cases, cover Windows Vista folders, cover Visual Studio 2008/2010 in some other cases, etc:

HOWTO: Removing commands and UI elements during Visual Studio .NET add-in uninstallation
http://www.mztools.com/Articles/2005/MZ2005002.aspx

HOWTO: Reset a Visual Studio add-in
http://www.mztools.com/Articles/2006/MZ2006014.aspx

HOWTO: Get rid of a Visual Studio add-in
http://www.mztools.com/Articles/2006/MZ2006018.aspx

INFO: Visual Studio .NET Add-In Commands Disappear On Next Session
http://www.mztools.com/Articles/2005/MZ2005014.aspx

Feature request to search for custom resource bitmaps for commands in the own add-in dll

Since I have no much hope of getting a new EnvDTE100.Commands.AddNamedCommand3 that accepts an icon as parameter rather than a resource id, I have filed a new feature request to at least get rid of the satellite DLL just making EnvDTE80.Commands.AddNamedCommand2 to search for resources in the own add-in dll, which wouldn’t require a new method or a change in the method signature:

Make EnvDTE80.Commands.AddNamedCommand2 to search for custom pictures in the own add-in dll
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=467535

You can vote for it if you like the idea.

Usercontrols hosted in toolwindows still requiring ComVisible(True) attribute

Another scenario where a managed add-in for VS 2005 or higher still requires the ComVisible(True) attribute (apart from the Connect class that I blogged about in the last post) is when creating toolwindows with the EnvDTE80.Windows2.CreateToolWindow2 method: if you move the ComVisible(True) attribute from the AssemblyInfo file to the Connect class (which is actually the class that needs it) then the usercontrol class passed to the CreateToolWindow2 is not visible to COM and in these circumstances the CreateToolWindow2 method doesn’t return the created usercontrol as last parameter, and EnvDTE.Window.Object (which should return the usercontrol) is also null.

I had heard reports from people that said that when the usercontrol resided in another assembly rather than in the own add-in assembly, the CreateToolWindow2 didn’t return the instance of the usercontrol. Now the explanation is clear:  usercontrols in Windows Control Library projects have the ComVisible attribute set to false in the assemblyinfo file, while usercontrols in the add-in project have it set to true in the assemblyinfo file. So, the problem is not where the usercontrol resides, but whether the usercontrol is visible to COM or not.

Since managed add-ins should get rid of COM semantics, I have filed another bug report to Microsoft:

EnvDTE80.Windows2.CreateToolWindow2 doesn’t return in the last
parameter the hosted usercontrol if ComVisible attribute not set to true
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=467084

Managed add-ins still requiring ComVisible(True) attribute

While add-ins for Visual Studio .NET 2002/2003 required COM registration (COM Interop) and registration for Visual Studio using the Windows registry, Visual Studio 2005 introduced XML-registration (.AddIn file) and removed the need for COM registration, both a big advance.

Then, one day, visiting the assemblyinfo.vb file that is not very much visited, you notice the following line:

<Assembly: ComVisible(True)>

and then you think that you can change it to:

<Assembly: ComVisible(False)>

At this point, if you try to load the add-in after this change you get an exception:

Error 80004002 (No such interface supported)

I blogged about this problem some months ago and today I have filed a bug report for MS to fix it:

Error 80004002 (No such interface supported) in add-in when ComVisible attribute is set to False
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=467081

Note 1: while the add-in wizard sets the ComVisible attribute to True at assembly level, actually only the Connect class needs to have such attribute.

Note 2: since the ComVisible attribute uses a boolean parameter that can be set to true o false, one may wonder which is the behavior if the attribute is missing at all. The answer is in the MSDN docs: (public) types are visible to COM by default, the attribute is only needed to hide them to COM. So, if seeing <Assembly: ComVisible(True)> in your code bothers you too much, you can actually delete the line and the effect would be the same.

Two more reports about bugs in folders used by Visual Studio to locate .AddIn files

I thought that I had already reported these ones to Microsoft for VS 2008, but I don’t find the bug reports and anyway the bugs are still present in VS 2010 Beta 1:

Visual Studio hardcodes “Application Data” folder in the list of folders for .AddIn files
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=466756

%ALLUSERSDOCUMENTS%\Microsoft\MSEnvShared\AddIns folder is not searched for add-ins
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=466741

Wouldn’t be nice to know where a Visual Studio add-in is registered from?

Given that add-ins for Visual Studio can use COM-based registration or XML-based registration and that the first one uses two locations (HKEY_LOCAL_MACHINE / HKEY_CURRENT_USER) and the second one uses up to six folders by default (Tools, Options window, Environment, AddIn/Macros Security section), when developing and troubleshooting add-ins I often wonder where an add-in is registered from.

I have filed a suggestion report to get this info in the Add-In Manager of Visual Studio 2010:

Add information of add-in registration in Add-In Manager
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=466762

You can vote for it if you would like to have that info too.

Call to action: please VOTE to get easy, custom, transparent, pictures for add-ins CommandbarButtons fixed forever

If you are subscribed to the RSS of this blog, chances are that you are an add-in developer, because despite its title, I don’t write very much about macros (nobody really uses them) and I don’t know about SDK packages, only a little about how to call SDK services from an add-in. So, if you are an add-in developer, you must know how difficult is to get custom, transparent pictures on add-in buttons.

I have tried with Microsoft to get this fixed in the last years publicly and privately to no avail, but I keep pushing 🙂 and now that they are changing the commandbars to WPF is the best chance to get this fixed forever. Just in case you haven’t tried yet, you can’t get transparent pictures in VS 2010 Beta 1, neither using native (C++) satellite DLLs nor using managed (.NET) satellite DLLs (I tried managed DLLs after opening the bug report).

The short story (call to action):

Go to this page and vote to get this problem fixed (I am thinking that if it gets some hundreds of votes maybe they will fix it):

Automation Model (EnvDTE) Enhancement: Accept .NET System.Drawing.Icon to set custom pictures in add-in commands and toolwindows
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=336868

The long story (my last internal e-mail to Microsoft some days ago):

I would like to call the attention of all the people inside the Visual Studio Shell team that can make something to fix this problem that lasts 12 years now: it is very difficult to provide custom, transparent, pictures in buttons (CommandBarButton) created from add-ins:

– In VB5 (1997), VB6 and VBA you had to use the CopyFace/PasteFace methods to put custom pictures. The use of clipboard is causing problems today with remote desktop tools that monitor the clipboard.

– VS.NET 2002 forced to create a native (C++) resource library where the background color have to be almost green RGB = 0, 254, 0. The picture for ToolWindow.SetTabPicture have to use also that background color.

– VS 2005 allowed managed (VB.NET/C#) resource libraries, but you have to use also that color, or maybe magenta RGB=255,0,255.

– VS 2010 has again problem with transparency as I have reported here (neither almost green nor magenta works, at least with native satellite DLLs):

https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=461192

The problems are two:

– There should no need to use resource libraries.
– The transparency should be much easier.

A very simple solution that solves both problems is:

– To allow to use icons, rather than bitmaps. Icons do support transparency natively.
– To provide a EnvDTE100.Commands3.

AddNamedCommand3 method with this signature:Function
AddNamedCommand2(ByVal AddInInstance As EnvDTE.AddIn, ByVal Name As
String, ByVal ButtonText As String, ByVal Tooltip As String, Optional ByVal Icon As System.Drawing.Icon,
Optional ByRef ContextUIGUIDs As Object( ), Optional ByVal
vsCommandStatusValue As Integer = 3, Optional ByVal CommandStyleFlags
As Integer = 3, Optional ByVal ControlType As
EnvDTE80.vsCommandControlType = 2) As EnvDTE.Command.The same for the current Window.SetTabPicture(object): Make it to accept a Systen.Drawing.Icon with transparency.It would be up to the developer the decission to get this icon from a resource library, an embedded resource in the own add-in dll, a ImageList, a Picture control, a file on disk, an icon in memory, or whatever.

Then, internally in VS, make whatever you need to do with the icon:
transform it to a bitmap, transform the transparent color to green,
magenta or whatever, and paint it with transparent background.

Now that you are changing the commandbars to WPF and we are in Beta 1, it would be the best chance to get this fixed for good.

I have reported this twice through Microsoft Connect last years, to no avail:

https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=336868

If you still feel that the current implementation that you offer to people extending Visual Studio with add-ins to use custom, transparent pictures in their add-ins is not so bad, then be 100% fully coherent and modify the add-in wizard to create a solution with:

1) The add-in project
2) A satellite DLL project with a custom, transparent, picture

and make it work just pressing F5 to debug the add-in. If it is quite difficult, then it means that the current implementation is not so acceptable after all. But it is too easy to ignore the problem and make the add-in wizard to create only the add-in project, without the satellite DLL, and use the parameter values MsoButton=True, Bitmap=59 to use the smiley face from the Office bitmaps rather than using a custom picture.

With best regards,

Carlos Quintero

Good response from Microsoft fixing bugs in new WPF-based commandbars of VS 2010 Beta 1

A week ago I blogged about some nasty bugs that happened in VS 2010 Beta 1 when using the new WPF-based commandbars from an add-in. While VS 2010 Beta 1 was very disappointing for me in this regard, the response from Microsoft in the last days has been great and so far the following ones will be fixed in the next build:

CommandBarButtons created by add-ins in context menus don’t appear

CommandBarPopup on toolbars doesn’t show arrow to indicate the dropdown

EnvDTE.Command.Delete does not remove CommandBarButtons created from that command on Visual Studio commandbars

“Object must be the same type as the enum” exception calling CommandBars.Add from an add-in

Custom pictures in CommandBarButtons created by add-in don’t show a transparent background

These others are still active (I hope they are fixed too) but are not so critical or have workarounds:

System.ArgumentNullException: “Value cannot be null.” getting CommandBar.Position from an add-in
Workaround: since it seems that VS 2010 toolbars can’t be moved by hand by the user, it is not much needed to use this property

CommandBars.Item(“Tools”) causes exception rather than finding the commandbar.
Workaround: HOWTO: Locate commandbars in international versions of Visual Studio

CommandBarButton.TooltipText causes exceptions when getting or setting its value
Workaround: use the tooltip parameter of the AddNamedCommand method rather than this property.

The strange case of Visual Studio getting “out of memory”

I started programming in the old times of 16-bit MS-DOS, where you had only 640 KB of memory, and you had concepts like “expanded memory” and “extended memory” and memory bank switching to use more than 640 KB and then wonderful things like the Watcom C++ compiler that allowed you to create linear 32-bit MS-DOS programs to use all the available memory, not just 640 KB or 1 GB MB (oops!). When Windows (95) became a 32-bit OS and I learned at college about 32 bit pointers, it seemed that 4 GB of memory will be enough forever. Guess what? Some weeks ago I got “out of memory” errors from Visual Studio when trying some features of my MZ-Tools add-in that operate on every file of a solution. Specifically, the problem happened when iterating the code elements of the EnvDTE.ProjectItem.FileCodeModel of every file of the solution. My computer had 4 GB of RAM so I was surprised by this error (later I learned that the amount of RAM is irrelevant for most “out of memory” errors in modern virtual memory operating systems).

The first reference that I found on the web about this error was in the MSDN VSX forum:

ProjectItem.FileCodeModel causes memory fragmentation?
http://social.microsoft.com/Forums/en-US/vsx/thread/9d6c1d17-63c8-40c4-b6bc-e7f0ead65c3d

Notice that while MSFT people explained that this is due to COM objects in memory wrapped by .NET objects that are not released, the explanation does not solve the problem, neither the manipulation of the Garbage Collector (GC). I didn’t try using EnvDTE.Project.CodeModel because it didn’t meet my needs of “file by file” processing.

Then I found that mine was not the only extension for Visual Studio experiencing this problem. Resharper was also experiencing it and provided some tools to fix it. But it was non until I read this post when I learned about the cause and (kind of) solution for this problem:

Hacking Visual Studio to Use More Than 2Gigabytes of Memory
http://old.stevenharman.net/blog/archive/2008/04/29/hacking-visual-studio-to-use-more-than-2gigabytes-of-memory.aspx

So, the problem is not the lack of physical memory (RAM) or virtual memory, but the address space of 32-bit processes, which is limited to 4 GB and half of it is reserved for the OS (kernel mode) so the process has only 2 GB for it (user mode). And using the file code model of every file of a solution can cause Visual Studio to reach the limit of 2 GB of its user-mode address space. Using the /3GB option in the boot.ini file allows 3 GB of address space for the user mode part of the process and 1 GB for the kernel mode part, which can cause other problems because 1 GB is little these days for some video cards, etc.

Also, to take advantage of the 3 GB address space, a process must be “marked” to indicate the OS that it can use all those memory addresses. This is done with the LARGEADDRESSAWARE flag in the executable image that Visual Studio 2008 does have set, but Visual Studio 2005 doesn’t (although you can patch it with the editbin utility as explained in the link above).

In my case, using the /3GB option in boot.ini with VS 2008 “solved” the problem and using the Task Manager I saw devenv.exe passing the limit of 2 GB without causing the “OutOfMemory” exception. I say “solved” because this is not really a happy solution, it is not something that you can patch in your add-in, you need to show a message explaining the user to either use Windows 64-bit (which gives 32-bit processes the full 4 GB address space for user-mode) or to use the /3GB option with Windows 32-bit (that can cause other problems, in my case with two other applications).

So, 32-bit pointers and 4 GB are not enough these days… maybe with 64-bit pointers we’ll have these problems solved forever.

There is a bunch of very interesting resources on the web about all this, starting by the Raymond Chen’s series:

Summary of the recent spate of /3GB articles
http://blogs.msdn.com/oldnewthing/archive/2004/08/22/218527.aspx

and this one of today:

“Out Of Memory” Does Not Refer to Physical Memory
http://blogs.msdn.com/ericlippert/archive/2009/06/08/out-of-memory-does-not-refer-to-physical-memory.aspx

.NET support in next version of InnoSetup installer (handy for COM-based add-ins)

Finally InnoSetup, a freeware very popular installer for Windows will include support for .NET, that is, constants to execute utilities from the .NET Framework SDK such as regasm.exe, etc. or to install assemblies in the GAC, etc:

InnoSetup 5.3 Beta:
http://www.jrsoftware.org/files/is5-whatsnew.htm#5.3.0

Using regasm.exe is required for COM add-ins (for Visual Studio .NET 2002/2003). Previously you had to write some custom code to get the path of the .NET Framework SDK folder, to execute regasm.exe, etc.

I have been using InnoSetup for my MZ-Tools add-in and I am very happy with it, since I switched to it many years ago after I tried the MSI-based installer of Visual Studio and found some problems.

If you want to use InnoSetup to create a setup for a Visual Studio 2005/2008 add-in, this article of mine will help you:

HOWTO: Create a setup for a Visual Studio 2005 / 2008 add-in using Inno Setup
http://www.mztools.com/articles/2008/MZ2008010.aspx