Development z Zapomnianej Strony

..:: Paweł Hofman .NET Portal ::..

Nie wiem czemu, ale wydawało mi się, że czasy, gdy firmy telekomunikacyjne traktują klienta jak szmatę odeszły w niepamięć. Oj, jak bardzo się pomyliłem i jak dobitnie wykazała się firma Netia S.A., aby mi to uświadomić.

Cała historia zaczęła się w połowie sierpnia, gdy zmieniłem biuro i zamówiłem na infolinii pakiet “Internet + telefon” w swojej nowej siedzibie. Wszystko pięknie, szybko, kurier przywiózł umowę do podpisania, za 2 tygodnie przyszedł monter i “coś” zrobił, a tydzień później przyjechał ruter i nagle zdziwko.

“Brak sygnału DSL”. Hmmm…

Miało działać, a coś jest nie tak i nie działa, ale to wiem i rozumiem tylko ja. Szybki telefon na infolinię – “wszystko aktywowane i w systemie widać, że śmiga”. To zróbmy kilka prostych testów. Dzwonię z telefonu stacjonarnego do siebie. Brawo, udało się, ale numer jakiś nie ten, co w umowie. Hmmm…. dziwne. To zadzwońmy na ten mój z umowy. O! ktoś odebrał i okazało się, że mieszka 3 ulice dalej, i twierdzi, że nagle telefon, z którego zrezygnował kilka miesięcy wcześniej “reaktywował się”!

Dzwonię ponownie na infolinię, i informuję ich, że aktywowali MÓJ Internet i MÓJ telefon u kogoś “przypadkowego”. “Już rejestruję zgłoszenie awarii. Sprawa zostanie natychmiast załatwiona”. Gdy w ciągu kolejnych 3-ch tygodni dzwoniłem tam jeszcze 4 razy i słyszałem dokładnie to samo, czasem przeplatane tekstem, że “zaraz się z Panem skontaktuje ekipa naprawcza”, to zacząłem nabierać podejrzeń, że ktoś mnie zbywa tanimi tekstami.

Czekam, nic innego nie pozostało. Czekałem 46 dni. W tym czasie, nikt z Netii S.A. się ze mną nie skontaktował, nikt nie napisał maila, a sprawa nadal została nierozwiązana. W ciągu tych dni Netia nie zrobiła dosłownie nic. Cóż… może dlatego, że była zajęta przejmowaniem kolejnej firmy, ale tego nie jestem pewien. Może wszyscy byli na urlopie. Może takie zachowanie to ich najnowsza dewiza. W ten też sposób z klienta, który sam przyszedł do nich, stałem się najbardziej rozgoryczonym złośliwcem.

Po wspomnianych 46-u dniach, zgłosiłem reklamację, że nie chcę płacić rachunków za kogoś, jeśli przypadkiem miałbym dostać jakąś fakturę, i w tym samym piśmie wypowiedziałem umowę. No proszę was, ile może czekać klient biznesowy!

Teraz uwaga, bo to co się stało później, przerosło moje najśmielsze oczekiwania. Firma Netia S.A. ze swoim flagowym oddziałem obsługi klienta, postanowiła kontynuować swoją w pełni nie-profesjonalną postawę, odpowiadając na moją reklamację – NEGATYWNIE! Ale uwaga, zrozumieli, że Internetu i telefonu nie mam, zatem anulują rozmowy prowadzone przez osoby trzecie. Jednakże wg nich umowę wypowiedziałem za wcześnie i obciążą mnie kosztami aktywacji. Pytanie tylko jakiej – bo ja w umowie mam konkretną lokalizację, a tam jak nic nie było, tak dalej nic nie ma! A za wcześnie, bo niby powinienem odczekać 70dni! Na dobicie, konsultant rozpatrujący reklamację stwierdził, że nie mam prawa odwołania ani odpowiedzi i jego decyzja jest ostateczna.

