locked
Creating a ToolWindow that will be used in both VS2008 and in VS2010 RRS feed

  • Question

  • I've created a tool window like so:

    public class MyToolWindow : ToolWindowPane

    And I am creating it using IVsUIShell.FindToolWindow and it works great for either VS2010 or VS2008. However, since I am developing an extension for both, I'd rather have the same ToolWindow class to be used in both (from a shared assembly). The problem is that that ToolWindowPane is different in every SDK and trying to create a tool window from Microsoft.VisualStudio.Shell.9.0 in VS2010 results with failure. Trying to create the window with Package.CreateToolWindow gave me the following error messagebox:

    "CreateToolWindow only creates Tool Windows derived from ToolWindowPane."

    Is there anything I can do with this issue? Or should I create 2 ToolWindow classes (one for each version of VS) for each tool window I have?

    Thanks,
    Vitaly

     

    Wednesday, December 1, 2010 12:51 PM

Answers

  • Yes, there is no need to reference ANY 10.0 dll's if you want your package / toolwindow to be usable across VS versions.  You need to rely only on the 'highest version' dll supported by the lowest version VS you want to run against, so in this case that would be Shell.9.0.  Unless you have a reason to reference Shell.10.0 (like you need some new functionality in it) then you shouldn't be doing it in this scenario.  If you DO need to reference Shell.10.0 you would need to ensure that even your 10.0 package derived from Shell.9.0 Package if you wanted to pass it a 9.0 derived WindowPane object.

    Ryan

    • Marked as answer by CodeValue Ltd Thursday, December 2, 2010 6:07 PM
    Thursday, December 2, 2010 6:02 PM

