0

Zaawansowane filtrowanie w Windows Event Log


Jest mało znanym faktem, że Event Log Viewer umożliwia filtrowanie nie tylko graficzne, ale także zaawansowane query uwzględniające dowolne dane zawarte we wpisach określonego typu.
Drugim mało znanym faktem jest, że Event Log Viewer umożliwia wyświetlenie i filtrowanie po tak zwanym „Correlation ID”. Oczywiście, aplikacja wpisująca rekordy do dziennika zdarzeń także musi wspierać Correlation ID, gdyż część aplikacji nie zapisuje tego pola.
Niezwykle przydatną sprawą jeśli chodzi o Correlation ID jest to, że możemy odfiltrować zdarzenia związane z jakąś jedną konkretną czynnością, która generuje szereg zdarzeń, zakończony, na przykład, błędem.
Oto przykładowe query:

1
2
3
4
5
6
7
<QueryList>
  <Query Id="0" Path="file://C:\Logs\Logs.evtx">
    <Select Path="file://C:\Logs\Logs.evtx">
*[System[Correlation[@ActivityID='{8A348658-802A-4ACB-A855-1CC57EA25B18}'] and (Level=1  or Level=2 or Level=3 or Level = 4) and TimeCreated[@SystemTime&gt;='2016-11-27T15:11:00.000Z' and @SystemTime&lt;='2016-11-21T15:12:00.000Z']]]
    </Select>
  </Query>
</QueryList>

Każdy wpis w logu systemu windows od 2008 w górę jest prezentowany w formacie XML. Query się odnosi do pól we wpisie. Niestety nie jest to wyrażenie XPATH, ale jest równie intuicyjne i proste do odczytania.
Przedstawiam przykładowy wpis z dziennika zdarzeń:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
  <System>
    <Provider Name="Microsoft-Windows-GroupPolicy" Guid="{AEA1B4FA-97D1-45F2-A64C-4D69FFFD92C9}" />
    <EventID>1500</EventID>
    <Version>0</Version>
    <Level>4</Level>
    <Task>0</Task>
    <Opcode>1</Opcode>
    <Keywords>0x8000000000000000</Keywords>
    <TimeCreated SystemTime="2016-11-27T15:11:31.651603600Z" />
    <EventRecordID>31607</EventRecordID>
    <Correlation ActivityID="{8A348658-802A-4ACB-A855-1CC57EA25B18}" />
    <Execution ProcessID="1288" ThreadID="31724" />
    <Channel>System</Channel>
    <Computer>ComputerName</Computer>
    <Security UserID="S-1-5-18" />
  </System>
  <EventData>
    <Data Name="SupportInfo1">1</Data>
    <Data Name="SupportInfo2">4202</Data>
    <Data Name="ProcessingMode">0</Data>
    <Data Name="ProcessingTimeInMilliseconds">0</Data>
    <Data Name="DCName" />
  </EventData>
</Event>

Najprostszą metodą do rozpoczęcia prac nad kwerendą jest wyjście od ustalenia elementarnych warunków Filtrowania poprzez wybranie opcji „Filter Current Log”.
Poniższy wycinek ekranu pokazuje przykładowe warunki filtru.
ScreenShot1
Następnie przechodzimy na zakładkę „XML” i zaznaczamy checkbox „Edit query manually”
ScreenShot2
Po zatwierdzeniu komunikatu o fakcie, iż nie będzie można tego query już więcej edytować graficznie, otrzymujemy edytor query.
ScreenShot3
Filozofia tworzenia query jest prosta. Każdy tag, na podstawie którego będzie wykonywane filtrowanie znajduje swoje odzwierciedlenie w postaci składni:

1
Tag[Warunek1 and/or Warunek2 (...)]

Oczywiście można zagnieżdżać w wyrażeniu kolejne tagi, jak również łączyć je operatorami. Każdy wpis w logu systemowym, który spełni wszystkie warunki zostanie pokazany w odfiltrowanym widoku.
Przedstawię jeszcze raz filtr, który pojawił się na początku. Zostanie on sformatowany w trochę inny sposób, należy jednak pamiętać, że query powinno być zapisane w jednej linii.