Jak we dwa dni później pozbierałem szczękę z ziemi, to tylko zostało mi stwierdzić kilka faktów i odesłać je ponownie na piśmie na skrytkę pocztową Netii w Katowicach. (Tak są pewne biura lokalne, które sprzedają te usługi, ale to już jest Internetia i nie bardzo chcą obsługiwać klientów, którzy podpisali umowy przez infolinie. Także przestroga – wszystkie reklamacje wysyłajcie zawsze na piśmie!).

A to, co stwierdziłem to:

  • w umowie mam konkretny lokal, gdzie aktywacja powinna mieć miejsce
  • umowa definiuje 40 dni od daty podpisania, jako ostateczny termin wykonania przez Netię S.A. aktywacji
  • brak możliwości odpowiedzi na odpowiedź łamie postanowienia regulaminu, na który wielokrotnie powoływał się konsultant
  • to umowa jest obowiązująca, a regulamin; regulamin reguluje to, co nie jest powiedziane w umowie
  • to po prostu najzwyklejsza próba wyłudzenia pieniędzy za niewykonaną usługę
  • podoba mi się to myślenie, że “jesteśmy dużą firmą – PŁAĆ, bo w sądzie z nami nie wygrasz”

Na koniec – cóż, minęło 65dni. Internetu dalej nie mam, do wyboru mam jeszcze TP S.A., bo nikt inny nie obsługuje centrum miasta. Dobrze, że to Wrocław, duże miasto, dobrze, że 21. wiek i premier Pawlak mówi o informatyzacji kraju. Ha! Oby tak dalej!



Jeśli zajmujesz się na poważnie pisaniem aplikacji na Windows Phone i często korzystasz z emulatora, to jest jedna opcja, która może ci pomóc w debugowaniu. Otóż emulator wyświetla logi na konsoli! Tak, korzysta ze standardowej konsoli w Windows. Domyślnie jest ona niestety ukryta. Brakuje menu, aby ją pokazać, zatem pozostaje tylko ustawienie magicznej wartości w rejestrze:

  • na maszynie 32-bitowej:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\XDE]
"EnableConsole"=dword:00000001

  • na maszynie 64-bitowej:

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\XDE]
"EnableConsole"=dword:00000001

Miłego podglądania!



maj
30

Obfuscator dla .NET

by Paweł | Tags:

Jakby tu zabezpieczyć swoje programy .NET-owe?

Szukałem, szukałem i znalazłem – darmowy obfuscator Eazfuscator.NET. Mnogość funkcji oraz wsparcie dla wszystkich współczesnych wersji platformy Microsoft .NET stawia go moim zdaniem na równi z płatnymi wersjami wielu innych firm znanych na rynku. Jedyne, czego życzyłbym sobie jeszcze w tym zestawie, to wsparcie dla Mono (chociaż samej manipulacji metadanymi), ale i tak duże wrażenie robi zaangażowanie autora w ten projekt przez tyle lat!

Życzę dalszej i równie dużej motywacji.



Dziś ukazała się długo oczekiwana nowa wersja moich bibliotek CodeTitans Libs v1.5. Zawiera ona szereg poprawek oraz nowych funkcjonalności.

Niewtajemniczonym, podpowiem, że służą one do: obsługi odczytu i zapisu w formacie JSON, wymiany danych z użyciem protokołu Bayeux oraz zawierają inne funkcjonalności potrzebne przy przenoszeniu programów z iPhone’a do Windows Phone 7.

Zapraszam do pobierania tutaj.



Kolejną ciekawostką, którą chciałbym omówić są zdalne repozytoria i dostęp do nich. O ile są to repozytoria tego samego typu (czyli np. Subversion połączone z Subversion – jako externals, czy Git pracujący z Gitem – jako submodules), to nie ma to większego znaczenia i obsługa jest bezproblemowa.

Ciekawsze są oczywiście krzyżówki. Jeśli przyjrzymy się bliżej pracy w Git, który musi korzystać z zewnętrznego repozytorium Subversion, to już wcale nie musi wyglądać prosto. Weźmy choćby mój projekt CodeTitans Libraries (wspomagający użycie protokołu Bayeux, standardu wymiany danych tekstowych JSON, InversionOfControl oraz udostępniający niektórych funkcjonalności znanych programistom iOS SDK w .NET-cie). Codeplex.com udostępnia go jako Subversion.

