17/11/2009

SharpPcap

Home

WinPcap to dobrze znane wielu osobom narzędzie umożliwiające przechwytywanie i analizę ruchu sieciowego, jego generowanie oraz wiele innych rzeczy. W oparciu o WinPcap została napisana inna bardzo przydatna aplikacja WireShark. Narzędzi te są bezwątpienia bardzo przydatne ale co jeśli chcemy samemu zaimplementować algorytm analizujący ruch sieciowy. Dodatkowo najlepiej by było zrobić to w C# i nie babrać się w mechanizmach interoperacyjności z kodem niezarządzanym, bawić z atrybutem DllImport itd. Oczywiście chcemy również skorzystać z możliwości WinPcap.

Dokładnie w takiej sytuacji znalazłem się ostatnio. Wypróbowałem kilka rozwiązań ale szeroki uśmiech na mojej twarzy wywołała biblioteka SharpPcap. Została napisana w oparciu o WinPcap ale ukrywa przed użytkownikiem wszelkie odwołania do niezarządzanego kodu. Do tej pory przetestowałem tylko jej podstawowe funkcje ale wydaje się działać bardzo dobrze, a pracuje się z nią przyjemnie.

Zastanawiałem się nad zamieszczeniem tutaj jakiegoś przykładu użycia ale jestem zwolennikiem zasady "Po co robić coś co zostało już zrobione". Zainteresowanych zachęcam więc do pobrania biblioteki i zapoznania się z załączonymi przykładami, które są dobrze skomentowane. .

09/11/2009

Jeszcze o rysowaniu wykresów

Home

Kilka miesięcy temu pisałem o komponencie do rysowania wykresów firmy Xceed. Teraz postanowiłem przyjrzeć się dwóm innym komponentom: Komponent pierwszy jest do pobrania za darmo ze strony Microsoftu. Za drugi trzeba już płacić ale producent udostępnia wersję demonstracyjną.

Najpierw zainstalowałem komponent firmy Dundas. Od razu spodobał mi się program pokazujący przykłady różnych wykresów wraz z kodem. Dobre wrażenie sprawił również kreator zintegrowany z VS do konfigurowania kontrolki. Ogólnie pierwsze wrażenie bardzo pozytywne. Na dalszy ogień poszło rozwiązanie Microsoftu. W porównaniu do poprzednika od razu rzucił mi się w oczy brak kreatora i programu demonstracyjnego (można go pobrać oddzielnie tutaj).

Następnie zaczynam przyglądać się interfejsowi programistycznemu. Patrzę, patrzę i mam wrażenie deja vu. Pomimo pewnych różnic oba produkty mają bardzo, bardzo podobne API. Chwila zastanowienia i wpisuję w Google ''Microsoft Chart Control vs. Dundas Chart Control''. Pierwszy link i wszystko staje się jasne. Począwszy od roku 2007 Microsoft posiada prawa do własności intelektualnej firmy Dundas, a przejawem tego jest komponent Microsoft Chart Controls for Microsoft .NET Framework 3.5 oparty o kod Dundas Chart for .NET.

Podsumowując można za darmo pracować z bardzo fajną kontrolką pamiętając jednak o tym, że produkt Microsoftu posiada do pewnego stopnia ograniczoną względem oryginału funkcjonalności. Po drugie firma Dundas udziela wsparcie tylko na produkty zakupione bezpośrednio od nich. Nie jestem również pewny czy nowe usprawnienia, które wprowadzają programiści z Dundas są również dostępne w wersji Microsoftu (pewnie nie).

02/11/2009

Problem z SqlDependency. Czyżby?

Home

Post ten dotyczy mechanizmu query notification, który pozwala na otrzymywanie powiadomień o zmianach w bazie danych dotyczących wybranych wierszy. Funkcjonalność ta jest dostępna na poziomie programistycznym między innymi przez łatwą w użyciu klasę SqlDependency (Jest to opakowanie na klasę SqlNotificationRequest). W Internecie można znaleźć bardzo dużo przykładów użycia tej klasy nie będę, więc powielał tego co zostało już napisane. Chciałbym natomiast zwrócić uwagę, że chociaż warunkiem koniecznym użycia powiadomień jest użycie SQL Server'a w wersji 2005 lub późniejszej to nie jest to warunek wystarczający.

Wszystko zaczęło się od tego, że postanowiłem przyjrzeć się dokładnie temu mechanizmowi. Do testów wybrałem chyba dobrze znana bazę Northwind. Bardzo szybko udało mi się stworzyć testową aplikację ale po jej uruchomieniu okazało się, że powiadomienia nie są generowane albo aplikacja ich nie otrzymuje. Kod sprawdziłem kilka razy, dla pewności przejrzałem kilka opisów w sieci i nic.

