Ok, so I’ve not posted anything for a few days and I felt the need to throw a brief technical post up with a code snippet from a current project I’m working on. I’m building a health check logon script and as part of that framework I wanted to build a logging object. Since the target format has to be vbscript for what I’m doing, I’ve built it as such, and in a format that views nicely inside of trace32 and trace64.
The idea was to build an object that would perform a simple task, write a log file…. then write a log file, or an event, then write only error events, but could also buffer and dump a final error or success log as a split log to another remote location. All configurable via properties, but with only two exposed methods to control it all (write & writeremote). This object is instantiated by:
Dim Logging
Set Logging = New cls_Logging
Call Logging.Write("my message",1)
Wscript.Quit(0)
Simple enough, no? It’s also worth mentioning I wrote the code so that a constant could be set within the instantiating script of DEBUGMODE and if TRUE it will error, else suppresses all error output.
Here’s the code:
'=================================================================================
'Logging Class ===================================================================
'=================================================================================
'Not required for WSF, but is when in standard VBS
Const ForAppending = 8
'Log and Event writer object
Class cls_Logging
'Class for logging to file and event viewer
Private oWShell,oNet,oFSo,Filehandle,rFilehandle
Private fPath,strRFPath,fMaxSize,fLogname,strRemoteErr,BoolEvent,BoolRemote,oDict
Private Sub Class_Initialize()
'Object Init subroutine
If Debugmode Then On Error Goto 0 Else On Error Resume Next
Set oWShell = CreateObject("Wscript.Shell")
Set oNet = CreateObject("Wscript.Network")
Set oFSo = CreateObject("Scripting.FileSystemObject")
Set oDict = CreateObject("Scripting.Dictionary")
LogEvent = False
RemoteLog = False
Path = Left(WScript.ScriptFullName,(Len(WScript.ScriptFullName)_
-Len(WScript.ScriptName)))
File = LCase(oNet.ComputerName)
MaxSize = 2
End Sub
'---------------------------------------------------------
Private Sub Class_Terminate()
'Object Termination subroutine
If Debugmode Then On Error Goto 0 Else On Error Resume Next
If bOpen Then
Filehandle.close
End If
Set oWShell = Nothing
Set oNet = Nothing
Set oFSo = Nothing
Set Filehandle = Nothing
Set fPath = Nothing
Set fMaxSize = Nothing
Set fLogname = Nothing
Set BoolEvent = Nothing
End Sub
'---------------------------------------------------------
'File name properties, for changing and retrieving the log file name
Public Property Let File(strFile)
If Debugmode Then On Error Goto 0 Else On Error Resume Next
If (InStr(StrReverse(strFile),"gol.")) <> 0 Then
fLogname = strFile
Else
fLogname = strFile & ".log"
End If
End Property
Public Property Get File()
If Debugmode Then On Error Goto 0 Else On Error Resume Next
File = fLogname
End Property
'---------------------------------------------------------
'Path name properties, for changing and retrieving the path to logs
Public Property Let Path(strPath)
If Debugmode Then On Error Goto 0 Else On Error Resume Next
If (InStr(StrReverse(strpath),"\")) <> 1 Then
fPath = strPath & "\"
Else
fPath = strPath
End If
End Property
Public Property Get Path()
If Debugmode Then On Error Goto 0 Else On Error Resume Next
Path = fPath
End Property
'---------------------------------------------------------
'Fully concatenated file name property for retrival.
Public Property Get FullFileName()
FullFileName = Path & File
End Property
'---------------------------------------------------------
'Property for setting maximum file size of log file
Public Property Let MaxSize(strVal)
If Debugmode Then On Error Goto 0 Else On Error Resume Next
fMaxSize = Cint(strVal) * 1048576
End Property
Public Property Get MaxSize()
If Debugmode Then On Error Goto 0 Else On Error Resume Next
MaxSize = fMaxSize
End Property
'---------------------------------------------------------
'Boolean property to determine if the filehandle is in use
Private Property Get bOpen()
If Debugmode Then On Error Goto 0 Else On Error Resume Next
If IsObject(Filehandle) Then
bOpen = True
Else
bOpen = False
End If
End Property
'---------------------------------------------------------
Public Property Let LogEvent( blValue)
'Bool property that dictates event viewer rights
BoolEvent = blValue
End Property
Private Property Get LogEvent()
LogEvent = BoolEvent
End Property
Public Property Let RemoteLog( blValue)
'Bool property that dictates if logging occurs to remote location
BoolRemote = blValue
End Property
Private Property Get RemoteLog()
RemoteLog = BoolRemote
End Property
Public Property Let RemotePath( strPath)
If (InStr(StrReverse(strpath),"\")) <> 1 Then
strRFPath = strPath & "\"
Else
strRFPath = strPath
End If
End Property
Public Property Get RemotePath()
RemotePath = strRFPath
End Property
'---------------------------------------------------------
Private Sub RemoteErrBuffer( strKey, strItem)
'Method to concactenate new items under one key at the end of the string
If Debugmode Then On Error Goto 0 Else On Error Resume Next
Dim concat
If Not oDict.Exists(strKey) Then
Call oDict.Add(strkey, stritem)
Else
concat = oDict.Item(strKey)
concat = concat & "|:|" & strItem
oDict.Remove(strKey)
Call oDict.Add(strKey,concat)
End If
End Sub
'---------------------------------------------------------
Public Function ErrBuffer()
'Method to return contents of the error buffer
If Debugmode Then On Error Goto 0 Else On Error Resume Next
Dim ItemToSplit, ItemArray, item
ItemToSplit = oDict.item("remotelog")
ItemArray = Split(ItemToSplit, "|:|")
ErrBuffer = ItemArray
End Function
'---------------------------------------------------------
Public Sub WriteRemote(strVal)
If Debugmode Then On Error Goto 0 Else On Error Resume Next
If Not CreateRemote Then
Exit Sub
End If
rFilehandle.WriteLine strVal
End Sub
'---------------------------------------------------------
'Subroutine for creating the remote log file and instantiating the handle
Private Function CreateRemote()
If Debugmode Then On Error Goto 0 Else On Error Resume Next
Dim FileProperty,Logsize
CreateRemote = False
If Not oFso.FolderExists(RemotePath) Then
Call Write(RemotePath & " Does not exist, or is unreachable.",3)
Exit Function
End If
If Not oFSo.FileExists(RemotePath & File) Then
oFso.CreateTextFile(RemotePath & File)
Else
oFSo.DeleteFile(RemotePath & File)
oFso.CreateTextFile(RemotePath & File)
End If
If Not IsObject(rFilehandle) Then
Set rFileHandle = oFSo.OpenTextFile(RemotePath & File, _
ForAppending, True)
End If
If oFSo.FolderExists(RemotePath) Then
CreateRemote = True
End If
End Function
'---------------------------------------------------------
'Subroutine for writing log entries
Public Function Write( msg, mtype)
If Debugmode Then On Error Goto 0 Else On Error Resume Next
Dim msgline, etype
Call Create()
If Not bOpen Then
Call Create()
End If
msgline = "<![LOG["&msg&"]LOG]!><time="&""""&DatePart("h",Time) _
&":"&DatePart("n",Time)&":"&DatePart("s",Time)&".000+0"""&" date=""" _
&Replace(Date,"/","-")&""""&" component="""&Left(WScript.ScriptName, _
Len(WScript.ScriptName)-Len(".vbs"))&""" context="""" type="""&mtype _
&""" thread="""" file="""&Left(WScript.ScriptName,Len(WScript.ScriptName)_
-Len(".vbs"))& """>"
Filehandle.WriteLine msgline
Select Case Mtype
Case 1
etype = 0
Case 2
etype = 2
If LogEvent Then
oWShell.LogEvent etype, msg
End If
Call RemoteErrBuffer("remotelog", msg & "," & "2")
Case Else
etype = 1
If LogEvent Then
oWShell.LogEvent etype, msg
End If
Call RemoteErrBuffer("remotelog", msg & "," & "1")
End Select
End Function
'---------------------------------------------------------
'Subroutine for rolling over log file at file size limit
Private Sub Rollover()
If Debugmode Then On Error Goto 0 Else On Error Resume Next
If bOpen Then
Filehandle.Close
End If
oFso.CopyFile FullFileName, Left(FullFileName,(Len(FullFileName)-1)), True
oFSo.DeleteFile FullFileName
Set FileHandle = oFSo.OpenTextFile(FullFileName, ForAppending, True)
End Sub
'---------------------------------------------------------
'Subroutine for creating the log file and instantiating the handle
Private Sub Create()
If Debugmode Then On Error Goto 0 Else On Error Resume Next
Dim FileProperty,Logsize
If Not oFSo.FileExists(FullFileName) Then
oFSo.CreateTextFile(FullFileName)
End If
If Not bOpen Then
Set FileHandle = oFSo.OpenTextFile(FullFileName, ForAppending, True)
End if
Set FileProperty = oFSo.GetFile(FullFileName)
Logsize = FileProperty.size
If Logsize > MaxSize Then
Filehandle.WriteLine "\\\\\\\\\\File Size Reached//////////"
Call Rollover()
End If
End Sub
End Class
I built a scripting dictionary wrapper as well which was inspired by work from Dan Thomson in his health check script. I’ll most likely post it next after I feel it’s complete.
If you found this object helpful, or otherwise, I would appreciate it if you rated it on script center.