title: SSMS Extensibility Project - howto research/debug
body: <p>In the vein of <a href="https://dba.stackexchange.com/a/25396/653">this answer</a> regarding creation of an SSMS Extension:</p>
  
  <pre><code>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) &amp;&amp; (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;
                  }
              }
          }
      }
  }
  </code></pre>
  
  <p>The code adds an event that fires before each SQL Execute in SSMS 2012... I hit F5, the sql query runs, but before it runs it saves a copy of the query to <code>B:\SSMS Queries\20130225\083000.sql</code>.</p>
  
  <p>What's missing from this? I want to add options for the Connection/Databse used, say for example <code>B:\SSMS Queries\Localhost\Northwind\20130225\083000.sql</code> (Just an example).</p>
  
  <p>What I would normally do... Breakpoint, step through, inspect objects, etc... This is a addon though. Class library. You can't breakpoint/step through a library...</p>
  
  <p>How do I put a breakpoint into a class library that gets loaded into SSMS/Visual Studio so that I can research? Or what would be a good resource for this kind of tinkering? Somewhere in <code>object customin, object customout</code> is the information I want to tinker with.</p>