2013-02-26 58 views
2

this answer关于建立一个SSMS扩展的静脉:SSMS扩展项目 - HOWTO研究/调试

namespace SSMSAddin 
{ 
    using System; 
    using System.IO; 
    using Extensibility; 
    using EnvDTE; 
    using EnvDTE80; 
    using Microsoft.VisualStudio.CommandBars; 
    using Microsoft.SqlServer.Management.UI.VSIntegration; 
    using System.Windows.Forms; 

    public class Connect : IDTExtensibility2, IDTCommandTarget 
    { 
     private DTE2 applicationObject; 
     private CommandEvents executeSqlEvents; 
     private AddIn addInInstance; 

     public Connect() { } 

     public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom) 
     { 
      this.applicationObject = (DTE2)application; 
      this.addInInstance = (AddIn)addInInst; 

      this.applicationObject = (DTE2)application; 
      this.executeSqlEvents = this.applicationObject.Events.CommandEvents["{52692960-56BC-4989-B5D3-94C47A513E8D}", 1]; 
      this.executeSqlEvents.BeforeExecute += this.ExecuteSqlEventsBeforeExecute; 

      if (connectMode == ext_ConnectMode.ext_cm_UISetup) 
      { 
       var contextGUIDS = new object[] { }; 
       var commands = (Commands2)this.applicationObject.Commands; 
       string toolsMenuName = "Tools"; 

       //Place the command on the tools menu. 
       //Find the MenuBar command bar, which is the top-level command bar holding all the main menu items: 
       CommandBar menuBarCommandBar = ((CommandBars)this.applicationObject.CommandBars)["MenuBar"]; 

       //Find the Tools command bar on the MenuBar command bar: 
       CommandBarControl toolsControl = menuBarCommandBar.Controls[toolsMenuName]; 
       CommandBarPopup toolsPopup = (CommandBarPopup)toolsControl; 

       //This try/catch block can be duplicated if you wish to add multiple commands to be handled by your Add-in, 
       // just make sure you also update the QueryStatus/Exec method to include the new command names. 
       try 
       { 
        //Add a command to the Commands collection: 
        Command command = commands.AddNamedCommand2(this.addInInstance, "SSMSAddin", "SSMSAddin", "Executes the command for SSMSAddin", true, 59, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported + (int)vsCommandStatus.vsCommandStatusEnabled, (int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton); 

        //Add a control for the command to the tools menu: 
        if ((command != null) && (toolsPopup != null)) 
        { 
         command.AddControl(toolsPopup.CommandBar, 1); 
        } 
       } 
       catch (ArgumentException) 
       { 
        //If we are here, then the exception is probably because a command with that name 
        // already exists. If so there is no need to recreate the command and we can 
        // safely ignore the exception. 
       } 
      } 
     } 

     private void ExecuteSqlEventsBeforeExecute(string guid, int id, object customin, object customout, ref bool canceldefault) 
     { 
      try 
      { 
       Document document = ((DTE2)ServiceCache.ExtensibilityModel).ActiveDocument; 
       var textDocument = (TextDocument)document.Object("TextDocument"); 

       string queryText = textDocument.Selection.Text; 

       if (string.IsNullOrEmpty(queryText)) 
       { 
        EditPoint startPoint = textDocument.StartPoint.CreateEditPoint(); 
        queryText = startPoint.GetText(textDocument.EndPoint); 
       } 

       DateTime now = DateTime.Now; 
       // string server = 
       string folderPath = string.Format(@"B:\SSMS Queries\{0}", now.ToString("yyyyMMdd")); 
       string fileName = now.ToString("yyyyMMdd-HHmmss") + ".sql"; 
       Directory.CreateDirectory(folderPath); 
       string fullPath = Path.Combine(folderPath, fileName); 
       File.WriteAllText(fullPath, queryText); 
      } 
      catch (Exception ex) 
      { 
       MessageBox.Show(ex.ToString()); 
      } 
     } 

     public void OnDisconnection(ext_DisconnectMode disconnectMode, ref Array custom) { } 

     public void OnAddInsUpdate(ref Array custom) { } 

     public void OnStartupComplete(ref Array custom) { } 

     public void OnBeginShutdown(ref Array custom) { } 

     public void QueryStatus(string commandName, vsCommandStatusTextWanted neededText, ref vsCommandStatus status, ref object commandText) 
     { 
      if (neededText == vsCommandStatusTextWanted.vsCommandStatusTextWantedNone) 
      { 
       if (commandName == "SSMSAddin.Connect.SSMSAddin") 
       { 
        status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled; 
        return; 
       } 
      } 
     } 

     public void Exec(string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled) 
     { 
      handled = false; 
      if (executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault) 
      { 
       if (commandName == "SSMSAddin.Connect.SSMSAddin") 
       { 
        var document = ((DTE2)ServiceCache.ExtensibilityModel).ActiveDocument; 
        if (document != null) 
        { 
         //replace currently selected text 
         var selection = (TextSelection)document.Selection; 
         selection.Insert(
@"Welcome to SSMS. This sample is brought to you by 

SSMSBoost add-in team 

Check www.ssmsboost.com for updates.", 
(Int32)EnvDTE.vsInsertFlags.vsInsertFlagsContainNewText); 
        } 

        handled = true; 
        return; 
       } 
      } 
     } 
    } 
} 

