Monday, January 30, 2012

VSX Add-in Development Adventures: Window.Object returns NULL

I’m in the middle of developing an add-in for Visual Studio 2008, a simple one that would help our in-house code review process. If you’ve ever written a VS add-in, you’d know the basic routine – Visual Studio creates the basic class Connect derived from IDTExtensibility2, then you put in your code in the methods OnConnection, OnDisconnection, OnAddInsUpdate, OnStartUpComplete and OnBeginShutdown.

I developed a few user controls (UserControl objects) for showing some UI as tool windows. One of them was AddCommentView which is just a dumb UserControl that displays some textboxes and buttons and also takes in some input. I deployed this control as a separate DLL and linked it to the add-in. Then, as usual, the following code should do the job of creating the tool window.
if (_addCommentWindow == null)   
{    
    object objTemp = null;    
    string guid = Guid.NewGuid().ToString();    
    Window2 toolWins = (Window2) this._applicationObject.Windows;

    // Create the tool window view for adding the comment   
    _addCommentWindow = toolWins.CreateToolWindow2(_addinInstance, "Controls.dll", 
        "Controls.AddCommentView", "Add Comment", "{" + guid + "}", ref objTemp);
}    

And like always it worked just fine till I tried to test it and that’s when I realized something wasn’t quite right.
The CreateToolWindow2 method has two outputs – the tool window (which is returned by the method) and the hosted user control (the ref parameter ‘objTemp’ in this case). The hosted user control can also be retrieved through the Window.Object property of the returned tool window. The problem was – no matter what I tried the Window.Object property always returned null and so did ‘objTemp’.
AddCommentView addCommentViewControl = _addCommentWindow.Object as AddCommentView;   
addCommentViewControl.StartLine = selection.AnchorPoint.Line;    
addCommentViewControl.EndLine = selection.ActivePoint.Line;

The solution – I was acting dumb, very dumb. Visual Studio requires all hosted controls to be visible to COM. After adding the attribute to the entire assembly using [assembly: ComVisible(true)] , everything started working like a charm (you can apply it even to the individual control if you don’t want to make the entire assembly COMVisible).

No comments:

Post a Comment