Skip navigation

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.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.