的代码添加每个SQL火灾之前在2012年SSMS执行的事件......我打了F5 ,sql查询会运行,但在运行之前,它会将查询的副本保存到B:\SSMS Queries\20130225\083000.sql

有什么缺点?我想为使用的Connection/Databse添加选项,例如B:\SSMS Queries\Localhost\Northwind\20130225\083000.sql(只是一个例子)。

我通常会做的......断点,一步一步,检查对象等等......虽然这是一个插件。类库。你不能断点/步骤通过一个库...

我如何把一个断点放入一个类库,被加载到SSMS/Visual Studio,以便我可以研究?或者什么是这种修补的好资源? object customin, object customout中的某处是我想要修补的信息。

+2

在项目属性的调试选项卡将它设置为启动外部程序,并输入路径SSMS 2012(例如'C:\ PROGRAM文件(x86)\ Microsoft SQL Server \ 110 \ Tools \ Binn \ ManagementStudio \ Ssms.exe),然后您可以放入一个中断点并以调试模式运行它。另请参阅关于SSMSAddin.addin文件的信息[here](http://www.ssmsboost.com/create-own-ssms-2012-add-in-sample-code-with-download)。 – 2013-02-26 08:06:18

+1

@MartinSmith如果我编译,将SSMSAddin DDL和Addin文件移动到文件夹,并启动SSMS 2012 - 它的工作原理 - 查询保存到文件夹。如果我将VS2012指向SSMS2012,然后指向F10,则会抛出“检测到PInvokeStackImbalance”错误。所以我可以使用插件,但我无法调试它。希望我可以upvote你+10 btw :) – WernerCD 2013-02-26 13:55:47

+0

奇怪......它给了我多个错误,但如果我一直按F5,我最终到达断点。 – WernerCD 2013-02-26 13:59:29

回答

0

其实记录我的答案(忘记多次后)。发现我的答案在SSMSBoostTSQLTidy.Blogspot(和马丁·史密斯评论)的组合

1) Set SSMS as the startup project inside Debug Profile. File location for SSMS2012: 
    C:\Program Files (x86)\Microsoft SQL Server\110\Tools\Binn\ManagementStudio\SSMS.exe 
2) I've created 2 Addin files: 
    MyAddin.Debug.Addin 
    MyAddin.Release.Addin 
    (Contents updated as listed below) 
3) Add postbuild event to create directory if not exists 
4) Add postbuild event to copy Addin from ProjectDir to MSeventShared 
5) Turn off P-Invoke warnings. Press CRLT + ALT + E - In Managed Debugging Assistants, find PInvokeStackImbalance, untick it. 

外接程序文件(版本中的更改从项目目录MSEnvShared \ Admin文件夹中的DLL位置):

<?xml version="1.0" encoding="UTF-16" standalone="no"?> 
<Extensibility xmlns="http://schemas.microsoft.com/AutomationExtensibility"> 
    <HostApplication> 
     <Name>Microsoft SQL Server Management Studio</Name> 
     <Version>*</Version> 
    </HostApplication> 
    <Addin> 
     <FriendlyName>MyAddin.</FriendlyName> 
     <Description>MyAddin Description.</Description> 
     <Assembly>C:\Projects\MyAddin\bin\Debug\MyAddin.dll</Assembly> 
     <FullClassName>SSMSAddin.Connect</FullClassName> 
     <LoadBehavior>0</LoadBehavior> 
    <CommandPreload>1</CommandPreload> 
    <CommandLineSafe>0</CommandLineSafe> 
    </Addin> 
</Extensibility> 

后生成事件:

cmd /x /c mkdir "C:\ProgramData\Microsoft\MSEnvShared\Addins\" 
cmd /C copy "$(ProjectDir)MyAddin.$(ConfigurationName).Addin" "C:\C:\ProgramData\Microsoft\MSEnvShared\Addins\MyAddin.Addin" 
1

问题的第二部分,以寻找到当前数据库的连接..

添加对Microsoft.SqlServer.RegSrvrEnum.dll和SqlWorkBench.Interfaces的引用(位于C:\ ProgramFiles .. \ SQL Server .. - 中的某处)。确保你已经安装了SDK的工具。

然后下面的代码应该做的伎俩(您的欢迎!)

IScriptFactory scriptFactory = ServiceCache.ScriptFactory; 
CurrentlyActiveWndConnectionInfo connectionIfno = scriptFactory.CurrentlyActiveWndConnectionInfo; 
UIConnectionInfo conn = connectionIfno.UIConnectionInfo; 
Debug.WriteLine("{0}::{1}", conn.ServerName, conn.AdvancedOptions["DATABASE"]);