Tagszkript

GUI-k, gombamódra

Kaján vigyorral figyelem, hogyan szaporodnak a GUI-k a Powershell körül. Félre ne értsd, a Powershell az egyik legjobb dolog, ami az utóbbi években történt az MS világban… csak azon vigyorgok, ahogy a felhasználói igények – csobogó patakként – megtalálják a rövidítéseket, az alacsonyabb partszakaszokat.

Most például Glenn dobott össze egy apró kis szkriptet. Semmi extra, egyszerűen csak csinált egy GUI-t, mely a spamfilter ügynökök naplójából összevadászgatja azt, hogy mi is történt konkrétan egy-egy levéllel. Nyilván ugyanezt meg lehetne csinálni egy egyszerű szövegszerkesztőből is… csak sokkal fapadosabban, sokkal kényelmetlenebbül.

Beindult az evolúció. Amire van igény, az előbb-utóbb el is fog készülni. Én például határozottan biztos vagyok benne, hogy hamarosan lesz egy olyan szkript, mely a régi message tracking vizuális formájában mutatja meg egy-egy legyűjtés eredményét – a jelenlegi ugyanis borzasztóan kényelmetlen.

Linkek:

A Powershell és a Windows Server 2008 Core

Ez bizony két különböző világ. A Powershell az .Net alapú, márpedig a Server Core alatt nem fut a .Net.

Két dolgot tehetünk:

  • Megvárjuk, amíg a Microsoft valamelyik Feature Pack-ba belerakja.
  • Hekk!

Dimitrij Sotnyikov az utóbbit választotta. Istenem, türelmetlen típus.

Habár le is lehetne fordítani az írását, de mégsem teszem. A lépések annyira egyértelműek, a megértésükhöz sincs szükség semmilyen Rigó utcai certifikációra.

Szóval az írás. Itt.

ps1. Bár Dimitrij bevallja, ő is ‘szerezte’ az ötletet, Alex Kibkalo blogjából. De valamiért mégsem azt az írást linkeltem be.

ps2. Az írás korábban készült, de már erre a blogra terveztem kirakni. Gondoltam, pár napot csak tudok vele várni. Hát, nem. Közben Kurbli is kirakta.

Az erő velünk van

Na, ja. Csak nem mindegy, mennyire körülményes kezelni. A végén még a saját kezünket vágjuk le vele.

Nemrég füstölögtem néhány enyhén szürkét arról, hogy mennyire értelmetlennek tartom a Powershell (tudom, Exchange Management Shell, de már annyira rááll a szám) parancsok bemagolásszintű visszakérdezését vizsgán. Úgy látszik, nem csak én, hanem egy fejlesztő társaság is, akik megalkották a PowerGUI-t.

A tudásáról nagyjából képet alkothatunk, rögtön a telepítés elején.

Nagyítás

Jól látható, hogy alapvetően három területre koncentrál: Exchange 2007, Operation Manager 2007 és Network. Ezekhez szép színes grafikus felületet kapunk, ráadásként pedig egy Powershell szkript editort.

Nagyítás

A fenti kép egy kicsit olyan, mint az az állatorvosi ló. Igyekeztem úgy sarokba szorítani a programot, hogy lehetőleg minél többet áruljon el magáról. Éppen ezért direkte olyat kértem tőle, mely kimaradt az Exchange Management Console-ból: kértem egy statisztikát az egyik felhasználóm postafiókjáról. (EMS-ben ez ugye úgy nézne ki, hogy get-mailboxstatistics 25ezer paraméter.) Az akciópanelen látszik, hogy a képernyőkimenetet mindenféle formátumú fájlokba irányíthatjuk. Lenyitottam a Tools menüt, bemutatva, hogy a GUI-ból is meghívhatjuk a szkript editort – és természetesen ez igaz visszafelé is. Végül alul látható, két nyomógomb: ezek közül a ‘Powershell Code’ feliratú az eddigi tevékenységünket naplózza vissza, értelemszerűen PSH kódban.

Még egy érdekesség.

Nagyítás

Az ugye tiszta, hogy bármelyik kattogtatás végeredménye egy Powershell parancs vagy szkript lesz. Ezt a szkriptet az adott menüpont tulajdonságaként kérdezhetjük le. A fenti képen például a Computers, azaz számítógépek listájának szkriptje látható – mely PSH szkriptbe ágyazott ADSI lekérdezésekből áll.

