2013-02-26 86 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"]);