Przyjmijmy, że repozytorium Git, ma bardzo prostą strukturę złożoną z branchy master oraz develop. Pierwszy służy to przechowywania referencji stabilnych wersji kodu oraz ich etykietowania. Drugiego używamy do rozwijania i pracy nad aktualnym kodem.

Cel: gdzieś w katalogu Externals/CodeTitans chcielibyśmy mieć kod z też projektu.

W tym celu przede wszystkich będziemy potrzebowali dodatkowego brancha. Nazwijmy go codetitans_develop. Wybiegając do przodu - Git tak naprawdę skopiuje pełny kod źródłowy zewnętrznego projektu i sam będzie go wersjonował. Niestety minus jest taki, iż będzie on ten kod próbował umieścić w głównym folderze swojego własnego repozytorium, generując niezły chaos, przy złączeniu obu projektów (tego pierwotnie trzymanego w Gicie oraz nowego). Praca na dodatkowym branchu pozwoli nam zatem na wprowadzanie lokalnych zmian, np.:

  • przeniesienia plików do wspomnianego folderu Externals/CodeTitans
  • dokonywania innych drobnych modyfikacji (np. gdy chcemy bezpośrednio dodać pliki do solution, bez referencjonowania projektów biblioteki CodeTitans Libraries, to może widoczność zmienić z ‘public’ na ‘internal’)

A zatem, po kolei:

  1. Dodanie nowego brancha:

    git checkout –b codetitans_develop
  2. Dodanie referencji do zewnętrznego repozytorium SVN:

    git svn init https://codetitans.svn.codeplex.com/svn -R codetitans --prefix Externals/CodeTitans/ --ignore-paths="^[^/]+/(?:branches|tags|bin)"

    - lokalizacja – codeplex.com
    - nazwa lokalna – codetitans
    - ponieważ repozytorium to ma standardową strukturę, a nas interesuje jedynie ‘trunk’ – ignorujemy pozostałe foldery
  3. Pobieramy historię zmian z repozytorium SVN:

    git svn fetch codetitans

    (za pierwszym razem pobrane zostanie pełna historia, co może trochę trwać; dla oszczędzenia czasu plecam dodanie opcji “-r <rev>” z numerem ostatniej rewizji, która jest dla nas istotna; później już oczywiście tylko ostatnie zmiany będą synchronizowane)
  4. Poprzednie polecenie, de facto, pobiera pliki, ale nie są one jeszcze nigdzie widoczne. Aby stały się widoczne, musimy połączyć je (operacją merge) z aktualnym branchem (tym utworzonym i ustawionym jako aktualny w kroku 1.).
    Pytanie pozostaje, co mamy teraz łączyć.

    Lista wszystkich branchy (git branch –a) ujawnia, że zostało dodane wskazanie zewnętrzne na kod SVN. Wygląda ono mniej więcej tak:

    remotes/Externals/CodeTitans/git-svn

    I łączymy kod:

    git merge –squash remotes/Externals/CodeTitans/git-svn

    Uwaga! W przyszłości to właśnie tutaj, podczas operacji merge będzie występowało najwięcej konfliktów. Tutaj też ładnie je rozwiążemy, a osobny branch gwarantuje nam, że nie mieszamy kodu (i zmian w nim) projektu zewnętrznego z naszym produkcyjnym.
  5. Wprowadzamy wszystkie niezbędne poprawki (przenosimy, zmieniamy treść plików…). Oczywiście operacje te kończymy pojedynczym:

    git commit –a –m “<komunikat>
  6. Wracamy z powrotem na nasz główny branch:

    git checkout develop
  7. I dodajemy do niego wypielęgnowany kod zewnętrznego projektu, który idealnie pasuje do naszej struktury:

    git merge --no-ff codetitans_develop

    - --no-ff – bardzo ważna opcja dla późniejszej graficznej wizualizacji repozytorium i zmian na nim; otóż wszystkie zmiany z brancha codetitans_develop nie zostaną wessane do brancha aktywnego w tym momencie brancha develop

    Tutaj już nie powinny wystąpić żadne konflikty, bo kod jest jednak rozdzielny, a wszystkie zmiany odnośnie zewnętrznej biblioteki prowadzone były na branchu “codetitans_develop”.
  8. Aktualizacja:

    Kiedy nasz projekt Subversion ulegnie zmianie, musimy je mozolnie dodać na repozytorium Git. Niestety, aby wszystko pięknie działało, należy wykonać wszystkie kroki od 3-ego włącznie.