Szóval GUI. De nehogy azt hidd, hogy ellene vagyok a szkript alapú menedzselésnek, isten ments. Határozottan örülök a dolgok ilyetén alakulásának – csak éppen elijeszt a hatalmas paraméterkupac, és a körülményes keresgetés. Ezért is örülök én inkább a csomaggal adott szkript editornak.

Nagyítás

Ehhez a képhez véleményem szerint nem szükséges semmilyen magyarázat.

És hogy mennyibe kerül? A program jelenleg tokkal-vonóval ingyenes (béta), köszönhetően a Quest Software támogatásának. Ami biztos, az az, hogy a szkript editor ingyenes is marad. Azaz… hajrá, irány kipróbálni. Ahogy Dimitrij mondta, ‘Notepad for Powershell’.

ps:
Mondjuk, azért érdekes hintapalinta ez:

  • Először elkészül a Powershell (leánykori nevén Monad).
  • Aztán elkészül az EMS modul, mely tulajdonképpen a Powershellbe beépülő snapin.
  • Utána az Exchange fejlesztőcsapat elkészít egy MMC3 snapin-t, mely gyakorlatilag egy varázslókkal sűrűn telepakolt grafikus felület a leggyakrabban használható EMS/Powershell parancsok végrehajtásához.
  • Végül jön egy csapat, aki elkészít egy grafikus felületet, mely tudja mindazt, melyet az Exchange fejlesztők – ki tudja, miért? – kihagytak az általuk gyártott GUI-ból. Nem mellékesen odatettek egy script editort, melynek segítségével tényleg felszabadíthatjuk agyunk azon területeit, melyet eddig a parancs paraméterek foglaltak le.

Jogos lehet a kérdés: akkor most hogyan is állunk a szkript vs. GUI fronton?

Hátbatámadás

Érdekes hibakeresési módszert olvastam Dave Goldman blogjában. Azt mondja, vannak olyan esetek, amikor a Powershell úgy fut lyukra, hogy semmilyen értelmezhető hibaüzenetet sem ad vissza. Én ugyan még nem találkoztam ilyennel, de hiszek neki.

– Ilyenkor nyúljunk vissza a gyökerekhez – javasolja. (Hogy ehhez mit szólnak a gyökerek, arról nem szól a fáma.) Végülis az egész Powershell .net alatt íródott, így a hibakódot el lehet kapni a System.Exceptions objektumon keresztül.

Nosza, csapjunk bele. Írjuk be a hibát okozó parancsot, regisztráljuk, hogy nem jött értelmezhető hibaüzenet, majd olvassuk ki a hibát:

  • $hiba = $error[0]

Utána pedig nézzük meg, mit mutatnak az egyes tulajdonságok. Pl:

  • $hiba.Exception.StackTrace
  • $hiba.Exception.InnerException
  • $hiba.Exception.InnerException.StackTrace

Majd ha még ez sem elég, akkor a kapott hibakódot betáplálhatjuk az err.exe programba és még több információval leszünk gazdagabbak.

Gondoltam, megnézem, hogy is néz ki ez a gyakorlatban. Mint írtam, én még nem tudtam olyan hibát produkálni, melyről ne kaptam volna vissza hibaüzenetet – de mi lenne, ha leellenőrizném, hogy tényleg jó-e a hibaüzenet? Be is írtam egyből, hogy
get-publicfolder -identity kiskutyafule

A következmények alább láthatóak:

Az err.exe kimenetele pedig itt:

Nálam átment a vizsgán.

21

Annyi otthoni teendőm torlódott fel, hogy szószerint megbénultam az íróasztalom előtt. Ezt is kellene, azt is kellene, ez rohadt sürgős, na az meg aztán végképp… csak néztem a monitoromat, néztem… végül úgy döntöttem, hogy hagyom eluralkodni magamon az ösztöneimet és játszok egy kicsit.
Persze geek módra.
Barnának ma este mutattam egy ízelítőt a logikai folyamatok grafikus ábrázolási módjairól, megemlítve, hogy ilyesmi ábrák jelentik a számítógép programozásának az alapjait is. Aztán – már egyedül, magamban – elgondolkodtam, le tudnám-e skiccelni a huszonegyes kártyajáték modelljét. Persze, vágtam rá. Igazából le se kellett rajzolnom, pár perc alatt fejben összeraktam.
Utána jött az izgalom: félóra alatt le tudnám-e programozni ezt – demonstrációs céllal – akármelyik itthoni számítógépen? Emlékszem-e még ennyire a régi dolgaimból, bennem van-e még készség szinten valami programolás – és van-e még eszközöm ahhoz, hogy csak úgy összedobjak egy programot? (Ugye a C64 esetében nem volt gond. Korai – első 10 év – IT-s időmben mindig volt vagy Pascal, vagy Clipper a gépemen beélesítve, bármikor gyorsan kellett valamit csinálnom, egyből ment.)

