Development z Zapomnianej Strony

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

Najlepiej jest być na bakier z wszelkimi zasadami zdroworozsądkowymi. Dlatego też postaram się w skrócie opisać, w jaki sposób zwykłemu szarakowi (czytaj: użytkownikowi bez jakichkolwiek uprawnień w domenie) pozwolić logować się na głównym kontrolerze domeny z zainstalowanym Windows Server 2008. Większość administratorów uderzyła już w tym momencie głową w biurko, zastanawiając się nad celowością takiego postępowania… toteż nikt nie będzie przeszkadzał.

Do dzieła, a zatem:

  1. Na kontrolerze domeny w narzędziu Server Manger znajdujemy gałąź Default Domain Policy (najszybciej po ścieżce: Features\Group Policy Manager\Fores: <domena>\Domains\<domena>\Default Domain Policy)
  2. Otwieramy Group Policy Management Editor poprzez wybranie Edit z menu kontekstowego.
  3. Dalej, nawigujemy do tej części, która pozwala nadawać i odbierać uprawnienia użytkownikom: Computer Configuration\Windows Settings\Security Settings\Local Policies\User Rights Assignment.
  4. Na koniec zezwalamy użytkownikowi na logowanie w trybie Terminal Services (KB278433), poprzez dodanie tam całej grupy Remote Desktop Users.
  5. Aby jeszcze wszystko szybko weszło w życie, wymuszamy odświeżenie polis w domenie: gpupdate /force.
  6. I to wszystko. Użytkownik nie musi mieć nawet uprawnień logowania lokalnego.

Dodatkowo uwaga:
- firewall musi mieć dziurę na przychodzące połączenia od usługi “Remote Desktop
- sama usługa natomiast musi być włączona :)
- użytkownik, któremu pozwalamy na logowanie musi należeć do grupy “Remote Dektop Users”, ale to już chyba zbyt oczywiste.



Visual Studio 2008 jako narzędzie developerskie dla programistów Windows (czytaj .NET i nie tylko) plasuje się na pierwszej pozycji. Jednak pod względem rozszerzania i dostosowywania plasuje się daleko w tyle za swoim największym konkurentem Eclipse. Prawdopodobnie dlatego też Microsoft zrezygnował z opłat licencyjnych, wymaganych przy pisaniu dodatków jeszcze przy pierwszej wersji Visual Studio 2008 SDK.