Salute!



Tyle co ukazał się upragniony przez wielu Visual Studio 2010 ServicePack 1, a już okazuję się, iż kolejność instalowania dodatków do Visual Studio ma swoje zależności.

To o czym chciałem przede wszystkim powiedzieć, to wymóg instalacji Visual Studio SDK przed zainstalowaniem SP1. Inaczej nie będzie to możliwe i instalacja się nie powiedzie z dziwnie (jak zwykle?) nic nie mówiącym komunikatem o błędzie.

Error Type: Microsoft.VisualStudio.Sdk.Setup.MissingPrerequisiteException
Error Message: You must have Microsoft Visual Studio 2010 installed on your computer before procedding.

 

Visual Studio 2010 SDK Error

Jak zatem wybrnąć z tej sytuacji (bo instalacja na maszynie wirtualnej zajęła jednak sporo czasu! i cofanie jej + ponawianie to trochę zbyt wiele)? Otóż sztuczka polega na tym, aby używając monitora rejestru zobaczyć, do czego próbuje odwołać się instalator SDK. W moim przypadku było to lokalizacja numer wersji Visual Studio Service Pack:

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\DevDiv\VS\Servicing\10.0]
“SP” = 1

A zmieniając wartość z ‘1’ na ‘0’, oszukamy na chwilkę instalator SDK. Na koniec przywracamy ‘1’ i po sprawie.

Więcej o tym, jak znaleźć rozwiązanie samemu następnym razem - tutaj.



Czasem zdarza się sytuacja, w której ktoś, kto ma dostęp tylko do odczytu do naszego repozytorium SVN, chciałby w nim coś jednak zapisać. Udało mu się (lub jej) rozwiązać jakąś usterkę czy problem, albo usprawnić działanie. Moglibyśmy w tym miejscu dodać uprawnienia do zapisu i byłoby po sprawie.

Jednak czy na pewno? Zawsze jakieś “ale”! Z czegoś wynikał przecież fakt, że ów użytkownik nie posiadał pełni praw.

  • Czy wspomniana zmiana ma w ogóle sens i czy w ogóle istnieje? (może ktoś tylko chce wyłudzić dostęp)
  • Czy zmiany są w pełni przetestowane?
  • Czy nie wprowadzają luk w zabezpieczeniach i innych ukrytych furtek?
  • Czy zgadzają się one z konwencją nazewniczą i stosują projektowe formatowanie kodu?
  • Czy będziemy pamiętać, o cofnięciu uprawnień, gdy zmiany zostaną już wysłane do repozytorium?

Wyjściem z tej sytuacji może okazać się utworzenie "łatki" (patcha), która zawierała będzie tylko proponowane zmiany w konkretnych plikach i lokalizacjach. Później przekazanie jej zaufanej osobie w projekcie, która zmiany te może przejrzeć, ocenić i ma prawa do zapisu na serwerze. Oto jak się za to zabrać:

  1. Zapamiętanie zmian:

    svn diff > fix.diff

    (Rozszerzenie diff jest rozpoznawane przez wiele edytorów, podświetlając składnię podczas przeglądania, niemniej jednak każde inne byłoby równie dobre)

  2. Aplikacja zmian:

    patch -p0 -i fix.diff

    Teraz można sprawdzić, co i gdzie się zmieniło i po przeglądzie (oraz koniecznie testach) wysłać do repozytorium na serwerze.
  3. Wysłanie na serwer:

    svn commit –m “<message> 


