locked
Trying to Add a Node to the ServerExplorer RRS feed

  • Question

  • I'm attempting to add another node to the ServerExplorer window.  Technically, it is a DataConnection, but this is for a document oriented database that doesn't support the ADO.NET provider model, hence why I'd like another top-level node.

     

    My VsPackage is loading just fine at startup, and my pkgdef file shows up in the registry under 10Exp_Config, but my node never shows up.  Any ideas?

     

    pkgdef...

     

    [$RootKey$\ServerExplorer\Nodes]
    [$RootKey$\ServerExplorer\Nodes\{D457F1E9-4A91-4570-92DA-656EC9EC1337}]
    "Assembly"="MongoDB.VisualStudio"
    "ClassName"="MongoDB.VisualStudio.Explorer.MongoDBNode"
    "CodeBase"="$PackageFolder$\MongoDB.VisualStudio.dll"

    MongoDBNode class
    public class MongoDBNode : Node
        {

            public static MongoDBNode RootNode { getprivate set; }

            public override System.Drawing.Image Icon
            {
                get { return Resources.MongoDBIcon; }
            }

            public override string Label
            {
                get { return "MongoDB"; }
                set { /*do nothing*/ }
            }

            public MongoDBNode()
            {
                if (RootNode == null)
                    RootNode = this;
            }

            private MongoDBNode(SerializationInfo info, StreamingContext context)
                : this()
            {
                Trace.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering ctor of {0}"this.ToString()));
                RootNode = this;
            }

            public override int CompareUnique(Node node)
            {
                return 0;
            }

            public override Node[] CreateChildren()
            {
                return null;
            }

            internal static void ShowAddConnectionDialog(object sender, EventArgs e)
            {
                System.Windows.Forms.MessageBox.Show("Hola");
            }
        }

     

    Friday, July 9, 2010 6:52 PM