W końcu postanowiłem wykorzystać kody pokazane w jednym z tutoriali, wraz z użytą w tam bazą danych. Po chwili okazało się, że działa. Zmodyfikowałem, więc swoją aplikację aby używała właśnie tej bazy danych. Chwila niepewności, uruchamiam i również działa.

Dochodzę do wniosku, że nie ma mocnych, problem musi tkwić gdzieś w bazie danych. Porównuję konfigurację obu baz danych i znajduję winnego - tryb kompatybilności. Okazało się, że po zainstalowaniu baza Northwind ma ustawiany tryb kompatybilności na SQL Server 2000, zamiast SQL Server 2005. Mała, głupia sprawa, a można stracić trochę czasu.

26/10/2009

CodeBehind i CodeFile

Home

Jakiś czas temu pisząc prostą aplikacje WWW utworzyłem z rozpędu projekt typu Web Application zamiast Web Site. Zanim się zorientowałem popełniłem już trochę kodu stwierdziłem więc, że nie będę pisał go od początku. Usunąłem projekt z solution, wykasowałem plik z rozszerzeniem csproj i skorzystałem z polecenia Add -> Existing Web Site.... Wszystko wydawało się w porządku do momentu kiedy spróbowałem skompilować aplikację. W efekcie otrzymałem komunikat jak poniżej:

Could not load type 'PageName'.

Przy drugiej próbie kompilacji otrzymałem taki sam błąd kompilacji. Patrzę i patrzę w kod strony i nic. Przecież jeszcze 5 minut temu kompilowało się, czary? Oczywiście, że nie. Po chwili przypominam sobie o jednej drobnej różnicy. W przypadku projektów typu Web Application w dyrektywie @Page używa się atrybutu CodeBehind, a w przypadku Web Site'ów atrybutu CodeFile. Niby szczegół ale jeśli się o nim zapomni może popsuć trochę krwi.

19/10/2009

Trochę o zwalnianiu zasobów

Home

Każdy dobry programista wie, że po skończeniu pracy z obiektem klasy implementującej interfejs IDisposable należy wywołać metodę Dispose (jawnie bądź nie jawnie). Dlatego kiedy ostatnio zobaczyłem kod, w którym programista beztrosko raz po raz tworzy ikonę, a następnie radośnie o niej zapomina powodując wzrost liczby obiektów GDI przez usta przeszły mi dość niecenzuralne słowa. Oczywiście od razu poprawiłem kod w mniej więcej taki sposób:
using(Icon icon = GetIcon())
{
   ...
}
Nic prostszego można powiedzieć. Jednak przy następnym uruchomieniu aplikacji ku mojemu zdziwieniu liczba obiektów GDI znowu zaczęła rosnąć. Zaglądam, więc do metody GetIcon. A tam widzę coś takiego:
return Icon.FromHandle(handle);
Nie kojarząc za bardzo metody FromHandle zaglądam do dokumentacji, a tam jest napisane coś takiego:

When using this method you must dispose of the resulting icon using the DestroyIcon method in the Win32 API to ensure the resources are released.

Kolejny mój krok to oczywiście sprawdzenie czy wywołanie DestroyIcon działa. Metodę tą należy zadeklarować w następujący sposób:
[System.Runtime.InteropServices.DllImport("user32.dll", CharSet=CharSet.Auto)]
extern static bool DestroyIcon(IntPtr handle);
Jej użycie oczywiście rozwiązało problem. Co dociekliwsi mogą jeszcze zapytać czemu wywołanie Dispose nie wystarcza. Sprawa jest dość ciekawa. Okazuje się, że klasa Icon używa wewnętrznie DestroyIcon do zwalniania zasobów ale tylko i wyłącznie wtedy kiedy jest właścicielem tych zasobów to jest kiedy sama je zaalokuje. W momencie tworzenia ikony przy pomocy uchwytu dostarczonego z zewnątrz trzeba samemu zadbać o jego zwolnienie.

Reasumując w opisanym przypadku dwóch programistów zrobiło dwa poważne błędy. Pierwszy zapomniał o zwolnieniu zasobów, a drugi o dokładnym przeczytaniu dokumentacji. Metoda GetIcon powinna zostać napisana tak aby korzystający z niej programista nie musiał posiadać wiedzy "tajemnej" aby dobrze jej użyć.