Dlatego też chciałem dzisiaj pokazać kilka przykładów, jak Visual Studio możemy dostosowywać do swoich potrzeb (z użyciem lub bez SDK):

  1. Korzystając z dostępnych w sieci narzędzi, zmieniamy aktualny motyw (theme) tak, aby nie raził i nie męczył wzroku. Milutki generator znajdziemy tutaj

    Visual Studio Generated Template

     

  2. Grzebiąc w rejestrach systemu możemy włączyć wskaźnik po prawej stronie tekstu tak, aby linie tekstu nie były zbyt długie. Wyróżniona 21-a kolumna zapewni nas, że pisząc tak krótkie linie, otworzymy pliki z kodem źródłowym nawet na najstarszej DOS-owej maszynie.

    Uaktualniamy rejestr systemowy dodając następujący wpis typu tekstowego (string):

    [HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\Text Editor]
    Guides = RGB(128,0,0) 20


    (dowolnie dobieramy kolor oraz po przecinku za liczbą 20 wpisujemy dodatkowe wartości, jeśli jeden przewodnik to za mało)
    Visual Studio - przewodnik
  3. Piszemy własny wizualizator danych.

    Wizualizatory to to, co tygrysy lubią bardzo. Bardziej lubią chyba tylko pakiety (VS Packages), ale o tym za chwilę. Idea wizualizatorów polega na tym, iż pisząc własne programy często tworzymy własne struktury danych, które łatwiej przestawiałyby się graficznie. Podczas debugowania Visual Studio udostępnia nam zatem kopię wskazanego obiektu, który możemy własnoręcznie przetworzyć i pokazać na ekranie. Poniżej znajduje się przykład wizualizatora obiektów System.__ComObject z wyszczególnieniem interfejsów i metod implementowanych przez tego CRW (Callable Runtime Wrapper).

    Visual Studio - wizualizator
    Oznaczone odpowiednimi atrybutami assembly wgrywamy do katalogu:

    %MyDocuments%\Visual Studio 2008\Visualizers

  4. Kolejnym ciekawym rozszerzeniem jest możliwość dodawania własnych słów kluczowych, które zostaną rozpoznane w edytorze tekstu dla VisualC++. Dotyczy się to przede wszystkim plików z rozszerzeniami .h, .c, .cpp, jednak bardzo dobrze sprawdza się również po przypisaniu edytora Microsoft Visual C++ do rozszerzeń takich jak .asm, .cu, czy tym podobnych (Tools->Options->Text Editor->File Extensions).

    W poniższym pliku umieszczamy nowe słowa kluczowe w kolejnych linijkach, a po ponownym uruchomieniu Visual Studio od razu zauważymy efekty:

    c:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\usertype.dat

  5. Na sam koniec deser. Gdy wymienione powyżej przykłady nie spełniają naszych wymagań, to zwracamy się w stronę pisania własnych rozszerzeń z w pełni funkcjonalną logiką. Co chcielibyśmy tym uzyskać, ot np.: aby z poziomu Visual Studio uaktualniały się wpisy w narzędziach do zarządzania błędami (ticket'y w wybranym trackerze) lub po prostu potrzebujemy dokujące okienko narzędziowe, które ściąga nowinki ze świata, przekonując pracodawcę, że jednak dzielnie kodujemy. Piszemy wtedy własny dodatek add-in lub VS Package wykorzystując w pełni możliwości oferowane przez SDK.

    Należą do nich m. in.:
    - własne edytory (lub zmiana istniejących)
    - okna narzędziowe (tool windows)
    - pliki pomocy
    - nowe języki programowania (wraz ze schematami budowania nowych projektów)
    - nowe rodzaje projektów (bądź dodawanie funkcji do istniejących, tj.: .csproj)
    - szablony i kreatorzy (templates & wizards)
    - dostawców usług (dostawcy listy błędów, zadań)


    Więcej informacji o pisaniu dodatków do Visual Studio zamieściłem w Samouczku.
    Jako działający przykład posłużyć może autorski projekt TytanNET.

 

Wytrwałych odsyłam do bloga Sary Ford, która do niedawna jeszcze żywo publikowała nowinki w stylu Tips&Tricks o Visual Studio oraz była autorką kilku książek o podobnie brzmiącym tytule.

Jako książkę z tej tematyki polecam (czym prawdopodobnie zadziwię niektórych) Inside Visual Studio .NET 2003 (tak 2003!), gdyż ona najdokładniej omawia sposób pisania add-inów oraz interakcję z tego poziomu z edytorami, plikami projektu i kodem źródłowym.

 

Wesołego kodowania!



Magiczny system Mac OS X zawsze wie lepiej, co chce zrobić użyszkodnik. Aby jednak wiedział lepiej możemy go poinstruować takimi oto skrótami:

rozruch z płyty CD/DVD C
rozruch z dysku twardego D
pokazanie dostępnych źródeł do bootowania OPT
uruchom z określonego dysku SCSI ID=# CMD-OPT-SHIFT-DELETE-#
uruchom z serwera sieciowego N
   
bezwarunkowy restart CTRL-CMD-POWER
bezwarunkowe zamknięcie systemu CTRL-CMD-OPT-POWER
   
zamknięcie aktywnej aplikacji CMD+Q
przełączanie aplikacji CMD+TAB
przełączanie okienek w ramach aktywnej aplikacji CMD+~


 

Próżno szukać opcji w ustawieniach, aby pokazać wszystkie ukryte pliki i foldery. Niestety takowa nie istnieje. Aby ukazać to, czego zazwyczaj “standardowy” użytkownik nie chce oglądać należy w oknie terminala wpisać:

defaults write com.apple.finder AppleShowAllFiles TRUE
killall Finder

I po sprawie. Oczywiście, dla cofnięcia zmian TRUE wystarczy zamienić na FALSE.



Podczas pracy nad projektem i uruchomieniu statycznej analizy kodu w Visual Studio 2008 (Code Analysis 2008/FxCop) napotkałem bardzo intrygujący błąd:

CA0058 : The referenced assembly 'EnvDTE, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' could not be found. This assembly is required for analysis and was referenced by: 'MojProjekt.dll', 'VSLangProj.dll'.

Należy w tym miejscu oczywiście zaznaczyć, że faktycznie projekt jest zależny od wymienionej VSLangProj.dll oraz EnvDTE.dll. Tyle, że ta ostatnia jest dołączana w wersji 8.0. Cały kłopot w tym, że wymagana wersja 7.0.3300, nie istnieje nigdzie w systemie. Wpływu na VSLangProj nie mamy żadnego, bo pochodzi on z publicznego SDK do Visual Studio, a naszym zadaniem nie jest przecież ‘naprawa’ tej sytuacji, a analiza własnego kodu źródłowego!, zatrzymana grubiańsko przez niezgodność skompilowanych bibliotek kogoś innego. Dodatkowo projekt działa i jakoś potrafi się odnaleźć w run-time’ie. Magia.

Zmiana właściwości referencji tak, aby wyłączyć wymaganie ‘Specific Version’, nie przyniosła żadnego rezultatu. W sumie można powiedzieć, że logiczne, bo przecież EnvDTE 7.0.3300 wymagany jest pośrednio przez VSLangProj.

Rozwiązanie:

  1. Przejść do lokalizacji: %ProgramFiles(x86)%\Microsoft Visual Studio 9.0\Team Tools\Static Analysis\FxCop
  2. Otworzyć w edytorze tekstowym: FxCopCmd.exe.config
  3. Zmienić wartość ustawienia AssemblyReferenceResolveMode na StrongNameIgnoringVersion

Od tej pory komunikat o błędzie zniknie bezpowrotnie.

FxCopCmd.configNa załączonym obrazku przestawiam, jakie są jeszcze inne dostępne opcje, jeśli ktoś kiedyś będzie potrzebował.



Nigdy nie trzymam swoich dokumentów (czytaj folderu, który traktuję jako ‘Moje dokumenty’) w domyślnej lokalizacji proponowanej przez system. Dlaczego? Ano dlatego, że chciałbym aby:

  • nie zniknęły mi te dokumenty przy przeinstalowywaniu Windows’a (niezależnie od przyczyny; a im mniej trzeba pamiętać w takiej chwili, tym lepiej)
  • kilka kont z tego samego/różnych systemów zainstalowanych na komputerze korzystało z tej samej lokalizacji, bo do tego właśnie służy ten folder
  • partycja systemowa nie jest odpowiednim miejscem na wrzucanie tam dużej ilości drobnych plików, które dość często aktualizowane, prowadzą jedynie do niepotrzebnego zwiększenia fragmentacji
  • dużo gier w końcu nauczyło się wrzucać zapisy stanów (save’y) do ‘Moich dokumentów’ i to też jest miłe jak po przeinstalowaniu potrafią się odnaleźć.

Tak czy owak, w Windows XP wystarczyło kliknąć prawym przyciskiem na przycisku ‘Moje dokumenty’ z menu ‘Start’ i we właściwościach wpisać nową lokalizację.

LibraryProperties W Windows 7 mamy niespodziankę. Ponieważ po wykonaniu powyższych kroków zamiast właściwości omawianego folderu, dostajemy właściwości biblioteki. Tutaj możemy sobie dodawać, usuwać lub układać foldery, na bazie których system później będzie twierdził, że są to wszystkie nasze dokumenty. Nam jednak ciągle nie o to chodzi. Bo pomimo wszystkich naszych manipulacji, domyślna lokalizacja tego, gdzie programy widzą ‘Moje dokumenty’ pozostaje niezmieniona.

 

 NewLocationOfDocuments

 

 

To co tak na prawdę należy zrobić, to odnaleźć lokalizację:

C:\Users\<nazwa_konta>\My Documents

i wejść w jej właściwości. ‘<nazwa_konta>’ to aktualnie zalogowany użytkownik, dla którego dokonujemy zmiany.

Tutaj na zakładce ‘Lokalizacja’ wskazujemy nowy folder i sprawa załatwiona. Wszystko zaczyna działać tak, jak chcemy.



Mało kto zdaje sobie tak naprawdę sprawę, że oprócz wersjonowania kodu oraz oficjalnych/inżynierskich releasów wysyłanych do klientów wypada również wersjonować pliki PDB z nimi związane. Dlaczego? Odpowiedź jest bardzo prosta. Wyobraźmy sobie, iż nasza aplikacja się po prostu wysypuje. Zaraz ktoś mi powie – “hola hola, ale przecież mamy logi, w pięknym tekstowym formacie i wszystko w nich widać”. Może ktoś nawet słyszał o plikach MAP :) Super! No ale nie wszystkie nasze moduły muszą być przecież napisane w .NET. Te napisane w językach natywnych (C/C++) nie podadzą nam tak łatwo miejsca wystąpienia błędu (czytaj: pełny stos wywołań, call-stack). Jedyne na co możemy wtedy liczyć, bez wspomnianej informacji debugowej, to nazwa modułu i adres, pod którym spotkany został błąd. Ponadto nie zawsze mamy pod ręką Visual Studio. Jeśli chcielibyśmy przeprowadzić debugowanie na nieco niższym poziomie przy pomocy WinDBG, aby wykryć zakleszczenia (dead-locks) oraz wysokie zużycie pamięci, czy po prostu różne inne wycieki pamięci natywnej (nawet w kodzie .NET) to okazują się one wręcz niezbędne. W dodatku na różnych maszynach, ten sam błąd może wystąpić pod różnym adresem, co związane jest z niedeterministyczną realokacją modułów lub po prostu dysponujemy zrzutem pamięci (memory dump file), który pozwala nam w pełni cieszyć się chwilą awarii naszej aplikacji w trybie “pośmietnym” (określanym jako post-mortem debugging).

