problem with trying to create ssms add-in

2020-06-06 02:23发布

问题:

I'm trying to create an add-in for SSMS 2008 and/or 2008 R2 but I've run into a problem straight away.

I can get my add-in to work and on SSMS start-up get it to simply show a message box.

However, after downloading various code-samples, when trying to reference Microsoft.SqlServer.Management.UI.VSIntegration.ServiceCache I get a null reference exception:

Commands2 commands = (Commands2)ServiceCache.ExtensibilityModel.Commands;

I get this problem when using SSMS 2008 or SSMS 2008 R2. I'm working on Visual Studio 2010.

It's a bit frustrating because I'm keen to learn more about SSMS add-ins but can't seem to get past the few samples out there.

Any advice/tips appreciated.

Thanks

回答1:

Karl, I don't know about your concrete problem here, but answering another question, I came across a bunch of articles and links on writing SSMS plug-ins - maybe one of them will be useful to you:

Some information can be found here:

  • The Black Art of Writing a SQL Server Management Studio Add-In
  • Building a SQL Server Management Studio Add-In
  • Extend Functionality in SQL Server 2005 Management Studio with Add-ins
  • SSMS Scripter - Internals, part 2 - plugging in


回答2:

ServiceCache is unreliable - from version to version it supports less and less and probable will go away at some point.

If you write SSMS Add-in, you can access internals by accessing VS ApplicationModel. Something like that:

public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
        {
            _addInInstance = (AddIn)addInInst;
            _applicationObject = _addInInstance.DTE as DTE2;

_applicationObject has Commands and other interesting stuff.

Please note, that application argument of OnConnection has an incorrect object passed in. That's why you have to use this line to get the right object: _applicationObject = _addInInstance.DTE as DTE2;



回答3:

I've been struggling with this for a while.

I've got an add-in what work in sql 2008 - written in VS2008.

I upgraded the project to VS2010 and started working on getting the sql 2008 r2 add-in working - I could not get this working for love nor money.

I tried lots of different things; * deleting and re-adding all the references. * changing the target framework. Not a sausage.

Nothing worked.... Until I went back to VS2008 - I made the changes. (see Jonathan Kehayias blog: https://www.sqlskills.com/blogs/jonathan/sql-server-2012-extended-events-add-in-to-manage-2008r2-instances/)

Hurray for new versions!!



回答4:

Ok I find solution, the problem is between CLR2.0 and CLR 4.0

Source : http://blogs.msdn.com/b/mshneer/archive/2010/03/19/com-shim-wizards-for-vs-2010.aspx

Debugging add-ins targeting CLR 2.0 in Visual Studio 2010

I had some problems debugging add-ins if those were loading in CLR 2.0. I would press F5, Excel would start up and my add-in would run but the breakpoints were not getting hit. So I wanted to share what's going on and how to set up your environment in such a way that F5 experience is not completely broken.

There is no magic in the way I usually go about debugging the shared add-in - either shimmed or unshimmed. I set a breakpoint in the OnConnection method in Connect.cs file, open project's properties, go to the Debug section, select the "Start External Program" option and set the full path to my Office application (e.g. "C:\Program Files\Microsoft Office\Office12\EXCEL.EXE"). Next I right click on the project node in the Solution Explorer and select "Set As Startup Project". When I press F5 my breakpoint is hit.

In Visual Studio 2010 the breakpoint is not hit if my add-in is loaded in CLR 2.0. What's going on is that debugger cannot attach to both CLR 4.0 and CLR 2.0 - it actually needs to know before the fact whether it should be using CLR 2.0 debugging engine or CLR 4.0 debugging engine. When you press F5 debugger tries to guess which CLR will be started in the process. The heuristic is based on reading the EXE's .config file where required runtime version is u8sually specified and if the .config file is not found than the debugger fires up the CLR 4.0 debugging engine. As we all know Office application are not bound to any particular version of the CLR so the heuristic miserably fails.

There are actually two ways of dealing with it – one is to put an .exe.config file alongside the.exe itself e.g. when debugging Excel 2007 I will create Excel.exe.config and leave it in the "C:\Program Files\Microsoft Office\Office12" folder.

But my preferred way of dealing with this is different. In the Solution Explorer I will right click on my solution node and select "Add" -> "Existing Project" and open "C:\Program Files\Microsoft Office\Office12\EXCEL.EXE". Next, I will right click on this newly added project and select "Set As Startup Project". Next, I will open the properties for this project and will set the "Debugger Type" property to "Managed (v2.0, v1.1, v1.0)". Now, I will F5 and the breakpoint I've set in OnConnection method will be hit.



回答5:

I've the same problem. I think that it's liked to the Framework

With Framework 3.5

ServiceCache.ExtensibilityModel is not null

With Framework 4.0

"ServiceCache.ExtensibilityModel" is null



回答6:

Ok, thanks for this way, but if I have a project in Framework 3.5, VS2010 doesn't stop on my break point. But if I change the Framework to 4, VS2010 stop on the breakpoint. But CreateToolWindow2 raise an exception, because isn't the same Framework !

I simplify the code as minimum :

    /// <summary>Implements the OnConnection method of the IDTExtensibility2 interface. Receives notification that the Add-in is being loaded.</summary>
    /// <param term='application'>Root object of the host application.</param>
    /// <param term='connectMode'>Describes how the Add-in is being loaded.</param>
    /// <param term='addInInst'>Object representing this Add-in.</param>
    /// <seealso class='IDTExtensibility2' />
    public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
    {            
       _addInInstance = (AddIn)addInInst;
       _applicationObject = (DTE2)_addInInstance.DTE;

       if (connectMode == ext_ConnectMode.ext_cm_Startup)//ext_ConnectMode.ext_cm_UISetup)
       {
       }        
    }

    /// <summary>Implements the OnStartupComplete method of the IDTExtensibility2 interface. Receives notification that the host application has completed loading.</summary>
    /// <param term='custom'>Array of parameters that are host application specific.</param>
    /// <seealso class='IDTExtensibility2' />
    public void OnStartupComplete(ref Array custom)
    {            
       Windows2 win2 = this._applicationObject.Windows as Windows2;

       if (win2 != null)
       {
           Assembly asm = Assembly.GetExecutingAssembly();
           AddIn addinobj;

           addinobj = this._applicationObject.AddIns.Item(1);

           object controlObject = null;

           Guid id = new Guid("4c410c93-d66b-495a-9de2-99d5bde4a3b9"); // this guid doesn't seem to matter?
           //Window                 
           Window windowTool = win2.CreateToolWindow2(addinobj,
                                                      asm.Location,
                                                      "MyAddinASupp.UserControl1",    "Zone de test", 
                                                      "{" + id.ToString() + "}",
                                                      ref controlObject);

          windowTool.Visible = true;
       }
    }


标签: .net add-in ssms