All replies

  • Do you have a small repro?  If you are only referencing Shell.9.0 there should be no problems, Package.CreateToolWindow exists in Shell.9.0 (and the other 'shell' versions).  If you have both 9.0 and 10.0 referenced perhaps there is type confusion, then again you couldn't deploy against 2008 if you had Shell.10.0 referenced as it doesn't exist on 2008.

    Ryan

    Wednesday, December 1, 2010 4:55 PM
  • Hi Ryan,

    I've made a short sample, you can find the zipped solution file here . I've created it using the VSPackage builder but you can safely ignore everything and focus on the code below:

    VitalyIsToolWindow.cs

    extern alias OldShell;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;
    using System.Windows.Forms.Integration;
    
    namespace BuilderPackage
    {
      [Guid("ad0f5f51-1197-4367-9791-ab8314d8487a")]
      public class VitalyIsToolWindow : OldShell::Microsoft.VisualStudio.Shell.ToolWindowPane
      {
        private ElementHost elementHost;
    
        public VitalyIsToolWindow() : base(null)
        {
        }
    
        protected override void Initialize()
        {
          base.Initialize();
    
          elementHost = new ElementHost();
          elementHost.Child = new System.Windows.Controls.TextBox();
        }
    
        public override IWin32Window Window
        {
          get { return elementHost; }
        }
    
      }
    }
    

     

    Note that since both Shell.9.0 and Shell.10.0 are referenced, I have to use an extern alias for Shell.9.0.

    Here is the code that tries to create the toolwindow from Package.cs :

     

    using System;
    using System.Diagnostics;
    using System.Globalization;
    using System.Runtime.InteropServices;
    using System.ComponentModel.Design;
    using Microsoft.VisualStudio.Shell.Interop;
    using Microsoft.VisualStudio.Shell;
    
    namespace BuilderPackage
    {
    
      [PackageRegistration(UseManagedResourcesOnly = true)]
      [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)]
      [ProvideMenuResource("Menus.ctmenu", 1)]
    	[ProvideToolWindow(typeof(VitalyIsToolWindow), Orientation=ToolWindowOrientation.Right, Style=VsDockStyle.Tabbed, MultiInstances = false, Transient = false, PositionX = 100 , PositionY = 100 , Width = 300 , Height = 300 )]
    	[Guid(GuidList.guidBuilderPackagePkgString)]
      public abstract class BuilderPackagePackageBase : Package
      {
        private void ShowToolWindowVitalyIs(object sender, EventArgs e)
        {
          ToolWindowPane window = this.FindToolWindow(typeof(VitalyIsToolWindow), 0, true);
          if ((null == window) || (null == window.Frame))
          {
            throw new NotSupportedException(String.Format("Can not create Toolwindow: VitalyIs"));
          }
          IVsWindowFrame windowFrame = (IVsWindowFrame)window.Frame;
          Microsoft.VisualStudio.ErrorHandler.ThrowOnFailure(windowFrame.Show());
        }
    ...
    }
    

     

    Note that here Shell.10.0 is used (since the package is intended for VS2010). The error happens at: 

    this.FindToolWindow(typeof(VitalyIsToolWindow), 0, true);<br/>
    
    

    And as I said before it shows me a messagebox with: "CreateToolWindow only creates Tool Windows derived from ToolWindowPane."

    Let me know what you think.

    Thanks for your help,

    Vitaly

    Wednesday, December 1, 2010 10:02 PM
  • If you plan on deploying to 2008 you shouldn't be referencing Shell.10, that assembly will not be installed on 2008 and your package will fail to load due to failure to resolve the reference.  You don't need multiple versions of versioned assemblies. 

    The problem is you explicitly derive from the Shell 9.0 version of ToolWindowPane and then you try to pass that into FindToolWindow on a Package that, most likely, derives from the Package class in Shell.10.0.  The ToolWindowPane type in Shell 9.0 and the ToolWindowPane type in Shell 10.0 both live in the same namespace (by design) and are considered DIFFERENT types by the CLR.  When FindToolWindow does its check it is likely just checking against ToolWindowPane, which since it (Package) is located in Shell.10.0 means the Shell 10.0 version of ToolWindowPane, which your window does not derive from, thus it throws.  My suggestion is don't reference Shell.10.0 at all as it won't exist on 2008.  Generally when you want to run cross version you can't take hard dependencies on types that won't exist down level (like the 10.0 version of all the types in the Shell assembly).

    Ryan

    Thursday, December 2, 2010 12:16 AM
  • Hi Ryan,

    My original plan was to use this package for VS2010, that's why the Package itself is in Shell.10.0. However, I wanted to use the same ToolWindowPane class for both 10.0 Package and 9.0 package (using a shared assembly). However, based on what you're explaining to me it seems that it is impossible, since ToolWindowPane is explicit class (not interface) and since 10.0 Package can't load 9.0 ToolWindowPane, I have to create a different class for each package version, i.e: VitalyIsToolWindow2008 and VitalyIsToolWindow2010 .

    Did I get it right?

     

     

    Thursday, December 2, 2010 9:18 AM
  • Why do you NEED to derive from the Shell 10.0 WindowPane class?  The Shell.9.0 WindowPane class will work just fine in 2008 and 2010.  Are you taking advantage of some functionality that is ONLY present in the 2010 WindowPane class?

    Ryan

    Thursday, December 2, 2010 5:45 PM
  • Err. I do not derivefrom Shell 10.0 WindowPane, I derive from 9.0:

     

     public
     class
     VitalyIsToolWindow : OldShell::Microsoft.VisualStudio.Shell.ToolWindowPane

    "The Shell.9.0 WindowPane class will work just fine in 2008 and 2010" - But in my sample it didn't, trying to load Shell.9.0 WindowPane in VS2010 in a Shell 10.0 package resulted an error.... Or wait, do you mean that I should use Shell 9.0 package in VS2010? I didn't even consider that option.

    Thursday, December 2, 2010 5:50 PM
  • Yes, there is no need to reference ANY 10.0 dll's if you want your package / toolwindow to be usable across VS versions.  You need to rely only on the 'highest version' dll supported by the lowest version VS you want to run against, so in this case that would be Shell.9.0.  Unless you have a reason to reference Shell.10.0 (like you need some new functionality in it) then you shouldn't be doing it in this scenario.  If you DO need to reference Shell.10.0 you would need to ensure that even your 10.0 package derived from Shell.9.0 Package if you wanted to pass it a 9.0 derived WindowPane object.

    Ryan

    • Marked as answer by CodeValue Ltd Thursday, December 2, 2010 6:07 PM
    Thursday, December 2, 2010 6:02 PM
  • I got it and I will try it out.

    Thank you for your help!
    Vitaly

    Thursday, December 2, 2010 6:07 PM