A tak niewiele trzeba, aby całe zadanie w pełni zautomatyzować. Potrzebujemy zrobić około trzech rzeczy:

  • założyć lokalne repozytorium plików PDB oraz EXE/DLL dla naszych produktów (dajmy na to w katalogu D:\SymbolStore\Projects)
  • dla jeszcze większej wygody założyć lokalne repozytorium na pliki PDB dla bibliotek systemu operacyjnego, które będziemy pobierać z publicznych serwerów Microsoftu (co pomoże rozszyfrować nazwy funkcji oraz przekazywane parametry do systemowych wywołań WinAPI – kernel32.dll, user32.dll…)
  • zdefiniować zmienną systemową _NT_SYMBOL_PATH, która będzie pokazywała na te repozytoria:

_NT_SYMBOL_PATH=srv*D:\SymbolStore\Microsoft\* http://msdl.microsoft.com/download/symbols;srv* D:\SymbolStore\Projects\

 

Od tej pory z każdą nową wersją naszej aplikacji wykonamy poniższe dwie linijki skryptu (rozszerzone samemu już też o pliki EXE/DLL lub inne cenne dla nas dane):

set MODPATH=D:\SymbolStore\Projects\
set ProjectPath=D:\Projects\MyProject
symstore add /r /f "%ProjectPath%\*.pdb" /s %MODPATH% /t "MyProject" /v "Build v2.0.1" /c "15/12/2009 Daily Build"