1
2
3
4
5
6
7
8
9
10
11
12
*[
    System[
        Correlation[
            @ActivityID='{8A348658-802A-4ACB-A855-1CC57EA25B18}'
        ]
        and (Level=1  or Level=2 or Level=3 or Level = 4)
        and TimeCreated[
            @SystemTime&gt;='2016-11-27T15:11:00.000Z'
            and @SystemTime&lt;='2016-11-21T15:12:00.000Z'
        ]
    ]
]
  1. Linia query mówi, że wyszukiwania należy wykonywać w dowolnych node’ach najwyższego rzędu. Tak naprawdę chodzi o node
  2. Linia nakazuje przeszukać Tag . W ten sam sposób można się odnieść do sekcji
  3. Linia nakazuje przeszukać Tag , który znajduje się wewnątrz tagu
  4. Linia definiuje warunek, w którym przyrównujemy wartość atrybutu o nazwie ActivityID do określonego ciągu znaków
  5. Linia zamyka listę warunków sprawdzanych w obrębie tagu
  6. Linia definiuje warunek sprawdzający zawartość tagu nie posiadającego żadnych subtagów, tylko wartość.
  7. Linia i kolejne definiują warunek w obrębie tagu i odnoszą się do dwóch atrybutów tego tagu.
Continue...
0

Wprowadzenie do Failover Cluster Generic Script Resource


Dzisiaj chciałbym poświęcić trochę miejsca bardzo słabo udokumentowanej funkcjonalności Klastra.
Skrypty zasobów generycznych (Generic Script Resource) umożliwiają uruchomić w środowisku klastrowym nawet bardzo skomplikowane z punktu widzenia startu i potrzebnych zasobów usługi, które nie mają wbudowanych mechanizmów zapewniających wysoką dostępność.
W systemie Windows Failover Cluster umożliwia tworzenie skryptów zarządzających stanem zasobów JEDYNIE w języku Visual Basic (VBScript).
Ponieważ jest to technologia archaiczna, to powstały różne skrypty dostępne w sieci, służące do wywoływania innych narzędzi skryptowych. Ja posłużę się wersją uruchamiającą skrypty Powershell, gdyż jest to najlepszy obecnie dostępny język skryptowy dla systemu Windows.
Jednak, zanim dojdziemy do przedstawienia właściwych rozwiązań, chciałbym omówić filozofię tworzenia takich skryptów.
W środowisku klastrowym każdy zasób ma swojego właściciela (Owner Host). Jest host, na którym w danym momencie uruchamiany jest kod odpowiadający za obsługę zasobu. Celowo piszę „kod odpowiadający za obsługę”, gdyż może być to trojaki typ kodu:

  1. Manager Usług
  2. Biblioteka DLL zarządzająca zasobem (na przykład maszyny wirtualne)
  3. Skrypt zasobu generycznego

Po prawdzie, to implementacja zarówno managera usług jak i zasobu skryptu generycznego jest wewnętrznie realizowana przez odpowiednią DLL, ale rozróżnienie to jest przydatne dla administratorów i wdrożeniowców mających zdecydować, w jaki sposób należy zapewnić wysoką dostępność.

Cykl życia zasobu można opisać pewnymi etapami, które są charakterystyczne dla każdego właściciela. Należą do nich:

  1. Inicjalizacja managera zasobu (Open)
  2. Uruchomienie zasobu (Online)
  3. „Obejrzenie stanu zasobu” (LooksAlive)
  4. Sprawdzenie stanu zasobu (IsAlive)
  5. Wyłączenie zasobu (Offline)
  6. Zniszczenie zasobu (Terminate)
  7. Zamknięcie managera zasobu (Close)

