Zine.net online

Witaj na Zine.net online Zaloguj się | Rejestracja | Pomoc
w Szukaj

dev2dev

Zrób to sam - SSMS addin (Window)

W tym odcinku zaprezentuję schemat dodawania własnych okien (jako obiektów UserControl) do wtyczki SSMS. Wykorzystam do tego celu okna, które zastosowałem w innej wtyczce do SSMS, która zarządzała obiektami Service Broker. Zawartość wyświetlana przez okna będzie zmieniała się dynamicznie przy zmianie dwóch kontekstów:

  • kontekst serwera – okno pokazujące obiekty Service Broker aktywne dla danego serwera, w kontekście którego aktualnie się znajdujemy w SSMS (z możliwością zmiany statusu danej instancji Service Broker),
  • kontekst bazy danych – okno pokazujące infrastrukturę obiektów Service Broker dla kontekstu aktualnie wybranej bazy danych w Object Explorer SSMS.

I. Window

Tak jak pisałem powyżej, nasze okno będzie komponentem UserControl z implementacją prostego interfejsu zapewniającego odświeżenie jego zawartości:

using System;
using System.Collections.Generic;
using System.Text;

namespace ToolWindows
{
    public interface IRefreshData
    {
        void RefreshData();
    }
}

Kontrolka prezentująca obiekty Service Broker jest bardzo prosta. Składa się z kontrolki Menu oraz kontrolki DataGridView.

 

Chociaż okienko odświeża się automatycznie opcja menu Refersh została dodana jedynie dla przykładu możliwości wstawiania własnego menu do okienka wtyczki. Metoda RefreshData dla tego okna jest bardzo prosta.

public void RefreshData()
{
    string connectionString = UtilitySqlTools.Current.ConnectionString();

    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        try
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("SELECT   name AS [Database Name],");
            sb.AppendLine("         Upper(service_broker_guid) AS GUID,");
            sb.AppendLine("         is_broker_enabled [Is broker enabled?]");
            sb.AppendLine("FROM sys.databases");

            SqlDataAdapter da = new SqlDataAdapter();
            da.SelectCommand = new SqlCommand();
            da.SelectCommand.CommandText = sb.ToString();
            da.SelectCommand.CommandTimeout = 0;
            da.SelectCommand.CommandType = CommandType.Text;
            da.SelectCommand.Connection = connection;

            DataSet ds = new DataSet();
            da.Fill(ds);

            dgBrokers.DataSource = ds.Tables[0];
            dgBrokers.Columns["Is broker enabled?"].ReadOnly = false;
        }
        catch (Exception exception)
        {
            // Logger
        }

        connection.Close();
    }
}

W powyższym kodzie najbardziej istotne jest uzyskanie connection string do aktualnie wybranego w SSMS serwera. Sposób jego odzyskania został opisany wcześniej tutaj.

Z punktu widzenia automatyki odświeżania zawartości tego okna przy zmianie kontekstu serwera to wszystko. Mając connection string jesteśmy w stanie w naszym okienku robić praktycznie wszystko “czego nie zabraniają pozostałe paragrafy” cytując za bohaterem książki “Paragraf 22”. W szczególności nasze okno może być bardzo rozbudowane (tak jak okno do infrastruktury obiektów Service Broker), którego nie będę tu analizować a jedynie pokażę go w działaniu na końcu tego odcinka.

II. Jak dodać okno do SSMS?

Mechanizm dodawania okien do SSMS jest bardzo prosty. Ogólna metoda tworzenia nowego ona na zakładce Tool Windows w SSMS jest następująca:

private Window CreateToolWindow(    string typeName,
                                           string assemblyLocation,
                                           Guid uiTypeGuid,
                                           DTE applicationObject,
                                           AddIn addinInstance,
                                           string caption)
       {
           Windows2 win2 = applicationObject.Windows as Windows2;

           if (win2 != null)
           {
               object controlObject = null;
               Window toolWindow = win2.CreateToolWindow2( addinInstance,
                                                           assemblyLocation,
                                                           typeName,
                                                           caption,
                                                           "{" + uiTypeGuid.ToString() + "}",
                                                           ref controlObject);
               toolWindow.Visible = true;
               return toolWindow;
           }
           return null;
       }

Parametrami tej metody są:

  • typeName – nazwy typu obiektu okna,
  • assemblyLocation – ścieżka do assembly,
  • uiTypeGuid – identyfikator obiektu,
  • applicationObject – instancja obiektu SSMS,
  • addinInstance – instancja obiektu wtyczki,
  • caption – caption naszego okienka na zakładce Tool Windows.

Metoda CreateToolWindow2 tworzy nawą zakładkę na obszarze Tool Windows SSMS a jednocześnie w parametrze controlObject zwraca instancję obiektu typu typeName. Również właściwość toolWindow.Object zwraca referencję to tego obiektu co jest szczególnie istotne w naszych zastosowania do automatyzacji odświeżania zawartości okienek.

