Jak debugować kod kontrolki SSIS?

Skoro na razie nie mamy testów jednostkowych, to trzeba wykombinować jak sprawdzać o co chodzi z błędami, które się pojawiają przy tworzeniu kontrolki. Dobrze jednak by było wiedzieć coś więcej niż enigmatyczne komunikaty „nieprawidłowe coś tam w czymś”. Kiedy ustawimy jednak punkt przerwania (breakpoint) i uruchomimy projekt wyskakuje okienko, że dla biblioteki to nie da się ot tak kliknąć i już.

DebugTypeLibraryError

Jak w takim razie sprawdzać co się dzieje bez konieczności ustawiania zbędnych fragmentów kodu, które np. wypiszą nam coś na konsoli (albo – o zgrozo – zastosują MsgBox)? Fajne są te narzędzia w Visual Studio i chcemy z nich korzystać! I kropka.

No to skorzystajmy. I przeżyjmy krótką przygodę z elementami pytań i zdziwień.

Metoda #1 – dtexec.exe

Po zbudowaniu (Build / Rebuild) i zainstalowaniu w GAC kontrolki oraz managera połączeń przechodzimy do opcji projektu ssis-winscptask:

  • albo prawym przyciskiem myszy na nazwie projektu ssis-winscptask i wybrać Propertes
  • albo będąc w projekcie ssis-winscptask nacisnąć kombinację klawiszy Alt + Enter (promujemy skróty klawiszowe)
  • albo będąc w projekcie ssis-winscptask z poziomu menu PROJECT wybrać ssis-winscptask Properties

W opcjach projektu ustawiamy wywołanie zewnętrznego programu DTexec.exe wraz z całą ścieżką (inaczej otrzymamy komunikat „The external program cannot be found”). W moim przypadku ścieżka to C:\Program Files (x86)\Microsoft SQL Server\130\DTS\Binn\DTExec.exe. Potem podajemy Command line arguments i tu chwila zastanowienia. W MSDN możemy przeczytać: „Often the command-line argument will consist of the /F[ILE] switch followed by the path and file name of the .dtsx file”. Jeśli użyjemy przełącznika File, to wszystkie elementy potrzebne do uruchomienia muszą być dostępne w pliku pakietu. W przypadku naszej kontrolki mamy dwa managery połączeń – jeden jest utworzony bezpośrednio w pakiecie (WinSCP Connection Manager), drugi jest na poziomie projektu (WIN-6EUDR62M1ON_SQL2016CTP3.ssistaskdb.ssis-winscptask) – jeśli użyjemy przełącznika /File
zobaczymy komunikat „The connection „WIN-6EUDR62M1ON_SQL2016CTP3.ssistaskdb.ssis-winscptask” is not found. This error is thrown by Connections collection when the specific connection element is not found.”. Dlaczego potrzebna chwila zastanowienia? Bo albo utworzymy manager połączeń do SQL Server na poziomie pakietu, albo wywołamy DTexec.exe z parametrami dla projektu.

Sprawdźmy oba podejścia i zobaczmy czy będzie jakaś różnica w jakości pracy. Najpierw utworzymy nowy manager połączeń na poziomie pakietu SSIS i ustawimy go w opcji SQLServerConnectionManagerName kontrolki WinSCPTask. Potem w ustawieniach debugowania projektu w polu Command line arguments ustawimy opcję /File CustomTask.dtsx. Dodatkowo jako Working Directory ustawimy katalog z lokalizacją pliku (o ile podaliśmy samą nazwę pliku przy parametrze /File), na koniec ustawiamy dwa breakpointy – na metodach Validate i Execute w pliku WinSCPTask.cs i można naciskać Start.

DebugProjectSettingsFile

Druga opcja to wywołanie DTexec.exe z parametrami projektu i tutaj jest mały haczyk. Wywołanie projektu wygląda tak:

dtexec.exe /Project C:\Users\brata_000\Source\Repos\ssis-winscptask\ssis-winscptask\SSIS\bin\Development\SSIS.ispac /Package CustomTaskTest.dtsx

/Project to ścieżka do pliku .ispac uruchamianego projektu, natomiast /Package to nazwa pliku w ramach tego projektu. Podkreślam specjalnie to, że w ramach projektu – nie podajemy żadnej ścieżki bezwzględnej tak jak do pliku projektu. Ponownie ustawiamy dwa breakpointy – na metodach Validate i Execute w pliku WinSCPTask.cs i można naciskać Start.

DebugProjectSettings

I jest prawie dobrze.

Debugger uruchamia program DTexec.exe – pojawia się jako odrębne okienko konsolowe – i ustawia się na starcie metody Validate. Kolejne naciśnięcia Step Over (F10) i po wyjściu z metody Validate nagle trafiamy do metody ReleaseConnection w managerze połączeń WinSCP. Ciekawe, warto zanotować na boku – wygląda, że przy końcu walidacji zwalnia połączenia managerów połączeń?