Nazwy funkcji Callback implementowane w skrypcie zasobu Podane zostały w nawiasach.
Istotne jest wyjaśnienie różnicy między LooksAlive a IsAlive, gdyż na pierwszy rzut oka wydaje się to być dość nietypowe rozwiązanie. Callback LooksAlive jest wywoływany często, żeby zmniejszyć możliwie najbardziej czas reakcji na ewentualną awarię. Czas wykonania tego callback’a jest ograniczony do 300ms.
Dopiero, gdy ta funkcja zwróci błąd wywoływana jest funkcja IsAlive.
Ponadto raz na około minutę wywoływana jest funkcja IsAlive niezależnie od opisanego powyżej mechanizmu. Wynika to z pryncypium szybkiego wykonania LooksAlive, a w konsekwencji pobieżnego sprawdzenia, które może coś (celowo, lub nie) przeoczyć.
Dlatego manager klastra i tak sprawdza pełną diagnostykę zasobu raz na minutę. Jest to na tyle nieduży czas, że jeszcze akceptowalny dla większości usług, a z drugiej strony jest on na tyle duży, że nie wprowadza znacznego obciążenia do systemu „władającego” usługą.
Pozostałe funkcje callback ze skryptu nie wymagają dłuższego omówienia.

Bardzo ważną sprawą do omówienia, gdyż z tym się mogą wiązać błędu i w konsekwencji problemy z uruchomieniem, jest kwestia zmiennych zasobu. Każdy zasób może (i powinien) przechowywać swój stan konfiguracji w przestrzeni klastra – dzięki temu unikniemy sytuacji, w której usługa będzie zachowywać się niespójnie na różnych hostach-właścicielach zasobu.
Istotnym jest, aby definiować zmienne zasobu na samym zasobie skryptu, a nie na grupie zasobów, czy też na zasobie adresu ip albo jakimkolwiek innym zasobie w grupie. Tylko zmienne zasobu skryptu (czyli zdefiniowane dla instancji typu Generic Script Resource) będą dostępne przez Api Klastra.

API klastra reprezentowane jest przez obiekt VBScript o nazwie

1
Resource

Przykład użycia tego obiektu prezentuje poniższa funkcja:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Function CheckProperties(ActionName, ErrorBaseCode)
    If Resource.PropertyExists("DebugVBA") = False Or Resource.PropertyExists("DebugPS") = False Then
        WshShell.LogEvent 1, "No Debugging Settings! Exiting."
        CheckProperties = ErrorBaseCode+1
        Exit Function
    End If
    LogEvent 4, "Enter " & ActionName & "()"
    If Resource.PropertyExists("PSScriptsPath") = False Then
        LogEvent 1, "Error " & ActionName & "(). No PSScriptsPath private property. Exiting."
        CheckProperties = ErrorBaseCode+2
        Exit Function
    End If
    If Resource.PropertyExists("QueueIndex") = False Then
        WshShell.LogEvent 1, ActionName & "(): No Cluster Queue Definition! Define QueueIndex private property. Exiting."
        CheckProperties = ErrorBaseCode+3
        Exit Function
    End If
    CheckProperties = 0
End Function
Continue...
0

Windows Terminal Services Logon „Access Denied”


Dzisiaj przedstawię rozwiązanie problemu z Usługą Terminalową w środowisku z odrębnym serwerem Licencji Terminalowych.

Symptomy:

  • W trakcie logowania użytkownik otrzymuje komunikat „Access denied.”. Wyświetlany jest on zamiast ekranu logowania po uprzednim komunikacie „Welcome”.
  • W logu aplikacyjnym i systemowym nie występują żadne informacje o błędach, lub są one ewidentnie niezwiązane z podstawowym objawem.
  • W logu TerminalServices-LocalSessionManager występuje następujący wpis skorelowany z próbą logowania użytkownika: „Session X has been disconnected, reason code 12″, gdzie X oznacza numer sesji przydzielony konkretnej próbie logowania.
  • Problem ten dotyka zarówno systemy windows 2008 R2 jak i 2012 (R2).
  • Często towarzyszy tej sytuacji brak możliwości wymuszenia GPO

Tymczasowym rozwiązaniem problemu może być wykonanie dodatkowego wpisu w rejestrze:

1
2
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\
IgnoreRegUserConfigErrors (DWORD) = 1

