Archiv pro štítek: vbscript

Windows 8 – formát data a času

V souvislosti s přechodem z Windows Vista na Windows 8 jsem dnes převáděl jednoduchý skript (VBScript), který používal příkazy pro převod textového řetězce na datum:

tLimit= DateValue("26.7.2012")

Skript ve Windows hlásil chybu:

C:\scripts\zmnt.vbs(14, 1) Microsoft VBScript runtime error: Type mismatch: 'DateValue'

Ukázalo se, že ve Windows 8 je v systému časový údaj správně a korektně pro české prostředí s mezerami za každou tečkou, takže oprava byla jednoduchá, do všech textových řetězců v datech jsem ve skriptu doplnil mezery:

tLimit= DateValue("26. 7. 2012")

Jde o formát nastavení Short date na panelu Control Panel | Region | Formats, skutečně jsou tam mezery. Pro kontrolu jsem se ještě jednou podíval na jeden další počítač (Windows 7) a tam je datumový formát také bez mezer („špatně“). Ve Windows 8 je tedy „konečně“ ve výchozím stavu formát zápisu správně:

VBScript: e-mail s kódováním utf-8

CDOsys.dll lze použít ve skriptech VBS k posílání zpráv prostřednictvím připojení k SMTP serveru. Ve skriptu lze zadat konfiguraci zprávy, hlavičku, formát (text, html) nebo i zakomponovat jako přílohu libovolný soubor. Ve výchozím nastavení používá tato metoda kódování Latin 1 (ISO-8859-1) a české znaky jsou tedy komoleny. Ověřil jsem následující konfiguraci, která správně zachová česká písmenka:

Set Msg = Createobject("CDO.Message")
Msg.To = "prijemce@mail.net"
Msg.Cc = ""
Msg.From = "odeslal@mail.net"
Msg.Subject = "nova zprava"
Msg.Textbody = "text zprávy" + vbCrLf + "další řádky zprávy"
Msg.Configuration.Fields("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
Msg.Configuration.Fields("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "SMTPserver.domain.cz"
Msg.BodyPart.Charset = "UTF-8"
Msg.Configuration.Fields.Update
Msg.Send
Set Msg = Nothing

ACS: list connected forwarders (VBScript)

Klientská část (agent) systému Operations Manager se skládá ze dvou neoddělitelných komponent, agent + acs forwarder. Druhá komponenta není ve výchozím stavu po instalaci agenta aktivována, tento krok musí zařídit správce systému.

Data jsou odesílána na server (role ACS Collector), který si zároveň řídí agenty – to například znamená, pokud nestíhá kolektor zpracovávat přijímaná data, dočasně začne pozastavovat příjem od některých agentů. Jakmile nápor pomine, agenty opět připojí a data postupně přijme a zpracuje. Agenty lze seskupit a pro jednotlivé skupiny stanovit různé priority, čímž zajistíme „přednostní“ zpracování záznamů třeba ze skupiny Domain Controllers (servery z této skupiny budou odpojeny ve výjimečných případech, jako poslední).

SCOM samotný informuje pouze o funkci (zdraví) forwarderu, nikoliv o aktivním připojení. K tomu musíme použít nástroj příkazové řádky AdtAdmin s parametrem /Stats. Výstup můžeme přesměrovat do souboru (stats.csv) a přehledně zobrazit v tabulce (MS Excel). Soubor nám vedle statistik pro jednotlivé servery také poskytuje informaci o aktivním připojení agenta (spojení forwarder – collector).

Následující skript VBS a příkazovou dávku CMD můžeme na management serveru ACS kolektoru použít jako Task nebo volat nezávisle, bez konzoly Operations Manager.
CMD

@echo off
echo.
echo WRITING ACTUAL STATUS (TXT FILE)
c:\windows\system32\security\adtserver\adtadmin -stats > Actual_Status.txt
cscript PARSER_STATS.VBS
echo.
echo CONNECTED FORWARDERS ARE:
type Connected_Forwarders.txt
echo -----------------------------------------------------
echo DISCONNECTED FORWARDERS ARE:
type disConnected_Forwarders.txt
echo -----------------------------------------------------

VBS – skript přehledně (lidsky čitelně) vypíše statistiku pro jednotlivé servery a nakonec dva seznamy podle stavu Připojen / Nepřipojen

Const ForReading = 1, ForWriting = 2, ForAppending = 8
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTxtFR = objFSO.OpenTextFile("Actual_Status.TXT", ForReading)
Set objTxtFW = objFSO.OpenTextFile("Connected_forwarders.TXT", ForWriting, True)
Set objTxtFWnot = objFSO.OpenTextFile("disConnected_forwarders.TXT", ForWriting, True)
'
' first line is Header
arrRecord = objTxtFR.Readline

i=1
Do While objTxtFR.AtEndOfStream <> True
arrRecord = split(objTxtFR.Readline, ",",-1)
wscript.echo " "
wscript.echo "Value: " & arrRecord(0)
wscript.echo "SID: " & arrRecord(1)
wscript.echo "Name: " & arrRecord(2)
wscript.echo "GrupID: " & arrRecord(3)
wscript.echo "Version: " & arrRecord(4)
wscript.echo "Connected: " & arrRecord(5)
wscript.echo "Total Transmitted Events: " & arrRecord(6)
wscript.echo "Total Size of Transmitted Events: " & arrRecord(7)
wscript.echo "Recv Packet Count: " & arrRecord(8)
wscript.echo "Recv Packet Size: " & arrRecord(9)
wscript.echo "Seconds Since Connection: " & arrRecord(10)
wscript.echo "Average Event Rate: " & arrRecord(11)
wscript.echo "Current Event Rate: " & arrRecord(12)
wscript.echo "Average time to collector(in ms): " & arrRecord(13)
wscript.echo "Connect Time: " & arrRecord(14)
wscript.echo "Last Action: " & arrRecord(15)
wscript.echo "Disconnect Time: " & arrRecord(16)
wscript.echo "---------------------------------------------------- " & i
If arrRecord(5) > 0 Then
objTxtFW.WriteLine(arrRecord(2))
Else
objTxtFWnot.WriteLine(arrRecord(2))
End If
i = i + 1
Loop

Přepočet času UTC na aktuální místní čas CET nebo letní CEST

Údaje o čase jsou v databázích SCOMu zapisované ve světovém univerzálním čase UTC, výjimkou je databáze OperationsManagerAC, která může časové údaje zaznamenávat buď ve formátu UTC nebo při instalaci zvolíme místní časové pásmo CET (tj. UTC+1). To je výhodné, pokud jsou v databázi všechny záznamy od serverů z jednoho časového pásma. Druhou výhodou je, že se nemusíme starat o změny při přechodu na letní čas a zpět.

CET   ->   CEST   ->   CET
nebo (UTC + 1   ->   UTC + 2   ->   UTC + 1)

V reportech, které vytvářím pomocí Visual Studia (SQL Server Bussines Inteligence Development Studio) můžeme zajistit ve výstupu přepočet časových údajů na aktuální čas našeho pásma CET (central european time, UTC+1) i v době platnosti letního času CEST (central european summer time, UTC+2) použitím kódu Visual Basic. Po zjištění aktuálního času v UTC je skriptem přidána jedna hodina nebo dvě hodiny v době platnosti letního času:


PublicFunction DateTimeUTC2Local(ByVal od As String) As Date 

Dim offset, i As Integer
Dim startDST, endDST As Date
Dim nd As String
offset = 1
' find last Sunday in March
For i = 31 To 25 Step -1
  If Weekday( "3/" & i & "/" & Year(od)) = 1 Then
    startDST = DateAdd("h", 1, CDate("3/" & i & "/" & Year(od)))
    Exit For
  End If
Next
' find last Sunday in October
For i = 31 To 25 Step -1
  If Weekday( "10/" & i & "/" & Year(od)) = 1 Then
    endDST = DateAdd("h", 1, CDate("10/" & i & "/" & Year(od)))
    Exit For
  End If
Next
' add hour to offset if within DST
If CDate(od) >= startDST And CDate(od) < endDST Then
  offset = offset + 1
End If
nd = DateAdd("h", offset, od)
Return nd
End Function

Použití kódu VBS v nástroji SQL Server Bussines Inteligence Development Studio:

Pokračujeme konfigurací z nabídky Report | Report Properties. Zde na záložce General vyplníme popis reportu (autor, popis). Na záložce Code vložíme kód, který použijeme při přepočítávání časového údaje:

Pro použití kódu v reportu, v poli které z databáze vybere čas ve formátu UTC, vypočítáme platný místní čas CET / CEST takto:
například čas, získaný dotazem z databáze OperationsManager ve sloupci Alert.TimeRaised – ve výstupním formuláři použijeme v příslušném sloupci následující výraz pro výpočet (Expression) s uvedením výše definované funkce:
=Code.DateTimeUTC2Local(Fields!TimeRaised.Value)


ReportBuilder

Potřebujeme-li podobnou funkčnost reportu zajistit také z editačního prostředí nástroje ReportBuilder, nemůžeme použít vlastní kód (alespoň mi to není známo – použití ReportBuilderu verze 2.0 a 3.0 jsem ještě nezkoumal).

Kód musíme napsat přímo do formátovacího pole, implementace výše uvedeného algoritmu by byla příliš složitá, proto postupuji takto:

  1. zjistím datum přechodu na letní čas a zpět pro aktuální období pro data v databázi,
  2. v příslušném sloupci při vytváření vzorce pro výpočet uvedu vzorec.
    Příklad: vstupní čas (LogonTime) je ve formátu UTC,
    přechod z letního času CEST na standardní CET je poslední neděli v říjnu v 1:00 hodin UTC,
    přechod na letní času CEST ze standardního CET je poslední neděli v březnu ve 3:00 hodin UTC, definice výrazu je tedy pro současné období:

 


IF(LogonTime < DATETIME(2010;10;31;1;0;0);
   DATEADD(HOUR;2;LogonTime); //přidat 2 hodiny, letní čas CEST
   IF(LogonTime < DATETIME(2011;3;27;1;0;0);
      DATEADD(HOUR;1;LogonTime); //přidat 1 hodiny, standardní čas CET
      DATEADD(HOUR;2;LogonTime) //přidat 2 hodiny, letní čas CEST
   )
)