Nic to, naciskamy znów F10, żeby przejść do następnego kroku i znowu jesteśmy w metodzie Validate. Ale jak to? No nie wiadomo, ale idziemy dalej – powtarza się krok ReleaseConnection i po wyjściu z niego kończy się program DTExec.exe i praca debuggera. No ale przecież miało przejść potem do metody Execute? Próbujemy kilkukrotnie – czy to z konfiguracją /Project + /Package czy /File i za każdym razem to samo.

Po dokładniejszym studiowaniu instrukcji narzędzia DTexec.exe pokazuje się przełącznik /CONSOLE, który pokaże nam komunikaty postępu takie jak w Visual Studio w zakładce Progress / Execution Results – z możliwością ograniczania wyświetlanych informacji. Po kilku próbach uruchomienia i śledzeniu wypisywanych informacjami wybieramy opcje /CONSOLE NSMT (N – nazwa akcji, S – nazwa elementu, M – komunikat, T – czasy początku i końca operacji). Cała treść pola Command line arguments wygląda zatem tak:

/Project C:\Users\brata_000\Source\Repos\ssis-winscptask\ssis-winscptask\SSIS\bin\Development\SSIS.ispac /Package CustomTaskTest.dtsx /CONSOLELOG NSMT > log.txt

Ponieważ przekierowuję wszystkie komunikaty do pliku tekstowego, to ustawiam jakoWorking directory katalog C:\temp, który pełni u mnie rolę katalogu tymczasowego. I uruchamiam ponownie z przerwami między uruchomieniami kolejnych wejść do metody Validate – żeby łatwiej namierzyć momenty uruchamiania kolejnych kawałków kodu. Po prześledzeniu pliku logu widać że:

  • walidacja występuje dwukrotnie, ponieważ pierwszy raz jest uruchamiana przy zdarzeniu OnPreValidate zaraz przy otwarciu pakietu, a drugi raz także przy OnPreValidate, ale wyzwalanego po operacji uruchamiania pakietu
  • pakiet nie idzie dalej z powodu komunikatu błędu: To run a SSIS package outside of SQL Server Data Tools you must install Standard Edition of Integration Services or higher.

Dokładnie taki sam komunikat otrzymujemy, jeśli na komputerze z zainstalowanym tylko Visual Studio spróbujemy uruchomić DTExec.exe z parametrami /File czy /Project/Package bezpośrednio w konsoli.

DTExecConsoleError

Wniosek: metoda #1 odpada przy testowaniu bez zainstalowanej usługi Integration Services.

Metoda #2 – podłączanie się do innej sesji

Ponieważ instalowanie Integration Services tylko po to, żeby testować uruchamianie pakietu nie zawsze musi być możliwe do wykonania (chociaż wersja SQL Server Developer Edition jest dostępna za darmo w ramach programi Visual Studio Dev Essentials) to przechodzimy do innej metody: w jednej sesji Visual Studio uruchomimy pakiet SSIS, a w drugiej się do niej podepniemy. Ale do zanotowania na boku: przetestować metodę #1 z zainstalowaną usługą Integration Services.

Do rzeczy – ponieważ nasze rozwiązanie (solution) zawiera także projekt o nazwie SSIS typu Integration Services uruchamiamy go ustawiając breakpoint na akcji OnPreExecute – bez różnicy czy to dla całego pakietu, czy tylko kontrolki. Potem uruchamiamy drugą instancję Visual Studio z naszym projektem – WAŻNE! w trybie administratora – i ponownie ustawiamy breakpointy na metodach Validate i Execute w pliku WinSCPTask.cs. Potem przechodzimy do menu DEBUG > Attach to Process … i z listy wybieramy proces DtsDebugHost.exe – co ważne typu Managed, x86, a nie samego x86. Po wybraniu naciskamy przycisk Attach, przechodzimy z powrotem do Visual studio z uruchomionym pakietem SSIS i naciskamy na pasku narzędzi przycisk Continue (lub zgodnie z duchem propagowania skrótów klawiszowych – F5). Pakiet uruchomi się dalej i nastąpi automatyczne przełączenie do Visual Studio z otwartym projektem i breakpointem na metodzie Validate.

Tym razem jest jednak tak, jak się spodziewamy – przejście przez metodę Validate następuje raz, a potem przechodzimy do metody Execute. W odróżnieniu od uruchamiania za pomocą DTExec.exe tutaj nie ma przejścia przez managera połączeń i metodę ReleaseConnection.

Niestety taka metoda ma dużą upierdliwość przy stosowaniu – po zakończeniu pętli debugowania za każdym razem musimy uruchamiać pakiet SSIS w jednym oknie Visual Studio, a następnie przez menu DEBUG > Attach to Process … podłączyć się do odpowiedniego procesu.

W dokumentacji MSDN jest wymieniona jeszcze trzecia opcja – debugowanie metod z poziomu desigera, czyli podczas używania komponentów w Control Flow czy Data Flow. Ale o tym będzie mowa przy tworzeniu GUI do naszej kontrolki i naszego managera połączeń.

Dodaj komentarz