Od jakiegoś czasu staram się rozwijać własną bibliotekę implementującą kliencką część protokołu Bayeux (używającego poniżej formatu JSON). Jest tam jeszcze oczywiście dużo innych rzeczy, ale te są na razie najważniejsze.

Zabawa idzie mi całkiem dobrze i z wyników jestem bardziej niż zadowolony. Jednak z racji tego, że za cel powziąłem sobie współpracę z każdą dostępna platformą .NET, natrafiłem coś zupełnie nieoczekiwanego. O ile przemilczę fakt, że każdy z .NET frameworków (tj. ten z komputera stacjonarnego desktop, Compact Framework, Mono oraz Silverlight dla Windows Phone 7), udostępnia inne API, które nie zawsze są ze sobą zgodne (bo te albo pokazują inne właściwości, albo wręcz brakuje synchronicznych wywołań). To o tyle nie sposób przejść obojętnie obok pewnego problemu, który zmarnował mi trochę czasu ostatnio. Ten sam kod do wymiany danych z użyciem HttpWebRequest, który działa poprawnie na Microsoft .NET Framework nie zadziała na Mono .NET na Linuxie.

Otóż w scenariuszu, w którym łączymy się przy użyciu HTTPS ze znanym z góry serwerem, wszystko pięknie działa na stacjonarnym Windows 7 oraz na Windows Phone 7. Jednak przy testach na Mono 2.8, przy próbie pisania do strumienia sieciowego otrzymujemy wyjątek ze statusem “SendFailure”. Prócz enigmatycznego komunikatu, nie mamy żadnego konkretnego punktu zaczepienia.

The authentication or decryption has failed.

Albo też nagle i niespodziewanie okazuje się, że coś, ale już nie nasz kod, zużywa 100% mocy procesora, 1GB RAMu oraz z wirtualnej maszyny Mono nie ma co zbierać.

Odpowiedzialnym za ten stan rzeczy jest sposób obsługi certyfikatów SSL. Microsoft .NET Framework akceptuje je wszystkie bez wyjątków i pozwala na komunikację. Mono natomiast jest bardziej restrykcyjne i wymaga, aby przed rozpoczęciem wysyłania, zaakceptować certyfikat serwera ręcznie. Jest to tym ciekawsze, że musi być zrobione nawet w sytuacji, gdy mamy zaufany certyfikat, podpisany przez zaufanego dostawcę.

Wystarczy zatem umieścić w swoim kodzie poniższy fragment, aby wszystko zaczęło działać zgodnie z oczekiwaniami:

ServicePointManager.ServerCertificateValidationCallback += CertificateValidationCallback;

public bool CertificateValidationCallback (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
    // tutaj należy wstawić logikę sprawdzania certyfikatu!
    return true;
}



Testowanie - niestety temat zapomniany i zupełnie zignorowany przez twórców Windows Phone 7. Jakoś w głowie mi się nie mieści, że premiera telefonu odbyła się trzy miesiące temu, po raz pierwszy telefon pokazano światu w marcu 2010 i do dzisiejszego dnia nie doczekał się od oficjalnego frameworka testowego zintegrowanego z Visual Studio. Aż jestem ciekaw, jakim cudem tak dobrze go przetestowali i czy w ogóle zamierzają coś w tę stronę ruszyć. Bo widzę, nawet po kursie na virtualstudy.pl, że dużo ludzi interesuje się dużo bardziej cyklem życia aplikacji, niż prowadzeniem dobrego projektu na tej platformie (nie obrażając nikogo oczywiście).

Na samym początku wyjaśnię zatem, że oczywiście chodzi nam o pisanie testów, do których już przywykliśmy – czy to używając MS Unit Testing Framework, czy NUnit, używając atrybuty, które znamy i które nie sprawiają nam kłopotu oraz całego tego podejścia.