Az utóbbi feltétel nem okozott komoly problémát: az eszköz természetesen egy átlagos gépen is adott, Excel ma már mindenhol van – és ahol Office van, ott VBScript is van, nem is rossz GUI-val. A programolással már elvoltam egy kicsit, már csak hiúságból is igyekeztem minél tisztábban, egyszerűbben megoldani a feladatot. Jól elvoltam, na.
A sürgős teendőim meg ennyit igazán várhatnak.

Végül itt van a program. Maga az Excel tábla is letölthető, a vbscript része meg alant olvasható.

Sub Macro1()

‘ Macro1 Macro
‘ Macro recorded 2006.11.06 by The Tiger of Wekerle

‘ Keyboard Shortcut: Ctrl+a

Dim i, lapom

Range(”B2:C24″).Select
Selection.ClearContents

i = 0
lapom = 0

Do While lapom < 16 And lapom < Cells(2, 1)
i = i + 1
lapom = lapom + (Int(10 * Rnd(1)) + 2)
Cells(1 + i, 2).Value = lapom
Loop

If Cells(2, 1) > 21 Then
Cells(1 + i, 3).Value = “Yeah, the smarter has won!”
Else
If Cells(1 + i, 2).Value < Cells(2, 1).Value Or Cells(1 + i, 2).Value > 21 Then
Cells(1 + i, 3).Value = “Your mother wears army boots”
Else
Cells(1 + i, 3).Value = “Yeah, the smarter has won!”
End If
End If

Range(”A2″).Select

End Sub

ps: A sorbehúzásokért elnézést, nem szoktam ilyen csúnyán forráskódot írni, de a WordPress kigyomlálja a space-ket.

Egyszerű kiolvasás

Abszolút egyszerű feladatot kaptam. Csináljak egy listát, a következő oszlopokkal: felhasználói név, GUID. Az első oszloppal nem volt semmi gond és úgy véltem, a másikkal sem lesz. Kétperces munka. Egy perc volt, amíg megnéztem adsiedit-tel, hogyan is hívják a tulajdonságot: objectguid. A következő perc pedig azzal telt, hogy az előregyártott lekérdezőszkriptemben átírtam a lekérdezést a kívánt formára.
Majd az elkövetkező pár órában azzal foglalkoztam, hogy rájöjjek, miért is nem működik ez a módszer. A szkript ugyanis üres oszlopot hozott le.
Rutinosan kikapcsoltam a szofisztikált hibafigyelést (on error resume next), így meg is kaptam a várt runtime error-t.
Nézzük, ldp-ből mit látok. Semmit. Nincs ilyen tulajdonság. Visszamentem az adsiedit-hez, hátha az előbb káprázott a szemem, de nem – a tulajdonság ott volt, sőt, módosítani is tudtam. (Ezzel azért óvatosan.) Azaz jogosultsági probléma sem lehet.
Jöjjön a gugli power. Hosszas keresgélés után találtam olyan linkeket, miszerint felejtsem el, a feladat vbscript segítségével nem oldható meg. Ugyanis az objectguid az egy binárisokat tartalmazó tömb, a vbscipt viszont kizárólag a variant típusú tömböket tudja kezelni.
Szerencsére a lendület továbbvitt és kipróbáltam még néhány keresőszót. És meg is lett az eredménye, rátaláltam egy írásra Eric Lippert blogján.
A szokásos szöveggel indít. Hogy miért nem lehet megoldani a feladatot. Aztán megmutatja, milyen trükközéssel lehet mégis.
Először bedobja a cstr() függvényt. Ez egy olyan függvény, amely képes kigondolkozni a dobozból. Mindent, még az általa értelmezhetetlen adatokat is átkonvertálja sztringgé. Bízik benne, hogy a programoló csak tud kezdeni valamit a karakterkukaccal. És Eric tud. Nekiáll sztringet szeletelni, karaktereket konvertálni, nullából duplanullát csinálni – míg végül a boszorkánykonyhájából kipottyan a friss, ropogós GUID.

