12/09/2011

IntelliTrace - problem ze zdarzeniem

Home

Jakiś czas temu pracując z IntelliTrace próbowałem zdefiniować zdarzenie diagnostyczne dla pewnej metody. Dla ustalenia uwagi niech jej sygnatura wygląda tak, jak poniżej.

string Flip(string s)

Moim celem było, aby opis zdarzenia zawierał wynik zwrócony przez metodę oraz wartość argumentu s. Inaczej mówiąc, aby w oknie IntelliTrace Events View w Visual Studio 2010 zdarzenie zarejestowane dla wywołania metody z argumentem s="Hello" i wynikiem "olleH" wyglądalo tak:

"olleH" Flip("Hello")

O definiowaniu zdarzeń IntelliTrace już pisałem (Własne zdarzenia IntelliTrace!, Własne zdarzenia IntelliTrace 2) dlatego nie będę opisywał całego procesu. Przytoczę już gotową definicję zdarzenia:
<DiagnosticEventSpecification enabled="true">
  <Bindings>
    <Binding>
      <ModuleSpecificationId>FibTest.exe</ModuleSpecificationId>
        <TypeName>Utilities</TypeName>
        <MethodName>Flip</MethodName>
        <MethodId>Utilities.Flip(System.String):System.String</MethodId>
        <ShortDescription _locID="shortDescription.Utilities.Flip">"{0}" Flip("{1}")</ShortDescription>
        <LongDescription _locID="longDescription.Utilities.Flip">"{0}" Flip("{1}")</LongDescription>
        <DataQueries>
          <DataQuery index="-1" maxSize="100" type="String" query="" />
          <DataQuery index="1" maxSize="100" type="String" query="" />
        </DataQueries>
        <ProgrammableDataQuery>
          <ModuleName></ModuleName>
          <TypeName></TypeName>
        </ProgrammableDataQuery>
    </Binding>
  </Bindings>
  ...
</DiagnosticEventSpecification>
Niestety ku moje zdziwieniu to nie zadziałało. Zdarzenie zostało zarejestrowane, ale w oknie IntelliTrace Events View zamiast zobaczyć upragniony wynik otrzymałem komunikat: An error occured while fetching the data for this event. Zajrzałem, więc do wcześniej zdefiniowanych przez siebie zdarzeń i przypomniałem sobie o jednej rzeczy. Aby odwołać się do wartości zwróconej przez metodę należy ustawić atrybut onReturn.
...
<Binding onReturn="true">
...
Niestety to też nie pomogło. Ponownie zajrzałem więc do wcześniej przygotowanych zdarzeń i na pierwszy rzut oka wszystko wyglądało tak samo. Po chwili zastanowienia doszedłem do wniosku, że przyczyną kłopotów może być to, że próbuję odwołać się zarówno do wartości argumentów jak i do wartości zwracanej przez metodę. Wcześniej czegoś takiego nie próbowałem. Zamiast jednego przygotowałem więc dwa zdarzenia. W jednym odczytuję wartość argumentu przekazanego do metody, a w drugim wynik zwrócony przez metodę.
...
<Binding onReturn="false">
  ...
  <ShortDescription _locID="shortDescription.Utilities.Flip">Flip("{0}")</ShortDescription>
  <LongDescription _locID="longDescription.Utilities.Flip">Flip("{0}")</LongDescription>
  <DataQueries>
    <DataQuery index="1" maxSize="100" type="String" query="" />
  </DataQueries>
  ...
</Binding>
...
...
<Binding onReturn="true">
  ...
  <ShortDescription _locID="shortDescription.Utilities.Flip">Flip returns "{0}"</ShortDescription>
  <LongDescription _locID="longDescription.Utilities.Flip">Flip returns "{0}"</LongDescription>
  <DataQueries>
    <DataQuery index="-1" maxSize="100" type="String" query="" />
  </DataQueries>
  ...
</Binding>
...
To zadziałało, zostały zarejestrowane dwa zdarzenia, jedno z opisem Flip("Hello"), a drugie z opisem Flip returns "olleh". Moim zdaniem to spore ograniczenie IntelliTrace, ale nie ma rady i trzeba o tym po prostu pamiętać.

11/09/2011

Londyn - trochę nietypowa wycieczka

Home