Po dodaniu tego wpisu konieczne jest ponowne uruchomienie komputera.

Po zażegnaniu kryzysu związanego z brakiem możliwości pracy użytkowników na spokojnie można przystąpić do diagnostyki, co się zepsuło tak naprawdę.
W tym konkretnym przypadku przyczyną był błędnie skonfigurowany Firewall na kontrolerach domeny przy użyciu GPO, gdzie był zabroniony ruch „SMB over TCP”.
Przyczyn należy w każdym razie szukać w otoczeniu kontrolerów domeny.

Continue...
0

Failover Cluster Generic Script Resource Failed 0×80070009


Witajcie,

Dzisiaj chciałbym się podzielić spostrzeżeniem mocno nieintuicyjnego zachowania funkcjonalności Failover Clustering w Windows 2012 R2.
Mianowicie, może się zdarzyć, że po przygotowaniu skryptu kontrolującego zachowanie aplikacji (Generic Script), której chcemy zapewnić wysoką dostępność i po konfiguracji zgodnie z tym blogiem Zespołu produktowego Microsoft zasób klastra nie zostanie uruchomiony, a status zasobu będzie zawierał informację

1
The storage control block is invalid.

Przedstawia to poniższy zrzut ekranowy:
Status zasobu klastrowego
Kiedy zgodnie z sugestią z komunikatu o błędzie wyświetlimy rozszerzoną informację o błędzie uzyskamy informację o kodzie błędu

1
0x80070009

Rozszerzona informacja o błędzie
Podobny wpis zostanie odłożony w logu systemowym klastra:
Log systemowy klastra

W takiej sytuacji należy przede wszystkim się upewnić, że przygotowany przez nas skrypt nie zwraca z żadnego wywołania API wartości 0×9.
Gdy posiadamy taką pewność, to błąd ten oznacza, że skrypt Visual Basic ma niepoprawną składnię i menedżer zasobów klastra nie był w stanie prawidłowo go skompilować.
Dlatego dobrą praktyką jest przed utworzeniem zasobu klastrowego weryfikacja poprawności kompilacji skryptu. W tym celu należy wydać polecenie z linii poleceń:

1
cscript.exe C:\pełna\ścieżka\do\pliku.vbs

Ponieważ skrypt zawierać powinien same definicje funkcji, a nie ma żadnych ich wywołań (cecha charakterystyczna wywołań zwrotnych – „CallBack”), to prawidłowo napisany skrypt nie powinien nic wykonać ani wyświetlić.
W przypadku nieprawidłowej walidacji wynik będzie podobny do poniższego zrzutu ekranu:
Błąd walidacji skryptu

Pozdrawiam serdecznie i życzę samych poprawnych skryptów!

Continue...
0

Migracja zasobów między subskrypcjami w MS Azure


W chmurze Microsoft Azure użytkownik może posiadać dowolną liczbę subskrypcji. Subskrypcja jest najmniejszą jednostką konfigurującą sposób płatności i zakres własności zasobów.
Każda subskrypcja generuje swój osobny Billing. Nie ma żadnego znaczenia w tym przypadku fakt, że jeden użytkownik, czy organizacja jest właścicielem subskrypcji. Jedna subskrypcja, jeden rachunek. Istnieje wyjątek w postaci umów typu Enterprise, gdzie ten model jest bardziej skomplikowany, ale ten temat zostawiamy na boku.
Istotne jest to, że będąc indywidualnym właścicielem kilku subskrypcji, można dostać na przykład 3 rachunki opiewające na 2 euro. To potrafi być irytujące.
Dlatego zaistniała potrzeba połączenia subskrypcji ze sobą.
Jedną metodą, jaka jest dostępna w Azure, na wykonanie takiej akcji jest migracja zasobów do jednej z subskrypcji i odwołanie pozostałych. W sieci można znaleźć dużo pytań na ten temat, jednak mało która odpowiedź jest konkretna. Okazuje się jednak, że rozwiązanie jest bardzo proste i wspierane. Opisane dokładnie w szczegółach jest w tym artykule.
Tutaj tylko przytoczę informację o tym, że możliwość migracji jest uzależniona od konkretnego typu zasobu i niektóre zasoby posiadają pewne ograniczenia w przenoszeniu.
Pełna lista zasobów wspierających przenoszenie dostępna jest tutaj.