Answers

  • Hi Craig,

    Unfortunately, this is considered an unsupported scenario as we're using an undocumented Node class from that Microsoft.VSDesigner.dll assembly.

    That being said, I was able to get this working after a bit of experimentation with VS 2010. First I had to copy the Microsoft.VSDesigner.dll assembly out of the gac, so I could reference it in my package.

    Second, the Server Explorer doesn't use/recognize any "CodeBase" registry value under the ServerExplore hive. Under the hood, there is simply a Type.GetType call that is used to attempt to create your node. So you'll have to add a BindingPath entry to ensure your assembly winds up in the IDE's probing path. See (or simply include) the ProvideBindingPathAttribute we ship as source in the VS 2010 SDK.

    Finally, there is a check at runtime, as the ServerExplorer reflects over your Node type, for a static Type property called "parentType". The following needs to be added to your Node class in order for the ServerExplorer to treat your node as a top level node. If this property isn't present, the node will never show.


       #pragma warning disable 0414
          public static readonly Type parentType = null;
       #pragma warning restore 0414

    And you'll need to ensure you're passing a good Image back from your Icon override. If you wind up throwing an exception here (as I did with my experiment) you run the risk of mucking up the ServerExplorer toolwindow.

    In addition to linking in the previously mentioned ProvideBindingPathAttribute.cs, I wrote a quick and dirty ProvideServerExplorerNodeAttribute class to automatically add the requisite entries in the .pkgdef.

    =================================

    using System;
    using System.IO;
    using System.ComponentModel;
    using System.Globalization;
    using Microsoft.Win32;
    using Microsoft.VisualStudio.Shell;

    namespace Microsoft.ServerExplorerX
    {   
        [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
        public class ProvideServerExplorerNodeAttribute : RegistrationAttribute
        {
            private Type _nodeType;

            private string RegKeyName(Type nodeType)
            {
                return string.Format(CultureInfo.InvariantCulture, "ServerExplorer\\Nodes\\{0}",
                nodeType.GUID.ToString("B"));
            }

            public ProvideServerExplorerNodeAttribute(Type nodeType)
            {
                _nodeType = nodeType;
            }

            public override void Register(RegistrationContext context)
            {
                if (context == null)
                    throw new ArgumentNullException("context");

                using (Key seNodeKey = context.CreateKey(RegKeyName(_nodeType)))
                {
                    Type pkg = context.ComponentType;

                    seNodeKey.SetValue("Assembly", pkg.Assembly.GetName().FullName);
                    seNodeKey.SetValue("ClassName", _nodeType.FullName);
                    //seNodeKey.SetValue("CodeBase", context.CodeBase);
                }

            }

            public override void Unregister(RegistrationContext context)
            {
                if (context != null)
                {
                    context.RemoveKey(RegKeyName(_nodeType));
                }
            }
        }
    }

    =======================

    Sincerely,


    Ed Dore
    Monday, July 19, 2010 8:01 PM

All replies

  • Hi Craig,

    I haven't actually seen anyone attempt something like this before. Previously, the only way I've seen top level nodes added to the Server Explorer, was to use IVsUIHierarchyWindow.AddUIHierarchy to add a custom hierarchy implementation directly into the Server Explorer.

    That isn't to say it isn't possible, but given the absence of documentation I'm not entirely certain this is a supported/recommended scenario. What assembly are you referencing to resolve that Node class? I took a quick look at the Server Explorer codebase, and the code above looks quite similar to some of our top level node implementations. But I'll need to poke around and see if the \ServerExplorer\Nodes\...regkey you mentioned is all that's required here.

    Were you able to confirm that they show up in the _Config hive?

    Thanks,


    Ed Dore
    Tuesday, July 13, 2010 9:51 PM
  • <form id="aspnetForm" action="edit" enctype="application/x-www-form-urlencoded" method="post">

    <script type="text/javascript"></script> <script type="text/javascript"></script> <script type="text/javascript"></script> <noscript></noscript>

    <noscript></noscript></form>
    Monday, July 19, 2010 7:35 PM
  • Hi Craig,

    Unfortunately, this is considered an unsupported scenario as we're using an undocumented Node class from that Microsoft.VSDesigner.dll assembly.

    That being said, I was able to get this working after a bit of experimentation with VS 2010. First I had to copy the Microsoft.VSDesigner.dll assembly out of the gac, so I could reference it in my package.

    Second, the Server Explorer doesn't use/recognize any "CodeBase" registry value under the ServerExplore hive. Under the hood, there is simply a Type.GetType call that is used to attempt to create your node. So you'll have to add a BindingPath entry to ensure your assembly winds up in the IDE's probing path. See (or simply include) the ProvideBindingPathAttribute we ship as source in the VS 2010 SDK.

    Finally, there is a check at runtime, as the ServerExplorer reflects over your Node type, for a static Type property called "parentType". The following needs to be added to your Node class in order for the ServerExplorer to treat your node as a top level node. If this property isn't present, the node will never show.


       #pragma warning disable 0414
          public static readonly Type parentType = null;
       #pragma warning restore 0414

    And you'll need to ensure you're passing a good Image back from your Icon override. If you wind up throwing an exception here (as I did with my experiment) you run the risk of mucking up the ServerExplorer toolwindow.

    In addition to linking in the previously mentioned ProvideBindingPathAttribute.cs, I wrote a quick and dirty ProvideServerExplorerNodeAttribute class to automatically add the requisite entries in the .pkgdef.

    =================================

    using System;
    using System.IO;
    using System.ComponentModel;
    using System.Globalization;
    using Microsoft.Win32;
    using Microsoft.VisualStudio.Shell;

    namespace Microsoft.ServerExplorerX
    {   
        [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
        public class ProvideServerExplorerNodeAttribute : RegistrationAttribute
        {
            private Type _nodeType;

            private string RegKeyName(Type nodeType)
            {
                return string.Format(CultureInfo.InvariantCulture, "ServerExplorer\\Nodes\\{0}",
                nodeType.GUID.ToString("B"));
            }

            public ProvideServerExplorerNodeAttribute(Type nodeType)
            {
                _nodeType = nodeType;
            }

            public override void Register(RegistrationContext context)
            {
                if (context == null)
                    throw new ArgumentNullException("context");

                using (Key seNodeKey = context.CreateKey(RegKeyName(_nodeType)))
                {
                    Type pkg = context.ComponentType;

                    seNodeKey.SetValue("Assembly", pkg.Assembly.GetName().FullName);
                    seNodeKey.SetValue("ClassName", _nodeType.FullName);
                    //seNodeKey.SetValue("CodeBase", context.CodeBase);
                }

            }

            public override void Unregister(RegistrationContext context)
            {
                if (context != null)
                {
                    context.RemoveKey(RegKeyName(_nodeType));
                }
            }
        }
    }

    =======================

    Sincerely,


    Ed Dore
    Monday, July 19, 2010 8:01 PM