Narzędzie symstore służące do zarządzania lokalnym repozytorium plików PDB dostępne jest za darmo po zainstalowaniu pakietu Debugging Tools for Windows (czyli po prostu z WinDBG). Dodatkowo zmienną tę poprawnie rozpoznaje większość Microsoftowych debuggerów i automatycznie pobiera odpowiednie pliki PDB związane z modułami EXE/DLL, które aktualnie analizujemy.

Nie ma róży bez kolców:

  • w ciągu kilku pierwszych uruchomień, większość tych plików PDB dla naszego OSa musi zostać pobrana z Internetu, co może trochę potrwać (300MB się jednak trochę pobiera…)
  • zajmują one też coraz więcej miejsca na dysku ;)
  • no i w końcu sam czas włączania debugera, zwłaszcza Visual Studio, znacząco się wydłuża, bo są one ładowane do pamięci, aby rozwiązywać nazwy funkcji; WinDBG jest tu o tyle inteligentniejszy, że ładuje te pliki na żądanie lub kiedy podejrzewa, że będą potrzebne nie obciążając maszyny aż tak bardzo.

Miłego debugowania.



Resource Governor Resource Governor to nowa opcja dostępna tylko w Microsoft SQL Server 2008 Enterprise. Dzięki niej możliwe jest w końcu zagwarantowanie priorytetów oraz średniego czasu wykonania zapytań, od których zależy nasz biznes. Pozwala on między innymi na zarządzanie i przypisywanie zasobów “typom” użytkowników łączących się z naszą bazą danych. Każdy “typ” reprezentowany jest jako pewna workload groupa, która z kolei posiada referencję do zasobów (resource pool). Zasobami są tutaj: minimalna i maksymalna ilość pamięci RAM oraz czasu procesora. Oba podawane są w procentach.

Procedura wygląda następująco - podczas łączenia, zanim jeszcze kontrola (czy uchwyt) zostanie zwrócony wywołującemu, wykonywana jest funkcja klasyfikująca (User Defined Function, UDF), którą sami możemy utworzyć, czy modyfikować. A następnie wszystkie zapytania (niezależnie od ich rodzaju), które wykonywane są w ramach danego połączenia będą ograniczane. Ograniczenia te zostają zaaplikowane jednak dopiero wówczas, gdy aktywnych jest kilka, różnych połączeń. Nawet restrykcyjne ograniczenia nie są więc brane pod uwagę, jeśli w danych aktualnie warunkach serwer dysponuje większymi zasobami, które może przydzielić. Gwarantuje to tym samym, że przy mało obłożonym serwerze, nawet połączenia o niskim priorytecie wykonają się możliwie najszybciej.