Continue...
0

Optymalizacja kosztów utrzymania Azure WebApps – prezentacja


W dniu 23. czerwca 2016 miało miejsce drugie spotkanie krakowskiej grupy Azure Users Group Poland.
W ramach tego wydarzenia przedstawiłem prezentację dotyczącą różnych sposobów optymalizacji kosztów utrzymania Azure WebApps.
Prezentację z tego wystąpienia można znaleźć tutaj
Stanisław Wawszczak przedstawia prezentację

Continue...
0

Generowanie Żądania certyfikatu z openssl dla Microsoft Enterprise CA


Dawno temu pisałem o tym, jak wygenerować żądanie certyfikatu dla systemów nie będących Windowsami tak, aby dało się certyfikat wystawić na Microsoft Enterprise CA. Jako przykład podałem generowanie certyfikatów serwera vCenter
Niedawno temat powrócił, ale w nowej odsłonie, gdyż serwer vSphere wymaga zdefiniowania w certyfikacie odpowiednich Nazw Alternatywnych. Powstało pytanie, jak pogodzić te dwie funkcjonalności.
Okazuje się to być całkiem proste, trzeba tylko pamiętać, że choć plik konfiguracji openssl pozwala na wiele sekcji opisujących rozszerzenia żądania certyfikatu, to tylko jedna z nich może być wykorzystywana w trakcie generowania certyfikatu. Dlatego przygotowując plik konfiguracyjny dla określonego serwera warto uporządkować jego strukturę, względem propozycji przedstawionej w poprzednim wpisie.
Przykładowy plik konfiguracyjny może wyglądać następująco:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
openssl_conf = openssl_init

[ openssl_init ]
oid_section = new_oids

[ req ]
default_bits = 2048
default_keyfile = rui.key
distinguished_name = req_distinguished_name
encrypt_key = no
prompt = no
string_mask = nombstr
req_extensions = v3_req

[ new_oids ]
MsCaCertificateTemplate = 1.3.6.1.4.1.311.20.2

[ v3_req ]
basicContraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectAltName = DNS:server01, DNS:server01.domena.test
MsCaCertificateTemplate = ASN1:PRINTABLESTRING:VMwareCertificate

[ req_distinguished_name ]
countrName = PL
stateOrProvinceName = Malopolskie
localityName = Krakow
0.organizationName = Firma
organizationalUnitName = Oddzial
commonName = server01.domena.test

Analizując najważniejsze części:

  • Linia 1. Wskazuje na sekcję będącą konfiguracją globalną.
  • Linia 4. Wskazuje na sekcję defniującą OIDy. Linia ta jest jedyną w sekcji konfiguracji globalnej
  • Linia 13. Wskazuje na sekcję definiującą rozszerzenia, które zostaną dodane do żądania certyfikatu
  • Linia 15. Definiuje sekcję z OIDami.
  • Linia 16. Definiuje OID zarejestrowany i użytkowany przez Microsoft do oznaczania rozszerzenia definiującego szablon certyfikatu
  • Linia 22. Definiuje alternatywne nazwy serwera. Należy zwrócić uwagę na fakt, że w przykładzie używany jest prefiks DNS: Możliwe są także inne prefiksy.
  • Linia 23. Definiuje nazwę używanego szablonu certyfikatów. Należy zwrócić uwagę, że wykorzystywany jest wariant nazwy bez żadnych spacji. Nazywa się on „Certificate Template Name”, w przeciwieństwie do nazwy przyjaznej, nazywającej się „Certificate Template Display Name”

Pozostała cześć jest standardowa dla każdego żądania obsługiwanego przez openssl.

Continue...
1

Błąd Orchestrator 2012 R2 REST OIP: HTTP Version should be either 1.0 or 1.1