Tak, czy inaczej, błądząc po Internecie i marnując kolejne godziny możemy znaleźć garść przydatnych materiałów, które pozwolą uzbroić nas w środowisko do zabawy. Podejrzewam, że większość nie ma za dużo czasu, zatem przejdźmy od razu do meritum. Polecam zatem przestudiowanie przynajmniej:

  • Wystąpienia Jeffa Wilcoxa na MIX2010 o testowaniu Silverlight3 i Silverlight4. Co ciekawe, jest on członkiem zespołu Silverlight (tworzącego między innymi Silverlight Toolkit) i pokazuje on tam między innymi swój autorski projekt. Doprawdy, podziwiam takich ludzi. Ale ciągle daje mi do myślenia, dlaczego Microsoft nie wspiera tego aktywniej (albo samemu?).
  • Najnowszą wersję bibliotek, które trzeba dołączyć do projektu automatycznego testowania (o czym za chwilkę) znajdziemy na jego blogu. Dla potomności skopiowałem to również tutaj. Niestety jest to wersja z maja 2010, a mamy ostatni dzień grudnia i choć dzisiaj działa, to ciekawe jak będzie w niedalekiej przyszłości. Kontaktowałem się z Jeffem i obiecał rzucić okiem (popatrzeć na problemy, które mu zgłosiłem) i wypuścić nową wersję niedługo. Wszyscy jednak wiemy, jak to jest z wolnym czasem… no jest wolny ;)

Na koniec zostawiłem sobie zbudowanie aplikacji testowej. Oryginalny post, na którym bazuję znaleźć można tutaj. Jednak jak dla mnie jest on nieco przekombinowany. W skrócie mówi on o tym, że:

  1. Trzeba już mieć zainstalowane narzędzia do pracy z Windows Phone 7.
  2. Utworzyć najzwyklejszy projekt Silverlight3 dla Windows Phone 7.
  3. Dodać referencje do bibliotek Jeffa.
  4. Usunąć wszystkie strony aplikacji, gdyż to framework będzie je tworzył sam (za chwilkę).
  5. Zmodyfikować konstruktor aplikacji App() tak, aby oprócz monitorowania wyjątków, ustawiał odpowiednio widok (wszystko inne należy skasować z konstruktora):
    this.RootVisual = UnitTestSystem.CreateTestPage();
  6. I najważniejsze – CreateTestPage(), posiada też wersję, która przyjmuje dodatkowe opcje konfiguracji (UnitTestSettings). Wśród nich jest między innymi lista assembly, które mają być przeszukiwane w celu lokalizacji testów. Dodajemy do niej oczywiście wszystkie, które nas interesują. Po co? No ja osobiście wolę oddzielić same testy, od aplikacji, która je odpala. Mimo wszystko testy można użyć jeszcze gdzieś indziej, a tej aplikacji to już nie zawsze.

Wesołego TDD!



Jest piękny grudniowy wieczór, kiedy to w świątecznej promocji nabyliśmy Crysis Maximum Edition ze Steam’a. Pobraliśmy go i zainstalowaliśmy na swoim komputerze, a naszym oczom już już ma ukazać się gra. Czekamy, czerwona dioda dysku miga ochoczo do nas… Aż tu nachodzi nas ów nieoczekiwany gość – crash (nie mylić z tytułem gry!), który psuje cały wieczór.

Logi twierdzą wyraźnie, kto jest winny:

Nazwa zdarzenia problemu:    BEX
  Nazwa aplikacji:    crysis.exe
  Wersja aplikacji:    1.1.1.6156
  Sygnatura czasowa aplikacji:    47d6d167
  Nazwa modułu z błędem:    MSVCR80.dll
  Wersja modułu z błędem:    8.0.50727.4927

Niemniej jednak logi kłamią. Jak go naprawić?

Usuwamy katalog: <Moje dokumenty>/My Games/Crysis (i prawdopodobnie tyczy się to także dodatku Warhead).

Otóż, grałem wcześniej w pudełkową wersję, głównie dla DirectX 10 i 64-bit, natomiast Steam pobrał i uruchomił wersję DirectX 10 ale niestety 32-bitową. A z mieszaniem takich ustawień nikt już sobie poradzić nie umiał, jak widać.