Londyn to miasto odwiedzane rokrocznie przez miliony turystów. Twierdza Tower, Tower Bridge, Pałac Buckingham to tylko z niektórych miejsc, które znajdują się na liście do zobaczenia dla wielu odwiedzających. Ja też nie omieszkałem pokazać się w tych i wielu innych miejscach, ale w tym poście chciałbym zachęcić do wizyty w innym, trochę bardziej nietypowym miejscu. Mam na myśli Thorpe Park czyli wesołe miasteczko zlokalizowane pod Londynem (ok. 40 minut pociągiem + 10 minut autobusem). Bilet kosztuje dla dorosłych 40 funtów, ale cenę można zbić o 35% przy zakupie online lub nawet 50% przy zakupie grupowym (7 biletów).

Miasteczko oferuje bardzo dużo dla miłośników przeciążeń, chyba nawet więcej niż konkurencyjny park Alton Towers. Wspomnę tylko o Stealth, w którym osiągamy prędkość ok. 130 km/h w ciągu 1.8 sekundy, maksymalne przeciążenie to prawie 5G (wciska w fotel), a najwyższy punkt kolejki znajduje się 60m nad ziemią. Robi niesamowite wrażenie, do tego stopnia, że bez zastanowienia zdecydowałem się na drugą przejażdżkę.

Z rzeczy praktycznych to w parku jest tłoczno nawet poza sezonem. Mówię tutaj o weekendach, w ciągu tygodnia może być lepiej. W związku z tym należy przygotować się na długie czekanie, nawet do 2 godzin aby dostać się na kilkunasto sekundową przejażdżkę! Kolejki można ominąć na dwa sposoby. Pierwszy to tzw. single riders. Polega to na tym, że najpierw do wagoników ładowane są osoby z normalnej kolejki i jeśli zostają wolne miejsca (bo ktoś nie chce jechać sam tylko z przyjaciółmi) to wsiada osoba z kolejki dla single riders. Kolejka ta przeważnie jest dużo krótsza niż normalna, ale po pierwsze nie jest dostępna wszędzie, a po drugie dużo zależy od szczęścia. Równie dobrze może być tak, że czas oczekiwania będzie taki jak w normalnej kolejce.

Drugi sposób jest dużo skuteczniejszy, ale nie ma nic za darmo i to dosłownie. Można kupić bilety fast tracks, które pozwalają wejść na atrakcje bez czekania w kolejce. Pojedynczy bilet (jeden przejazd na jednej atrakcji) to koszt od 2 do 5 funtów. Czy warto? Niech każdy odpowie sobie samemu, czy woli czekać czy nie.

Wizytę w Thorper Park szczerze polecam wszystkim, którzy lubią takie atrakcje, szczególnie, że jest zlokalizowany blisko Londynu. Ja bawiłem się tam naprawdę dobrze. Linki do poprzednich postów z serii na temat życia w Londynie:

04/09/2011

IntelliTrace - schemat XSD

Home

Swego czasu w postach Własne zdarzenia IntelliTrace! oraz Własne zdarzenia IntelliTrace 2 opisałem jak zmodyfikować plik CollectionPlan.xml zawierający plan działania IntelliTrace (historycznego debuggera) tak, aby zdefiniować swoje własne zdarzenie IntelliTrace (ważny punkt w historii działania programu kiedy IntelliTrace nagrywa stan aplikacji). Ostatnio wróciłem do tego zagadnienia i "bawię się" testując różne możliwości IntelliTrace. Niestety czasami, po zmodyfikowaniu pliku CollectionPlan.xml, przy próbie uruchomienia debuggera otrzymywałem błąd np.:

error VSLG4001: The specified collection plan is invalid: 'C:\CollectionPlan.xml'. More information: The 'type' attribute is invalid - The value 'Object' is invalid according to its datatype 'urn:schemas-microsoft -com:visualstudio:tracelog:ClrType' - The Enumeration constraint failed.

Komunikat jest czytelny, wartość Object dla atrybutu type jest niedozwolona. Metodą prób i błędów można wywnioskować, jakie wartości są poprawne, ale to męczące i niewydajne. Pomyślałem więc, że skoro zawartość pliku CollectionPlan.xml to dokument XML, to musi on być walidowany przy pomocy odpowiedniego schematu XSD. Ale gdzie go szukać? Przejrzałem zawartość katalogu instalacyjnego Visual Studio 2010 i niczego nie znalazłem.