Dzisiaj szybka diagnostyka problemu przedstawionego w tytule postu.
Rozważamy następujący scenariusz:

  1. Orchestrator 2012 R2 zainstalowany na serwerze Windows 2012 R2
  2. Zaimportowany Integration Pack dla REST
  3. Skonfigurowane ustawienia regionalne które zakładają separator dziesiętny inny niż kropka (‘.’)
  4. W parametrach akcji „Invoke Rest Service” jest wprowadzona zgodna z dokumentacją wartość ciągu „1.0″ lub „1.1″

W Polsce, mamy Z scenariuszem takim mamy do czynienia zazwyczaj , gdzie zwyczajowym separatorem dziesiętnym jest przecinek.
I to właśnie on jest powodem powstania problemu, w przypadku gdy jesteśmy pewni że ostatni punkt scenariusza został zrealizowany prawidłowo.
Wewnątrz implementacji tej akcji znajduje się odpowiednik następującego kodu (tutaj przytaczam powershell, aby łatwo było potwierdzić diagnozę):

1
2
3
4
5
6
7
$result = 0;
$HTTPVersion = "1.1"
$status = [float]::TryDecode($HTTPVersion, [ref]$result);
if(($status -ne $true) -or ($HTTPVersion -ne "1.0") -or ($HTTPVersion -ne "1.1"))
{
"Return Error: HTTP Version should be either 1.0 or 1.1";
}

W sytuacji, gdy w ustawieniach regionalnych separator dziesiętny nie jest ustawiony na znak '.' to w linii numer 3 zostanie ustawione $status == $false.

Rozwiązaniem jest ustawić klucz rejestru HKU\SID\Control Panel\International\sDecimal
oraz HKU\SID\Control Panel\International\sMonDecimalSep dla użytkownika o wartości SID na znak '.'
Na koniec należy zrestartować usługę orchestratora, a problem zostanie rozwiązany.

Po raz pierwszy opisałem temat odpowiadając na pytanie rosyjskojęzycznej osoby z technet’u.

Continue...
1

Eksport/Import szablonów certyfikatów z AD w Windows 2012