Dwie wbudowane grupy (“default” i “internal”) nie posiadają żadnych ograniczeń. Ich zadaniem jest wykonywanie zapytań, gdy: coś źle zostało sklasyfikowane (wtedy “default”) lub aby nie zagłodzić procesów własnych engine'u bazy, tzn.: SQL Server Agent, Service Brokera, checkpointów, czy lazy-writera (wtedy “internal”).

Za:

  • w końcu można kontrolować, co jest najważniejsze w naszym biznesie
  • jeden użytkownik nie ubije nam całego serwera dzięki “runaway” query

Braki:

  • jest to tylko własność Database Engine’u (czyli nici z zarządzaniem Analysis Services, Reporting Services, Integration Services…)
  • działa w obrębie jednej instancji (jeśli na jednej maszynie chodzi ich więcej, to o ile z pamięcią można próbować skonfigurować, to czasem procesora możemy zarządzać tylko przez opcje affinity, co nie jest dość optymalnym rozwiązaniem)
  • ograniczenie pamięci działa tylko na Query Execution Memory (nie pamięć cache), czyli podlegać mu będą jedynie zapytania alokujące pamięć (tj.: wymagające sortowania, łączenia tabel…)
  • brak restrykcji na operacje I/O
  • połączenie jest klasyfikowane tylko raz, podczas łączenia i później nie może być przeniesione do innej grupy, bez wcześniejszego rozłączenia (choć zasoby grupy mogą być zmieniane dynamicznie).


Z różnych powodów, czasem nie chcemy, aby ktoś przyglądał się naszej aplikacji w trakcie jej działania. Pomińmy jednak na chwilę te powody i skupmy się na samym wykrywaniu debuggera…

Najprostszą metodą sprawdzenia w systemie Windows, czy nasza aplikacja jest aktualnie uruchomiona w jego kontekście lub jest on podłączony można wykonać poprzez wywołanie funkcji IsDebuggerPresent() z WinAPI. Jednakże sprytny debugger może ją przesłonić i zawsze zwracać, że nie.

Informację tę zatem wyciągniemy samemu, “ręcznie” z bloku informacji o wątku (Thread Information Block – TIB). Pod indeksem 0x30 znajduje się wskaźnik na strukturę opisującą debugger. Drugi bajt tej struktury opisuje status tego, czego szukamy. Ponadto wartość ta jest dynamicznie uaktualniana, gdy tylko coś dzieje się z naszym procesem. Przykład implementacji funkcji w C, która pobierze dla nas tę wartość przestawiam poniżej.


int IsSuperDebuggerPresent ()
{
    int result;

    __asm
    {
        /* get the Thread Information Block (TIB) pointer */
        mov eax, fs:[18h]

        /* 0x30 byte points to the debugger structure: */
        mov eax, dword ptr [eax + 0x30]

        /* then second word indicates if the process is under debugging: */
        movzx eax, byte ptr [eax + 2]
        mov result, eax
    }

    return result;
}


Inną metodą pozwalającą sprawdzić, czy nic nie dzieje się wokół naszej aplikacji jest również sprawdzanie licznika instrukcji RTDSC (Time Stamp Counter). W swoim kodzie możemy oszacować ilość ticków procesora, która mija przy wykonywaniu pewnych, zabezpieczanych bloków instrukcji. Następnie porównywać je  ze statystykami prowadzonymi wśród całego kodu.  Tutaj jednak pojawiają się pytania – jak zachowywać się i w środowiskach wielowątkowych i wieloprocesorowych, gdzie wielkości te nie dają się łatwo przewidzieć i mogą zmieniać się w czasie…



9.-te spotkanie przygotowujące do egzaminu 70-432 za nami. Poprowadzona sesja o Database Engine Tuning Advisor oraz Resource Governor udana! Więcej takich sobie i wam życzę.

Materiały do pobrania tutaj. Video opublikowane zostanie niebawem.

Te same sesje również obejrzeć można na portalu www.VirtualStudy.pl.



Autor

Paweł Hofman [CodeTitans]

ASP.NET
C/C++, C#, Objective-C
SQL

License and Disclaimer

Moje Gry i Aplikacje

Zobacz mnie na GoldenLine

Zobacz mnie na LinkedIn
Supported by Polish SQL Server User Group (PLSSUG)

Supported by WrocNet.org

Zine.net.pl

Wpisy

Projekty

Moje projekty open-source:

Sign in