Stwierdziłem więc, że zajrzę do biblioteki Microsoft.VisualStudio.IntelliTrace (pisałem o niej w poście Poznaj swój program), która umożliwia programową analizę logów IntelliTrace, ale nie tylko. Biblioteka ta wykorzystywana jest również przez program IntelliTrace.exe (o tym też pisałem w poście Używanie IntelliTrace poza Visual Studio 2010!), który znajdziemy w katalogu instalacyjnym Visual Studio 2010. Program ten służy do uruchomienia historycznego debuggera i kiedy używamy IntelliTrace z poziomu Visual Studio, to korzystamy właśnie z tego programu. Skoro tak to doszedłem do wniosku, że walidacja konfiguracji i schemat XSD znajdują się właśnie w tej bibliotece.

Okazało się to strzałem w dziesiątkę. Bibliotekę załadowałem do .NET Reflector'a. Najpierw zlokalizowałem w zasobach komunikat z błędem. Następnie sprawdziłem gdzie jest używany i znalazłem tylko jedno takie miejsce, a stamtąd już szybko doszedłem do wywołania metody public static XmlSchema GenerateXmlSchema(). Niestety okazało się, że nie mogę jej wywołać z własnego kodu, ponieważ znajduje się w klasie internal class ConfigMessagePacker. Skopiowałem więc jej kod (ok. 1200 linii) do swojego programu i po chwili miałem już XSD.

31/08/2011

Krótko o instalowaniu ServicedComponent

Home

W dwóch poprzednich artykułach na temat zarządzanych komponentów COM+ pisałem, że instaluje się je przy użyciu narzędzia regsvcs.exe. Tak oczywiście jest, ale ostatnio ku swojemu zaskoczeniu zauważyłem, że jest to opcjonalne. Jeśli nie zainstalujemy takiego komponentu z poziomu konsoli (np.: regsvcs.exe MyComponent.dll) to zostanie on zainstalowany automatycznie przy pierwszym wywołaniu jego konstruktora.
[assembly: ApplicationName("MyComponent")]
[assembly: ApplicationActivation(ActivationOption.Server)]
[assembly: System.Reflection.AssemblyKeyFile("MyComponent.snk")]
[assembly: ApplicationAccessControl(false)]
public class MyComponent: ServicedComponent
{
  ...
}

...

//Jeśli komponent nie został wcześniej zainstalowany to zostanie zainstalowany w tym momencie
using (MyComponent cmp = new MyComponent())
{
  ...
}


25/08/2011

Jeszcze o ServicedComponent

Home

W tym poście wrócę do tematu aplikacji modelu COM+ napisanych w kodzie zarządzanym, który to poruszyłem w poprzednim artykule. Tym razem chciałbym zwrócić uwagę na problem wersjonowanie takich komponentów. Upraszczając, chodzi o różnicę pomiędzy katalogiem, z jakiego komponent został zainstalowany w systemie, a katalogiem, w którym znajduje się biblioteka z komponentem jakiej używa dana aplikacja. W szczególności mogą to być inne katalogi np.: c:\Install oraz c:\bin.

W takim przypadku łatwo może dość do sytuacji, w której binaria w obu lokalizacjach będą się różnić. Objawy będą różne w zależności od trybu aktywacji (pisałem o nich poprzednio).W przypadku Aplikacji biblioteki tak długo jak w obu katalogach będą znajdować się biblioteki skompilowane dla tego samego środowiska (32 lub 64 bitowego) nie będzie żadnego problemu (poza bałaganem). Co ciekawe znaczenie ma tylko liczba bitów, wersje bibliotek mogą być inne, różna może być nawet liczba udostępnianych przez komponent metod. Natomiast w przypadku kiedy w jednym katalogu będzie wersja 32 bitowa, a w drugim 64 bitowa przy próbie skorzystania z komponentu dostaniemy wyjątek ComException o treści Klasa niezarejestrowana....

W trybie Aplikacji serwerowej liczba bitów nie ma znaczenia. Znaczenie ma jednak zawartość bibliotek w obu lokalizacjach. Jeśli będzie różna debugowanie nie będzie możliwe. Jeśli zmieni się interfejs, na przykład do biblioteki zostanie dodana nowa metoda, ale nowa wersja nie zostanie zainstalowana, to przy próbie jej użycia pojawi się wyjątek.

Generalnie problem dotyczy też natywnych komponentów COM+ (piekło COM+) ale z takimi komponentami nie pracowałem dlatego nie znam szczegółów.