Dzisiaj będzie parę słów o imporcie i eksporcie szablonów certyfikatów w Microsoft Active Directory.
Te dane są zapisane w partycji konfiguracji AD i przez to są współdzielone przez wszystkie domeny w obrębie lasu AD.
Czasem jednak zdarzają się sytuacje, kiedy zachodzi potrzeba przeniesienia tych danych między lasami, na przykład przy wdrażaniu testowanego uwcześnie rozwiązania w środowisku przed produkcyjnym do produkcyjnej domeny.
Zadanie takie może być wykonane na dwa różne sposoby. Pierwszy jest oczywisty dla tych, którzy mają z systemem windows duże doświadczenie, ale sposób ten jest brzydki i może powodować duże komplikacje w dzisiejszych systemach. Dlatego omówię go później.
Wraz z nadejściem systemu Windows 2008 R2 została wprowadzona nowa rola AD CS, która nazywa się AD CS Web Enrollment Service.
Służyć ona ma publikacji oraz użytkowaniu CA pomiędzy lasami AD, przy założeniu istnienia jedynie Zewnętrznej relacji zaufania pomiędzy tymi lasami. Więcej na ten temat można znaleźć tutaj.
Na tej samej stronie zostały też zamieszczone dwa świetne skrypty napisane w powershellu, które stanowią istotę dzisiejszego wpisu. Dzięki nim można wyeksportować oraz zaimportować szablony do oraz z plików XML w formacie MS-XCEP.
Niestety, te skrypty posiadają dwa błędy, które ujawniają się w trakcie pracy z systemem Windows 2012:

  1. skrypty zostały napisane jako zwykłe CMD-Let’y, które niestety nie są ładowane w W2k12. Szybkim obejściem tego problemu jest zakomentowanie deklaracji funkcji wraz z zamykającym nawiasem klamrowym na początku i końcu skryptu. Ponadto należy zakomentować deklarację parametrów jako cmd-let binding. Po tych zmianach skrypty uruchamiać się będą w normalny sposób z możliwością podania odpowiednich danych wejściowych, jak jest to wymagane.
  2. Funkcja eksportująca ma w niewłaściwy sposób zrealizowaną obsługę weryfikacji istnienia jednego z tablicowych atrybutów szablonu. Linię:
    1
    $superseded = if ($temp.Settings.SupersededTemplates -eq 0) {

    Należy zastąpić następującą:

    1
    $superseded = if ($temp.Settings.SupersededTemplates.Length -eq 0) {

    Dzięki temu zabiegowi zarówno eksport jak i import przebiegną pomyślnie..

  3. Ostatnią niedogodnością tych skryptów jest zależność od zewnętrznego modułu Power Shell. Ponieważ moduł jest napisany w .NET, na pewno istnieje możliwość wyeliminowania tej zależności, jednak ten temat będzie przedmiotem innego posta.

Wspominana wcześniej „brzydka metoda” to jest stara komenda ldifde wraz z wymaganymi flagami służącymi do eksportu:

1
ldifde -m -v -d cn=%Template1%,%LDAP% -f %Template1%.ldf

Najważniejszą częścią tej komendy jest przełącznik -m, który skutkuje wynikowym plikiem ldf pozbawionym odwołań do obiektów AD Forest.
Żeby zaimportować wygenerowany plik należy użyć bardzo podobnej komendy.:

1
 ldifde -i -k -f %Template1%.ldf

Metoda ta powinna działać dla wszystkich systemów, począwszy od Windows 2000.

Continue...
2

Pobieranie obiektów WMI osadzonych wewnątrz innych jako zmienne klas (C#)


Witajcie,

Dzisiaj szybkie spostrzenie dotyczące właściwości pobierania obiektów WMI będących zawartych wewnątrz obiektów zadanej klasy.
Gdy w podstawowej formie pobieramy kolekcję obiektów WMI spełniających zadane warunki, dostajemy w wyniku obiekt klasy System.Management.ManagementObjectCollection. Każdy z System.Management.ManagementObject posiada wypełnione jedynie podstawowe pola, będące zdefiniowane jako typy proste (int, string, bool). Jednak gdy chcemy odnieść się do pola, które jest typu innej klasy WMI, to dostajemy w rezultacie wartość NULL.
Aby wypełnić takie pole(a) należy wywołać na potrzebnym nam obiekcie metodę Get()
Metoda ta w dokumentacji przedstawiona jest jako popinająca reprezentację .NET klasy System.Management.ManagementBaseObject do rzeczywistej instancji WMI. Może być użyta jako skrótowa forma odwołania się do obiektu klasy poprzez wypełnienie atrybutu Path obiektu po czym wywołanie funkcji Get(). Jednak w naszym przypadku chodzi o ponowne podłączenie, które jako efekt uboczny (skutek wcześniejszej optymalizacji) daje pełną reprezetancję klasy wraz z osadzonymi wewnątrz obiektami (albo tablicami!).
Prezentuje to poniższy przykład:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// for kerberos constrained delegation
ConnectionOptions wmiOptions = new ConnectionOptions();
wmiOptions.Authentication = AuthenticationLevel.PacketPrivacy;
wmiOptions.Impersonation = ImpersonationLevel.Impersonate;
// for connection to remote host
ManagementScope scope = new ManagementScope("\\\\" + serverName + "\\root\\SMS\\Site_" + siteCode, wmiOptions);
// for performing query to wmi
WqlObjectQuery wmiQuery = new WqlObjectQuery(query);
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, wmiQuery);
// performing search itself
ManagementObjectCollection Colls = searcher.Get();
ManagementBaseObject[] rules = null;
ManagementObject coll = null;
//retrieving objects from collection, in this example we assume only one result
foreach (ManagementObject o in Colls)
{
      coll = o;
      // coll["CollectionRules"] == null
      coll.Get();
      // after previous call it is filled in
      rules = (ManagementBaseObject[])o["CollectionRules"];
}
Continue...