Egyszerű kiolvasás. Ja.

Itt sincs, ott sincs

Megőrjít.
Van egy kliens gépem. Ezen akarok futtatni egy szkriptet, mely távoli AD szájtok felhasználóinál módosítana display nevet. (Vbscript + ADSI.) Az adatok Excel táblában vannak.
Lefuttattam az egyik szájtra, a nevek átíródtak. Megnéztem ADUC-ból, tényleg.
Lefuttattam ugyanazt a szkriptet a másikra, nevek látszólag átíródtak. ADUC – mégsem íródtak át. Átfutottam az összes DC-t, sehol sem íródtak át. Picit átírtam a szkriptet, hogy most csak lekérdezze az értékeket – és tényleg nem íródtak át. Beleraktam még vagy ötször a setinfo-t, biztos, ami kurvafix – és kiegészítettem azzal, hogy írás után olvassa is vissza ADSI-n keresztül az értékeket és írja ki fájlba. Szkript lefutott, és a megváltozott értékeket írta ki. Gyorsan ADUC – sehol sem volt változás. Site-site replikáció megrángatása, újból körbenézés, semmi. Lefuttattam a szkriptet csak olvasó módban – a régi értékek jöttek vissza.
Hihetetlen.
A kliens gépről egy gyors próba, ldp-vel megváltoztattam a távoli szájt felhasználójának az adatát – és így működött, tehát se jogosultsági, se tűzfal probléma nincs. Ha ugyanezt egy nyomorult háromsoros vbscript-ből csináltam, akkor bezzeg nem ment.
Bele fogok dilizni. Ez az egy lépés van hátra abból a holland projektből, melynek már a nevétől is feláll a szőr a hátamon. És itt, az utolsó lépésnél jön be egy ilyen X akta, amikor már nem vágyom másra, mint hogy lezárjam ezt a szutykot.

Miután jól kisírtam magam, nekiálltam gondolkozni. Mi lenne például, ha kitörölném a bűvös ‘on error resume next’ sort?
Hoppá. Rögtön az elején befigyelt egy hiba:

Run-time error ‘-2147016693 (8007200b)
Automation Error
The attribute syntax specified to the directory service is invalid

Na, vajon mi lehet ez? Erős a gyanú, hogy adathiba, hiszen a szkript más szájtra lefutott. Kezdjünk játszani. Első körben csak a displayname értékét írtam ki – nem volt hiba. Jött a keresztnév, nem volt hiba. Jött a vezetéknév – és vele együtt a hiba. Hmm… ennyire kényes lenne az az sn attribútum?
Ránéztem az excel táblára – és letéptem az első sor csempét. Az adott szájton nem mi adminisztrálunk és a fiúk nem vacakoltak, a teljes nevet a keresztnévhez írták – azaz az sn attribútumba üres mezőt kellett volna betölteni. Ettől borult meg a szkript futás közben – de az onerrorresumenext továbblökte, mintha mi sem történt volna. Nem is történt semmi. Kiírás sem.
Oké. Akkor tegyünk bele egy vizsgálatot és ha üres a mező, akkor a kérdéses mezővel ne történjen semmi, de a sor többi mezőjét írja ki. Jó lesz ez? Nem biztos. Lehet, hogy az ügyfél törölt egy értéket és szeretné, ha az el is tűnne az AD-ból. Jó, akkor írjunk ki egy “”-t.
Nos, aki azt hiszi, hogy az oChild.attributum = “” lesz a jó megoldás, az még menjen vissza egy kicsit a homokozóba. Ugyanis pont ez a forma adta a fenti runtime error-t.
Igenám, de akkor hogyan lehet törölni egy attribútum értékét? Gugli.
És végül itt van a megoldás. Annyira szép, hogy alig hiszem el.
Tudni kell, hogy az AD-ba lehet cseppeként is írni. Ilyenkor csak a megváltozott attribútum értéke utazik a dróton, azaz spóroltunk egy csomó sávszélességet. Cserébe kicsit bonyolultabb a szintakszis.
Ilyen: oChild.putex X, “attributum”, valtozo,
ahol az X a helyzet kulcsa. Ugyanis ha X=2, akkor kiírás következik, ha X=1, akkor törlés.
Tehát a kérdéses kódrészlet:

If Trim(Cstr(Cells(sor,1).value)) = “” then
oChild.putex 1, “displayname”, “”
else
oChild.putex 2, “displayname”, Trim(Cstr(Cells(sor,1).value))
EndIf

Dögi. Futtassuk meg.
Megint ugyanazt a runtime error-t kapjuk. WTF?
Nos, ismét jött egy kis Gugli – majd megint lekerült a falról egy sor csempe.
A putex-es verzió ugyanis tömböt kér paraméternek. Miért? Csak. Akkor, amikor törlök, akkor nem is igazán kell neki érték, a “” bőven megteszi. De akkor, amikor módosítok, akkor bizony tömbbe kell rakni a változót.
Így fog kinézni a sor:
oChild.putex 2, “displayname”, Array(Trim(Cstr(Cells(sor,1).value)))
És ez már tényleg működik.

Illetve…
Boldogan engedtem rá a felturbózott szkriptet a böszme nagy excel táblára – és pár perc múlva megint runtime error-t kaptam. Egy kicsit megrugdostam az asztallábat majd nekiálltam nyomozni. Hiába. Minden teljesen rendben volt. Kínomban kimásoltam a táblázatból a dn értéket, benyomtam az ldp-be – és megfeküdt az is tőle. Nocsak. Nézzünk be az ADUC-ba.
Basszus. Amíg szarakodtam a szkripttel, addig törölték a felhasználót.
‘On error resume next’ visszakapcsol. Anyátok.

Requesting data from the Exchange Server

Valószínűleg több sorstársamnak is keserítette már meg az életét a fenti üzenet. Az Outlook kliens monoton homokórázik, a felhasználó csak ül, és a rendszergazdával karöltve szelíden bámulják a monitort.
Ashley Webb leírt egy történetet, ahol igen trükkösen kerítették be ezt a vadat.

Megjegyzés: a sztori – sajnos – nem egy univerzális módszer a probléma megszüntetésére. Csak érdekes megoldás egy szituációra.

Arról volt tehát szó, hogy a klienseknél teljesen sztochasztikusan bejött ez a hiba, miközben az Exchange szerver összes lényeges teljesítménymutatója teljesen rendben volt. (Innentől speciális a történet; a jelenséget ugyanis általában valamilyen szerveroldali/hálózati szűk keresztmetszet okozza.)
Webb szerette volna, ha a homokórázás alatt le tudja menteni az Information Store és a System Attendant által használt memóriatartalmakat (ADPlus.vbs), de ennek igen komoly akadálya volt a véletlenszerű előfordulás. Egész nap csak nem ülhet ott egy biorobot a szerver előtt, a telefonra koncentrálva…
Viszont rájöttek, hogy van egy mutató (Average RPC Latency), mely felugrik, ha bekövetkezik a hiba. Ez jó, mert a permormance monitorban rátettek egy alertet erre a mutatóra, mely egy küszöb átlépésekor automatikusan elindított egy programot – az ADPlus.vbs-t.
79 példányban. Ugyanis a dump elég hosszú ideig tartott, közben pedig az érték többször is leesett, majd visszaugrott. Itt egy garázsszagú buhera következett, összedobtak egy parancsfájlt, ez úgy indult, hogy megvizsgálta egy bizonyos txt fájl létezését: ha nem létezett, akkor létrehozta, majd futott tovább; ha létezett, akkor a szkript megállt.
És ennyi. Megszerezték a kívánatos memóriatartalmat.
A módszernek volt egy apró mellékhatása: a dump igen erőforrásigényes művelet, rendesen leterhelte az Exchange szervert. Amíg futott, addig nem is volt ideje kiszolgálni a klienseket.
Mit csinált helyette? Úgy van, kiszórta nekik is a címben szereplő üzenetet.:-)

[Update]
Benne volt a levegőben. Ha az Exchange csapat egyik tagja csak mellékesen is megemlít egy ennyire összetett és nehezen kezelhető hibát, biztosra lehet fogadni, hogy rengetegen követelnek majd részletes magyarázatot róla.
Nos, itt van a cikk, Nino Bilic tollából. Ez se rossz.