Szczegółowa metoda dodawania naszego przykładowego okna z zawartością Service Brokers dla domyślnego serwera z SSMS jest niemniej prosta:

public void CreateBrokersWindow(DTE application, AddIn addinInstance)
        {
            if (toolBrokersWindow == null)
            {
                Assembly asm = Assembly.Load("ToolWindows");
                Guid id = Guid.NewGuid();

                toolBrokersWindow = CreateToolWindow(   "ToolWindows.Brokers",
                                                        asm.Location,
                                                        id,
                                                        application,
                                                        addinInstance,
                                                        brokersWindowCaption);

                toolBrokersWindow.Height = 400;
                toolBrokersWindow.IsFloating = false;
                toolBrokersWindow.SetTabPicture(ToolsResource.Windows.GetHbitmap());
                application.MainWindow.LinkedWindows.Add(toolBrokersWindow);
                application.MainWindow.LinkedWindows.Item(brokersWindowCaption).AutoHides = true;
            }
        }

Nasze okienko znajduje się w assembly ToolWindows i jest klasy ToolWindows.Brokers. Dodatkowo ustawiamy jego wysokość, żądamy aby nie było oknem pływającym (czyli dokowanym), Dodajemy ikonkę przy pomocy metody SetTabPicture (dodawałem obraz bitmap i metoda, którą tu zastosowałem jest skuteczna, inne metody okazały sie zawodne). Dodajemy nasze okienko do kolekcji LinkedWindows obiektu MainWindow w SSMS i żądamy aby ukrywało sie automatycznie.

Teraz modyfikujemy metodę initializeAddin opisaną w poprzednich odcinkach dodając do niej kod:

private void initializeAddIn()
{
    try
    {
        if (Controller.Current.BrokersWindow == null)
            Controller.Current.CreateBrokersWindow(applicationObject, addInInstance);
    }
    catch (Exception exception)
    {
        // Logger
    }

który tworzy i dodaje nasze okienko do SSMS.


I to wszystko jeżeli chodzi o dodanie okienka do SSMS. Mechanizm ten można oczywiście zastosować z powodzeniem do dodawania okienek poprzez menu (tak jest w przypadku okienka prezentującego infrastrukturę obiektów Service Broker).

III. Jak automatycznie odświeżać zawartość naszych okienek?

Czytelnicy tej serii zapewne pamiętają, że w różnych miejscach kodu naszej wtyczki pojawiały się “zwinięte” regiony kodu o nazwach “Refresh database related windows” oraz “Refresh server related windows”. W te miejsca wstawiamy odpowiednio metody:

  • RefershBrowsers – do regionu “Refresh server related windows”,
  • RefreshInfrastructure – do regionu “Refresh database related windows”.

Wspomniane wyżej metody wyglądają następująco:

/// <summary>
/// Refresh Service Brokers window
/// </summary>
private void RefreshBrokers()
{
    if (Controller.Current.BrokersWindow != null)
    {
        ToolWindows.Brokers brokersWin =
                (ToolWindows.Brokers)Controller.Current.BrokersWindow.Object;

        brokersWin.ConnectionString = dbContext.ConnectionString;

        brokersWin.RefreshData();
    }
}

private void RefreshInfrastructure()
{
    if (Controller.Current.InfrastructureWindow != null)
    {
        ToolWindows.Infrastructure infraWin =
                (ToolWindows.Infrastructure)Controller.Current.InfrastructureWindow.Object;

        infraWin.CurrentDatabase = dbContext.Database;

        infraWin.RefreshData();
    }
}

Jak to wygląda w działaniu? Do ObjectExplorer podłączamy dwa serewry przełączając sie między nimi zauważymy, że okno Browsers dopasowuje się dynamicznie do zmienionej sytuacji.

W naszej wtyczce dodałem jeszcze jeden element, Show infrastructure,


który wyzwala polecenie pokazania infrastruktury obiektów Service Broker dla aktualnie wybranej bazy danych.

Uruchomienie go gdy w Object Explorer nie została wybrana domyślna baza danych kończy się komunikatem:


ponieważ w metodzie obsługi tego polecenia ustawiliśmy atrybut, że wymaga ono kontekstu domyślnej bazy danych. Gdy kontekst taki określimy wybierając w Object Explorer konkretną baz danych to zobaczymy:


Klikając na zakładkę Service Broker infrastructure zobaczymy:


Zmieniając w Object Explorer domyślną bazę danych możemy zaobserwować dopasowywanie się tego okna do zmieniającej się struktury obiektów Service Broker w tej bazie. I o to nam chodziło :).

Linki:

do następnego odcinka serii o tworzeniu wtyczki do SSMS

do poprzedniego odcinka serii o tworzeniu wtyczki do SSMS



Opublikowane 26 października 2009 08:50 przez marekpow

Komentarze:

 

dotnetomaniak.pl said:

Dziękujemy za publikację - Trackback z dotnetomaniak.pl

października 26, 2009 11:37
Komentarze anonimowe wyłączone
W oparciu o Community Server (Personal Edition), Telligent Systems