laboratoria – czyli skrypty, skrypciki i inne takie


   Wile osób woli uczyć się czytając przykłady. Ponieżej zamieszczam kilkanaście małych skrypcików, które urodziły się podczas gdy uczyłem się pewnych mechanizmów – czy to pewnych cech VBasic’a czy zachowania się interface’u LDAP. Każdy przykład jest krótko opisany – po co został napisany i co testuje. Na podstawie tych skryptów myślę, że spokojnie można będzie spłodzić jakiś własny wynalazek…
Poszczególne rzeczy opisane są jednokrotnie – czyli jeśli w którymś skrypciku jest jakiś mechanizm nieopisany, najprawdopodobniej wyjaśnienie znajduje się gdzieś powyżej, w opisie wcześniejszego kodu.


  1. Skrypcik został napisany w celu sprawdzenia jak w VBS’ie obsługuje się argumenty z linii poleceń.

    +———— testArgs.vbs

    01. ON ERROR RESUME NEXT
    02. Dim a
    03. a = WScript.Arguments.Item(0)
    04. wscript.echo wscript.arguments.count
    05. IF len(a)>0 Then
    06.     WScript.echo "jest argument"
    
    07. Else
    08.     WScript.echo "nie ma arg"
    09. End iF

    —–( źródło )—–

    opis:

    • [1.] wyłączone zostaje wstrzymywanie programu w razie wystąpienia błędu. Jeśli w programie zamieszczone są jakieś funkcje, ten blok powinien znajdować się w każdej funkcji – inaczej błąd, który wystąpi, spowoduje przerwanie wykonywania bloku finkcji [patrz kolejny przykład].
    • [2.] deklaracja zmiennej 'a’. W VB nie predefiniuje się typów zmiennych [podobnie jak w JScipcie]. Type zmiennej jest automatycznie określany kontextowo.
    • [3.] WScript.Arguments jest tablicą argumentów skryptu. Item(0) to pierwszy element tej tablicy. Jest to wyra�ne niedpatrzenie ze strony twórców VBScriptu, ponieważ powinien od zwracać nazwę samego skryptu [testArgs.vbs], tak jak jest to np. w C, C++ czy Javie.

      zmiennej ’a’ przyjmuje wartość stringową, występującą jako pierwszy parametr.

    • [4.] na ekran wyświetlona zostaje [wscript.echo] informacja o ilości wszystkich argumentów [wscript.arguments.count]
    • dalej w zalezności od tego czy długość argumentu jest większa od zera [czyli jest jakiś argument][if len(a)>0 then] wyświetlana jest odpowiednia informacja.

  2. Jest to w zasadzie to samo co powyżej, z kilkoma dodatkami.

    +———— testArgs2.vbs

    01. OPTION EXPLICIT
    02. ON ERROR RESUME NEXT
    03. 
    04. Dim a
    05. show
    06. 
    
    07. Sub show
    08. ON ERROR RESUME NEXT
    09.     a = WScript.Arguments.count
    10.     IF a<>0 Then
    11.         WScript.echo "jest argument "&WScript.Arguments.item(0)
    12.     Else
    
    13.         WScript.echo "nie ma arg"
    14.     End iF
    15. end sub

    —–( źródło )—–

    opis:

    • [1.] o ile ’ON ERROR...’ może pojawić się w każdym miejscu, o tyle ’OPTION EXPLICIT’ musi być pierwszą linijką skryptu. Generalnie w VBS’ie nie ma obowiązku deklaracji zmiennych [Dim a]. Zostaną one automatycznie zadeklarowane w razie potrzeby. Czyli w poprzednim przykładzie linijkę 2 można było pominąć. ’OPTION EXPLICIT’ powoduje, że brak zadeklarowania zmiennej będzie błędem. Jest to przydatne [wręcz zalecane] w dużych skryptach w celu uniknięcia literówek, z czego mogą wyniknąć trudne do odnalezienia błędy.
    • [4.] wywołanie procedury 'show’ zdefiniowanej w liniach 6-13. W VBS’ie są procedury [SUB] i funkcje [function]. Funkcje to procedury przyjmujące wartość.
    • we wnętrzu procedury został zmieniony kod względem poprzedniego przykładu, na bardziej poprawny – najpierw sprawdzana jest ilość parametrów, żeby uniknąć operacji na null’ach.

  3. Testowanie obsługi tablic.

    +———— testArray.vbs

    01. Dim arr
    02. arr=Split( trim(" jakis tam sobie text ") )
    03. wscript.echo "----"
    04. wscript.echo ubound(arr)
    
    05. wscript.echo "----"
    06. redim arr(0)
    07. wscript.echo ubound(arr)
    08. arr(0)="ala"
    09. wscript.echo arr(0)
    10. redim preserve arr(ubound(arr)+1)
    11. arr(ubound(arr))="kot"
    12. wscript.echo arr(1)
    13. 
    
    14. dim arr2
    15. redim arr2(1,0)
    16. arr2(0,0)="ala"
    17. arr2(1,0)="kot"
    18. wscript.echo arr2(0,0)&" "&arr2(1,0)
    19. wscript.echo ubound(arr2,2)
    20. 'u can preserve only resizing last dimention
    21. redim preserve arr2(1,1)

    —–( źródło )—–

    opis:

    • linie 1-5 to test funkcji split(), która dzieli podany string na kawałki i tworzy z tego tablicę. Warto zwrócić uwagę, że również w tym przypadku typ zmiennej został automatycznie zkonwertowany na macierzowy – ’arr’ stało się tablicą. Pojawia się również funkcja trim(), która obcina puste znaki na końcu i początku stringa. ubound() zwraca ilość elementów w tablicy [tutaj 4];
    • [6.] zmiana wielkościd tablicy na 0;
    • [10.] zwiększenie wielkości tablicy [redim] z zachowaniem znajdujących się w niej elementów [preserve] o jeden, w stosunku do obecnej wielkości tablicy.
    • linie 14-21 to trochę zabawy z tablicami dwuwymiarowymi. To co jest najważniejsze to to, że powiększać z zachowaniem poprzedniego stanu [redim preserve] można tylko ostatni element macierzy.

  4. Przykład obrazujący sposób bindowania się do domeny z autoryzacją czyli podaniem usera i hasła. Taki sposób jest potrzebny jeśli bind’ujesz się z systemu poza domeną.

    +———— testAuthorization.vbs

    01. Dim oADsObject,oADsNamespace
    02. Dim strADsNamespace, strADsPath
    03. 
    04. strADsPath="LDAP://CN=userName,OU=studenci,DC=pjwstk,DC=edu,DC=pl"
    
    05. 'strADsPath="WinNT://pjwstk/userName,user"
    06. strUserName="pjwstkuserName"
    07. strUserPassword="userPassword"
    08. 
    09. strADsNamespace = left(strADsPath, instr(strADsPath, ":"))
    10. set oADsNamespace = GetObject(strADsNamespace)
    11. 
    12. on error resume next
    13. Set oADsObject = oADsNamespace.OpenDSObject(strADsPath, strUserName, strUserPassword, 1)
    
    14. ' we've only managed to bind if err.number = 0
    15. if not (Err.number = 0) then
    16.     WScript.echo "Failed to bind to object " & strADsPath
    17.     WScript.echo err.description
    18.     WScript.echo "Error number is " & cstr(hex(err.number))
    19. else
    
    20.     WScript.echo "USER AUTHENTICATED!"
    21.     WScript.echo "Currently viewing object at " & oADsObject.ADsPath
    22.     WScript.echo "Class is " & oADsObject.Class
    23. end if

    —–( źródło )—–

    opis:

    • przykład będzie działał tak samo dla providera LDAP jak i WinNT – obecnie wyremowana jest linijka 5, ale można zamiast niej wyremować 4.
    • użytkownik i hasło nie powinny oczywiście być w pliku – jeśli chciałoby się to wykorzystać w rzeczywistości powinno się zczytać jako argumenty.
    • [13.] to własciwe bind’owanie
    • [17.] pojawia się tu err.desciption – teoretycznie coś takiego istnieje i jest opisane w dokumentacji. W rzeczywistości to jakiś fake – nigdy mi jeszcze nie zadziałało. Panuje tu typowa regóła – chcesz mieć coś zrobione – zrób to sam.
    • [20-22]: jeśli autentykacja przebiegnie właściwie, zostają wyświetlone dwa atrybuty obiektu 'user’ – pełna ścieżka i klasa obiektu [czyli 'user’]
    • należy zwrócić uwagę, że w poprzednich przykładach nie pojawiało się 'set’ – ponieważ przypisując zmiennej wartość nie korzysta się z tej funkcji. Tutaj pewne zmienne stają się referencjami do obiektów – stąd 'set’ w momencie ustalania referencji.

  5. Tworzenie usera za pomocą providera LDAP z kilkoma parametrami.

    +———— testCreateUser.vbs

    01. Dim ADPath
    02. 
    03. ADPath="LDAP://pjwstk.edu.pl/DC=pjwstk,DC=edu,DC=pl"
    04. CreateUser ADPath, "testowy", "abc123def", "Imie Nazwisko", ""
    05. 
    
    06. sub CreateUser(ServerName, name, password, fullname, logonscript)
    07.     on error resume next
    08.     err.clear
    09. 
    10. 	'set objProvider = LDAP:
    11. 	set objDomain = GetObject(ADPath)
    12.     If Err.Number then
    
    13. 		If CStr(Hex(Err.Number)) = "80070035" Then
    14. 			Print "Object " & strDomain & " is not found."
    15. 		Else
    16. 			Print "Error 0x" & CStr(Hex(Err.Number)) & " occurred in getting object " & strDomain & "."
    
    17. 			If Err.Description <> "" Then
    18. 				Print "Error description: " & Err.Description & "."
    19. 			End If
    20. 		End If
    21. 		Err.Clear
    
    22.         Exit Sub
    23. 	Else WScript.echo "ok1"
    24.     End If
    25. 
    26. 	set objUser = objDomain.Create("user", "cn=" & name)
    27.     If Err.Number Then
    
    28.         Print "Error " & CStr(Hex(Err.Number)) & " occurred in creating user account " & strUser & "."
    29.         Print "Failed to create user " & strUser & "."
    30.         Err.Clear
    31.         WScript.Quit
    
    32. 	Else
    33.         WScript.echo "ok2"
    34.     End if
    35. 
    36. 	objUser.sAMAccountName = name
    37.     If Err.Number Then
    
    38. 		Wscript.echo CStr(Hex(Err.Number)) & " name"
    39. 		Err.Clear
    40. 	End If
    41. 
    42. 	objUser.Fullname = fullname
    43.     If Err.Number Then
    
    44. 		Wscript.echo CStr(Hex(Err.Number)) & " fulln"
    45. 		Err.Clear
    46. 	End If
    47. 
    48.     if not isNull(logonscript) then
    49.         objUser.loginscript = logonscript
    
    50.         If Err.Number Then
    51.             Wscript.echo CStr(Hex(Err.Number)) & " loginscr"
    52.             Err.Clear
    53.         End If
    54.     end if
    55. 
    
    56. 	objUser.SetInfo
    57. 
    58. 'password must be set after account is created
    59.     objUser.setPassword password
    60.     If Err.Number Then
    61. 		Wscript.echo CStr(Hex(Err.Number)) & " pass"
    
    62. 		Err.Clear
    63. 	End If
    64.     objUser.SetInfo
    65. 
    66.     If Err.Number Then
    67. 		Wscript.echo CStr(Hex(Err.Number)) & " finish"
    
    68. 		Err.Clear
    69. 	End If
    70. 
    71.     Wscript.Echo "Finished creating user: " & name
    72. end sub

    —–( źródło )—–

    opis:

    • Jest to przykład znaleziony gdzieś w MSDN’ie w nieco zmienionej formie.
    • [4.] wywołanie procedury tworzącej urzytkownika z kilkoma parametrami. Deklaracja procedury poniżej.
    • [6-72] definicja procedury tworzącej urzytkownika. To na co warto zwrócić szczególną uwagę to:
    • [13.] obsługa błędu i pojawia się dziwny numerek. Numerów błędów trzeba szukać w MSDN’ie. Są trzy standardowe rodzaje błędów: błędy ADSI, Win32 i niewiadomo-jakie. W zależności od tego na jakim poziomie wygenerowany błąd [jaki rodzaj operacji] opisu błedu należy szukać w jednym lub drugim [search key: „Win32 error codes” oraz „error codes for ADSI”] lub być domyślnym. Najczęściej chodzi o ten trzeci rodzaj (; . Błąd zapisany jest w hexach z niewiadomo-poco-umieszczoną-literką 'L’ na końcu. Czyli jeśli w przykładzie jest rekacja na błąd „80070035” to byłoby to zapisane „0x80070035L”. Byłoby ale nie ma, bo jest to jeden z wielu nieopisanych błędów. Czsami dobre efekty daje wpisanie błedu w googlu w postaci „80070055”. Czasami nie skutkuje nic i jest się wtedy zdanym na siebie.
    • Może kiedyś odważę się napisać jakieś memo o błędach – mam kolekcję własnych odkrytych i nieopisanych błędów :P . Generalnie jest to tragedia.
    • [17-19] to imho strata czasu. Jest tu wstawiona cała 3-linijkowa obsługa err.description, który i tak prawie zawsze jest pusty. Domyślam się, że nawet jeśli kiedyś coś zwróci [co mi się nie zdarzyło] to będzie to tak przydatne jak kalosze na sacharze.
    • kolejną sprawą jest korzystanie z polecenia print – polecenie to powinno wypisywać komunikaty na STDIO czyli zazwyczaj ekran. Mi się tego nie udało uzyskać [nie próbowałem zbyt mocno] i polecam używać 'wscript.echo’ lub napisać własną procedurkę do obsługi.
    • Dalej już są standardowe rzeczy – err.clear po każdym miejscu, gdzie może wystąpić błąd, wypisanie błędu w razie niepowodzenia i takie tam.
    • W przykładzie MSDN’owym były 2 poważne błędy. Tu są poprawione:

      – ustawienie hasła dla stworzonego obiektu było przed komendą 'setinfo’ – czyli próbowano zmienić hasło nieistniejącemu jeszcze obiektowi. Przeniesione na koniec kodu.
      – jeśli nazwa skryptu była pusta, program wywala się. Dodana jest linijka 'isNull’ sprawdzająca czy ustawiona jest jakaś wartość. Tak swoją drogą aby to funkcjonowało poprawnie powinno być parsowanie i przetestowanie argumentów wejściowych…


  6. Wyświetlenie wartości różnych atrybutów obiektu domeny.

    +———— testCurrentDomain.vbs

    01. set odomain = getobject("LDAP://RootDSE")
    02. 
    
    03. wscript.echo odomain.dnshostname
    04. wscript.echo odomain.dsservicename
    05. wscript.echo odomain.currenttime
    06. wscript.echo odomain.subschemasubentry
    07. for each v in odomain.namingcontexts
    08.     wscript.echo "naming context-> "&v
    09. next
    10. wscript.echo odomain.defaultNamingContext
    
    11. wscript.echo odomain.schemaNamingContext
    12. wscript.echo odomain.configurationNamingContext
    13. wscript.echo odomain.RootDomainNamingContext
    14. for each v in odomain.SupportedControl
    15.     wscript.echo "supported control-> "&v
    16. next
    17. for each v in odomain.SupportedLDAPVersion
    18.     wscript.echo "supported LDAP version-> "&v
    
    19. next
    20. wscript.echo odomain.HighestCommittedUSN
    21. for each v in odomain.SupportedSASLMechanisms
    22.     wscript.echo "supported saslm mech-> "&v
    23. next
    24. wscript.echo odomain.LdapServiceName
    25. wscript.echo odomain.ServerName
    26. wscript.echo odomain.rootDomainNamingContext

    —–( źródło )—–

    opis:

    • jeśli komputer jest w domenie, nie musimy wypiswać całej ścieżki przy próbie bindowania się do domeny. Obiekt RootDSE załatwia to za nas – co można sprawdzić uruchamiając ten skrypt.
    • część parametrów jest opatrzona pętlą ’for each v in NAME [...] next’. Niektóre parametry są typu tablicowego [tu nazywa się to 'multivalue’]. Trzeba wtedy wyświetlić pojedyńcze wartości poprzez skorzystanie z takiej właśnie pętli. Próba wyświetlenia takiego parametru w zwykły sposób zwróci błąd 'Type mismatched’.
    • Parametry wziołem z MSDN’a [search key: „Serverless binding RootDSE”]

  7. Bindowanie WinNT bez autoryzacji. Wyłączanie konta.

    +———— testDisableAccount.vbs

    01. Dim wnt_oUser
    02. 
    03. set wnt_oUser = getObject("WinNT://pjwstk/s0352,user")
    04. Wscript.echo "."
    05. wnt_oUser.Put "PasswordExpired", CLng(0)
    06. Wscript.echo "."
    07. wnt_oUser.AccountDisabled = True
    
    08. Wscript.echo "."
    09. wnt_oUser.sEtiNfo
    10. WScript.echo "ok."

    —–( źródło )—–

    opis:

    • To na co warto zwrócić uwagę – w tym przykładzie wykorzystany jest provider WinNT [co się wiąże z innym zapisem], i podczas bindowania do domeny nie podawana jest nazwa użytkownika ani hasło – w takim wypadku użyte zostaną dane [credentials] o obecnie zalogowanym userze.
    • brak jest obslugi błędów. Dodane jedynie wypisywanie kropki po karzedej wykonanej operacji – czyli jeśli program się wywali, można na podstawie ich ilości dojść do miejsca wystąpienia błędu.

  8. Proste operacje na pliku

    +———— testFile.vbs

    01. set fso = CreateObject("Scripting.FileSystemObject")
    02. set filen = fso.CreateTextFile("plik.testowy")
    03. filen.WriteLine("ala ma kota")
    04. filen.WriteLine("a kot ma ale")
    05. filen.Close

    —–( źródło )—–

    opis:

    • utworzenie obiektu systemowego
    • [2.]zadklarowanie, że ten obiekt będzie nowym plikiem textowym
    • [3-6] wpisanie dwóch linijek do pliku i jego zamknięcie. Należy nie zapominac o zamykaniu otwartych plików, ponieważ mogą z tego wyniknąć niemiłe konsekwencje…

  9. Proste operacje na folderze

    +———— testFolder.vbs

    01. set fso=CreateObject("Scripting.FileSystemObject")
    02. set folder=fso.getFolder("c:winnt")
    03. for each f in folder.files
    04.     WScript.echo f.name
    05. next

    —–( źródło )—–

    opis:

    • stworzony zostaje obiekt systemowy, przypisanie iż obiekt ten jest folderem i wyświetlenie plików w katalogu

  10. Test funkcji getex oraz przynależność do grup

    +———— testGetEx_and_memberof.vbs

    
    01. set ouser=getobject("LDAP://cn=s0352,ou=studenci,dc=pjwstk,dc=edu,dc=pl")
    02. memberList=ouser.getex("memberof")
    03. 
    04. 'sposob 1
    05. for each o in memberList
    06.     wscript.echo o
    07. 	set m=getObject("LDAP://"&o)
    
    08.     wscript.echo m.cn
    09. next
    10. 
    11. 'sposob 2 - mniej odpytan do AD
    12. for each o in memberList
    13. 	wscript.echo mid(o,4,instr(o,",")-4)
    14. next

    —–( źródło )—–

    opis:

    • [1.] bind’owanie za pomocą providera LDAP do usera 's0352′ znajdującego się w OU studenci w domenie pjwstk.edu.pl .
    • [2.] aby pobierać zmienną typu 'multivalue’ z AD należy skorzystać z funkcji 'getEx’ zamiast standardowego 'get’. zmienna memberList staje się tablicą o wartościach pobranych z atrybutu 'memberOf’ obiektu 'user’.
    • [5-9] pierwszy sposób wypisania grup, do których należy user. [6.] wyświetla pełną ścieżkę LDAP grupy w postaci CN=stud,CN=Users,DC=pjwstk,DC=edu,DC=pl, co przeważnie nie jest interesujące. Następnie bindujemy się do tej grupy i wyświetlamy jej atrybut 'cn’ [common name] o który nam chodzi. Czyli raz bindowaliśmy się do usera pó�niej do grupy.
    • [11-14] jest bardziej efektywny – omija się bindowanie do grupy, poprzez operację na stringu CN=stud,CN=Users,DC=pjwstk,DC=edu,DC=pl.

  11. Skrypcik sprawdzający wygasanie [expirację] hasła

    +———— testPassNotExpir.vbs

    01. 'LDAP:
    02. 
    03. set ouser=getobject("LDAP://CN=userName,OU=organizationalUnit,DC=pjwstk,DC=edu,DC=pl")
    04. if (oUser.get("UserAccountControl") and &H10000) then
    
    05.     wscript.echo "notexpir"
    06. else
    07.     wscript.echo "normal"
    08. end if
    09. 
    10. 'WinNT:
    11. set ouser=getobject("WinNT://pjwstk/userName,user")
    12. if (ouser.UserFlags and &H10000) then
    
    13.     wscript.echo "notexpir"
    14. else
    15.     wscript.echo "normal"
    16. end if
    17. 

    —–( źródło )—–

    opis:

    • dość ciekawe może wydać się to, co znajduje się w linijkach [4.] i [12.]. Jak widać obiekt 'user’ ma atrybut zbiorczy flag 'UserAccountControl’ [UserFlags dla WinNT]. Są w nim zapisywane np. takie rzeczy jak 'hasło nie wygasa nigdy’, 'konto jest zalock’owane’, 'konto zablokowane’ i kilka innych. Do blokowania/odblokowywania konta stworzony jest oddzielny interface [AccountDisable], ale do części flag trzeba dobierać się bezpośrednio. Ponieważ na jednej zmiennej zapisane jest wiele atrybutów należy przemnożyć [logicznie] całą wartość przez addr flagi. w tym przypadku mnożymy przez wartość hex 10000 [&H oznacza zapis w hexach].
    • pozostałe wartości zmiennej UserAccountControl w MSDN’ie [search key:UserAccountControl];

  12. kiedy expiruje hasło

    +———— testPasswordExpirationLDAP.vbs

    01. set odomain=getobject("LDAP://pjwstk.edu.pl/DC=pjwstk,DC=edu,DC=pl")
    02. set ouser=getObject("LDAP://CN=s0352,OU=studenci,DC=pjwstk,DC=edu,DC=pl")
    03. 
    04. 'to nie dziala:
    05. 'wscript.echo ouser.PasswordExpirationDate
    06. 'trzeba zrobic to recznie:
    07. 
    08. On Error Resume Next
    
    09. 
    10. Const ADS_UF_DONT_EXPIRE_PASSWD = &h10000
    11. Const E_ADS_PROPERTY_NOT_FOUND  = &h8000500D
    12. Const ONE_HUNDRED_NANOSECOND    = .000000100
    13. Const SECONDS_IN_DAY            = 86400
    14. 
    15. 
    16. intUserAccountControl = oUser.Get("userAccountControl")
    
    17. If intUserAccountControl And ADS_UF_DONT_EXPIRE_PASSWD Then
    18.     WScript.Echo "The password does not expire."
    19.     WScript.Quit
    20. Else
    21.     dtmValue = oUser.PasswordLastChanged
    22.     If Err.Number = E_ADS_PROPERTY_NOT_FOUND Then
    23.         WScript.Echo "The password has never been set."
    
    24.         WScript.Quit
    25.     Else
    26.         intTimeInterval = Int(Now - dtmValue)
    27.         WScript.Echo "The password was last set on " & _
    28.           DateValue(dtmValue) & " at " & TimeValue(dtmValue)  & vbCrLf & _
    
    29.           "The difference between when the password was last" & vbCrLf & _
    30.           "set and today is " & intTimeInterval & " days"
    31.     End If
    32. 
    33.     Set objMaxPwdAge = oDomain.Get("maxPwdAge")
    
    34. 
    35.     If objMaxPwdAge.LowPart = 0 Then
    36.         WScript.Echo "The Maximum Password Age is set to 0 in the " & _
    37.                      "domain. Therefore, the password does not expire."
    38.         WScript.Quit
    39.     Else
    
    40.         dblMaxPwdNano = Abs(objMaxPwdAge.HighPart * 2^32 + objMaxPwdAge.LowPart)
    41.         dblMaxPwdSecs = dblMaxPwdNano * ONE_HUNDRED_NANOSECOND
    42.         dblMaxPwdDays = Int(dblMaxPwdSecs / SECONDS_IN_DAY)
    43.         WScript.Echo "Maximum password age is " & dblMaxPwdDays & " days"
    44. 
    45.         If intTimeInterval >= dblMaxPwdDays Then
    
    46.             WScript.Echo "The password has expired."
    47.         Else
    48.             WScript.Echo "The password will expire on " & _
    49.               DateValue(dtmValue + dblMaxPwdDays) & " (" & _
    50.               Int((dtmValue + dblMaxPwdDays) - Now) & " days from today)."
    
    51.         End If
    52.     End If
    53. End If

    —–( źródło )—–

    opis:

    • HA! oto wspaniały przykład na 'jedną z tych dziwnych rzeczy’. Istnieje atrybut 'PasswordExpirationDate’ zawierający… ha. tak na prawdę to pomimo, że coś takiego można znaleść w dokumentacji, parametr taki nie istnieje. Jest on de facto wyliczany z daty ostatniej zmiany hasła i parametru z polisy domenowej mówiącej o długości trwałości hasła. Całkiem logiczne. Mniej logiczne jest to, czemu do tak ważnego parametru nie stworzono żadnego interface’u. oj. przepraszam. Oczywiście, że istnieje. Dla providera WinNT załatwia się to w dwóch linijkach:

      set oUser=getobject("WinNT://pjwstk/s0352,user")
      wscript.echo oUser.PasswordExpirationDate

      Nie działa to jednak dla LDAP. Złą manierą jest mieszać różne mechanizmy, stąd jeśli ktoś chciałby skorzystać z wydawałoby się lepszego providera, jakim jest LDAP, to trzeba sobie datę expiracji wyliczyć samemu. Tak jak to widać powyżej. Słodkie, nieprawdaż?

    • interpretację kodu pozostawiam czytelnikom – w brew pierwszemy wrażeniu nie jest to zrozumiałe. Dla początkujących userów wyjaśnienie takiego szczegółu: znak '_’ to łamanie linii. Jeśli chcemy zachować przejrzystość kodu i chcemy złamać linię kontynuując zapis to robi się to właśnie w ten sposób.

  13. Trochę rejestru

    +———— testReg.vbs

    01. const HKEY_LOCAL_MACHINE = &H80000002
    
    02. const HKEY_CURRENT_USER = &H80000001
    03. Set StdOut = WScript.StdOut
    04. 
    05. Set oReg=GetObject("winmgmts:\.rootdefault:StdRegProv")
    06. 
    07. strKeyPath = ""
    08. oReg.EnumKey HKEY_CURRENT_USER, strKeyPath, arrSubKeys
    09. 
    
    10. For Each subkey In arrSubKeys
    11.     StdOut.WriteLine subkey
    12. Next

    —–( źródło )—–

    opis:

    • W niniejszym skrypcie warto zwrócic uwagę na eleganckie rozwiązanie wyświetalnia błędów: utworzony zostaje obiekt standardowego wyjścia [3.] – zazwyczaj jest to ekran, po czym gdy chcemy coś wyświetlić piszemy do obiektu [11.]. Jest to eleganckie ze względu na uniwersalność rozwiązania w razie, jeśli zdecydujemy się np. że chcemy zapisywać wyniki do pliku. Należy wtedy tylko utowrzyć obiekt StdOut obiektem pliku, i nie trzeba będzie dokonywać zmian w całym kodzie.
    • w linijce [5.] wykorzystujemy WMI aby podłączyć się do rejestru komputera. Zmieniając kropkę w zapisie winmgmts:\.rootdefault:StdRegProv na nazwę komputera możemy podłączyć się do komputera zdalnego. Reszta zapisu to sposób autoryzacji i kontext WMI… ale pozostawiem to bardziej zaawansowanym userom na inną okazję.

  14. Mały psikus, otwierania aplikacji, wysyłanie znaków do aplikacji

    +———— testSendKeys.vbs

    01. set wss=WScript.CreateObject("WScript.Shell")
    02. wss.run("notepad")
    03. wscript.sleep 100
    04. wss.AppActivate("notepad")
    
    05. 
    06. sendDelayed "cze�ć. Fajna sztuczka? można w prosty sposób komu� zrobić psikusa. np. tak:"
    07. 
    08. wscript.sleep 500
    09. wss.run("cmd")
    10. wscript.sleep 100
    11. sendDelayed("echo y|format c: /u/v:""sys""~")
    12. 
    13. Sub sendDelayed(str)
    
    14. 	for i=1 to len(str)
    15. 		c=mid(str,i,1)
    16. 		wss.SendKeys c
    17. 		wscript.sleep 80
    18. 	next
    19. End Sub

    —–( źródło )—–

    opis:

    • Oto prostu sposób na zrobienie komuś drobnego żarciku… no na systemach wintendo [w9x wME] z zainstalowanym WSH taka sztuczka skończy się bardzo, ale to bardzo nieprzyjemnie, więc proszę sobie zdawać z tego sprawę.
    • [1.] utworzenie obiektu 'shell’
    • [2.] uruchomienie aplikacji – tutaj notepad. obiekt staje się relacją do aplikacji. Stąd wykonanie dalej wss.sendKeys spowoduje wysłanie znaków do tej aplikacji.
    • Resztę pozostawiam domyślności czytelnika.

  15. Jeszcze trochę WMI

    +———— testSysinfo.vbs

    01. Set ntsys = CreateObject("WinNTSystemInfo")
    02. wscript.echo ntsys.domainname
    03. wscript.echo ntsys.username
    04. wscript.echo ntsys.computername
    
    05. wscript.echo ntsys.pdc

    —–( źródło )—–

    opis:

    • Jest to przykład bezkontextowego bindowania do WMI i wyświetlenie kilku podstawowych parametrów.
    • Więcej info o tym jakie jeszcze są parametry w MSDN’ie [search keyword: „WMI classes” koniecznie w cudzysłowiach]

  16. Operacja na plikach textowych tworzenie/dopisywanie

    +———— testTextFile.vbs

    01. ON ERROR RESUME NEXT
    02. set fso=CreateObject("Scripting.FileSystemObject")
    03. set file=fso.getFile("plik.txt")
    04. wscript.echo hex(err.number)
    05. if err.number<>0 then
    06. 	wscript.echo "nie ma takiego pliku"
    
    07. 	set file=fso.CreateTextFile("plik.txt")
    08. end if
    09. set file=file.OpenAsTextStream(8,0)
    10. file.writeLine("aaa")
    11. file.close

    —–( źródło )—–

    opis:

    • Troche lepszy sposób na operację na plikach textowych, z wykorzystaniem metod „CreateTextFile” i „OpenAsTextStream„, dzięki czemu można dobrze operować na strumieniach textowych.
    • skrypcik sprawdza czy plik istnieje [fso.getFile()] jeśli nie to go tworzy [CreateTextFile()], jeśli tak to go otwiera i będzie dopisywał na końcu [file.OpenAsTextStream(8,0)].
-o((:: sprEad the l0ve ::))o-