An error free log looks like this:
~~~~~~~ start of file ~~~~~~~
1> 2> 3> 4> 5> 6> 7> 8> 9> 10> 11> 1> 2> 3> 4> 5> 6> 7> 8> 9> 10> 11>
12> 13> 14> 15> 16> 17> 18> 19> 20> 21> 22> 23> 24> 25> 26> 27> 28> 29>
30> 31> 32> 33> 34> 35> 36> 37> 38> 39> 40> 41> 42> 43> 44> 45> 46> 47>
48> 49> 50> 51> 52> 53> 54> 55> 56> 57> 58> 59> 60> 61> 62> 63> 64> 65>
66> 67> 68> 1> 2> 3> 4> 5> 6> 7> 8> 9>
~~~~~~ end of file ~~~~~~~~~
A log that has errors looks like this:
~~~~~~~ start of file ~~~~~~~
1> 2> 3> 1> 2> 3> 4> 5> 6> 7> 8> 9> 10> 11> 12> 1> 2> 3> 4> 5> 6> 7> 8>
9> 10> 11> 12> 13> 14> 15> 16> 17> 18> 47> 48> 49> 50> 51> 52> 53> 54>
55> 56> 57> 58> 59> Msg 262, Level 14, State 1, Server
DB019-APP0553-S, Procedure BUP_SAVE_POPULAR_SEARCH, Line 65535
CREATE PROCEDURE permission denied in database 'Metrics'.
1> 2> 3> 4> 5> 6> 7> 8> 9> Msg 208, Level 16, State 11, Server
DB019-APP0553-S, Line 2
Invalid object name 'WebAdmin.BUP_SAVE_POPULAR_SEARCH'. 1> 2> 3> 4> 1>
2> 1> 2> 3> 4> 5> 6> 7> 8> 9> 10> 11> 1> 2> 3> 4> 5> 6> 7> 8> 9> 10>
11> 12> 13> 14>
~~~~~~ end of file ~~~~~~~~~
An error in the log is defined by any character that's not a number, or
a greater than (>) symbol. I need a script to search the file and
report if the log is error free, or not. Any help would be greatly
appreciated. Thanks!
This is a bit horrible: A function that takes a string as its
parameter (the ReadAll() of your log file), and then removes all
numbers, ">" signs and spaces, and then returns true or false
depending on whether the resulting string is of zero length.
It might be of some use to you.
Lloyd
function CheckForErrors(s)
dim str
dim ret
str = s
str = replace(str, "1", "")
str = replace(str, "2", "")
str = replace(str, "3", "")
str = replace(str, "4", "")
str = replace(str, "5", "")
str = replace(str, "6", "")
str = replace(str, "7", "")
str = replace(str, "8", "")
str = replace(str, "9", "")
str = replace(str, "0", "")
str = replace(str, ">", "")
str = replace(str, " ", "")
if len(str)>0 then
ret = false
else
ret = true
end if
CheckForErrors = ret
end function
Dim fso, f
Dim regEx, Match, Matches
Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.OpenTextFile("c:\temp\testfile.txt",1)
ReadAllTextFile = f.ReadAll
Set regEx = New RegExp
regEx.Pattern = "[^0-9> \n\r\s]"
regEx.Global = True
Set Matches = regEx.Execute(ReadAllTextFile)
For Each Match in Matches
RetStr = RetStr & "Found at position " & Match.FirstIndex & ". Value :
" & Match.Value & vbCRLF
Next
if RetStr <>"" then
MsgBox("Errors in log")
MsgBox(RetStr)
else
MsgBox("No error in log")
end if
Regards
Georges
"Highlander" <tron...@msn.com> a écrit dans le message de news:
1141138590....@u72g2000cwu.googlegroups.com...
If all errors begin with "Msg" you could use InStr to seach for that string.
If InStr returns 0, there are no errors.
--
Richard
Microsoft MVP Scripting and ADSI
Hilltop Lab - http://www.rlmueller.net
"Highlander" <tron...@msn.com> wrote in message
news:1141138590....@u72g2000cwu.googlegroups.com...
I did find that for fairly large log files, with alot of errors, the
script doesn't return anything - no error messages, no MsgBox. It's
either blowing up, or I'm not patient enough to allow it to finish. In
any case, I resolved this by changing this line:
RetStr = RetStr & "Found at position " & Match.FirstIndex & ". Value :
" & Match.Value & vbCRLF
to this:
RetStr = RetStr & Match.FirstIndex
I don't need to record the found matches anyway, I just need the
notification. A large log file will still take a bit of time to finish,
but it works exactly how I need it to.
Thanks again!
- Dave
For Each Match in Matches
' an error has been found
RetStr = "Error found"
exit for
Next
Another thing is that the file is read entirely.
You can also open it, read 1 line at the time, anlysing it and stop if an
error is found
Like this
Dim fso, f
Dim regEx, Match, Matches, RetStr
Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.OpenTextFile("c:\temp\testfile.txt",1)
Set regEx = New RegExp
regEx.Pattern = "[^0-9> \n\r\s]"
regEx.Global = True
RetStr = ""
do while not f.AtEndOfStream
line=f.ReadLine
Set Matches = regEx.Execute(line)
For Each Match in Matches
' an error has been found
RetStr = "Error found"
' exiting loop for
exit for
Next
if RetStr<>"" then
' exiting loop do
exit do
end if
loop
f.close()
if RetStr <>"" then
MsgBox("Errors in log")
else
MsgBox("No error in log")
end if
Regards
Georges
"Highlander" <tron...@msn.com> a écrit dans le message de news:
1141157029.5...@j33g2000cwa.googlegroups.com...
I have a text file that looks like this:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[LEVEL]
1/25/2006 9:01:28 AM=ASDT v4.5
2/13/2006 11:02:00 AM=ASDT v4.6
2/24/2006 12:58:25 PM=ASDT v4.7
2/27/2006 2:08:48 PM=ASDT v4.8
[INSTALL]
1/25/2006 9:01:28 AM=User3 - ASDT Code Release - STR 7009
2/13/2006 11:02:00 AM=User5 - ASDT Code Release - STR 7212
2/24/2006 12:58:25 PM=User5 - ASDT Code Release - STR 7359
2/27/2006 2:08:48 PM=User2 - ASDT Code Release - STR 7375
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I'd like to be able to write to this file by making entries in both the
[LEVEL] and [INSTALL] sections - so that afterwards it looks like this:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[LEVEL]
1/25/2006 9:01:28 AM=ASDT v4.5
2/13/2006 11:02:00 AM=ASDT v4.6
2/24/2006 12:58:25 PM=ASDT v4.7
2/27/2006 2:08:48 PM=ASDT v4.8
3/6/2006 9:25:37 AM=MY NEW ENTRY IS HERE
[INSTALL]
1/25/2006 9:01:28 AM=User3 - ASDT Code Release - STR 7009
2/13/2006 11:02:00 AM=User5 - ASDT Code Release - STR 7212
2/24/2006 12:58:25 PM=User5 - ASDT Code Release - STR 7359
2/27/2006 2:08:48 PM=User2 - ASDT Code Release - STR 7375
3/6/2006 9:25:37 AM=MY NEW ENTRY IS HERE
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I imagine this could be done using RegExp, InStr, or some combination
thereof. Note that the seperation between the end of the [LEVEL]
section, and the beginning of the [INSTALL] section, can vary between
no carriage returns at all, to any number (typically one or two) of
carriage returns.
Any ideas on how to do this would be greatly appreciated. Thanks!
- Dave
[snip]
Will this help?
Option Explicit
'*
'* Declare Constants
'*
Const cVBS = "ini.vbs"
Const cOT1 = "ini1.txt"
Const cOT2 = "ini2.txt"
Const cIN1 = "[LEVEL]"
Const cIN2 = "[INSTALL]"
'*
Const ForReading = 1
Const ForWriting = 2
'*
'* Delare Variables
'*
Dim booIN1
booIN1 = False
Dim booIN2
booIN2 = False
Dim strNEW
strNEW = Now
strNEW = Month(strNEW) & "/" & Day(strNEW) & "/" & Year(strNEW) & "
"
strNEW = strNEW & Time "=MY NEW ENTRY IS HERE"
Dim arrOT1
Dim intOT1
Dim strOT1
Dim intOT2
Dim strOT2
'*
'* Declare Objects
'*
Dim objFSO
Set objFSO = CreateObject("Scripting.FileSystemObject")
Dim objOT1
Set objOT1 = objFSO.OpenTextFile(cOT1,ForReading)
Dim objOT2
Set objOT2 = objFSO.OpenTextFile(cOT2,ForWriting,True)
'*
'* Read File, Insert new entries, Write file.
'*
strOT1 = objOT1.ReadAll()
arrOT1 = Split(strOT1,vbCrLf)
For intOT1 = 0 To UBound(arrOT1)
strOT2 = arrOT1(intOT1)
If Left(strOT2,Len(cIN1)) = cIN1 Then booIN1 = True
If Left(strOT2,Len(cIN2)) = cIN1 Then booIN2 = True
If strOT2 = "" Then
If booIN1 Then
booIN1 = False
objOT2.WriteLine(strNEW)
ElseIf booIN2 Then
booIN2 = False
objOT2.WriteLine(strNEW)
End If
End If
objOT2.WriteLine(strOT2)
Next
'*
'* Destroy Objects
'*
Set objOT1 = Nothing
Set objOT2 = Nothing
Set objFSO = Nothing
'*
'* Finished
'*
MsgBox strNEW,vbInformation,cVBS
This presumes that the last line contains CrLf.
[snip]
In case the last line doesn't contain CrLf,
insert this line after the "Next" statement:
If booIN2 Then objOT2.WriteLine(strNEW)
Hi McKirahan thanks for the reply. Using "ini1.txt" as my original text
file, your script created a new text file "ini2.txt", which had a new
entry in the [LEVEL] section only.
I need to update the original file, versus creating a new file. I also
need the entry text ("MY NEW ENTRY IS HERE") to be two different
variables, one for the [LEVEL] section and one for the [INSTALL]
section.
The entries for each section would look something like this:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[LEVEL]
...
...
3/6/2006 12:28:47 PM=ASDT v4.8
[INSTALL]
...
...
3/6/2006 12:28:47 PM=User6 - ASDT Code Release - STR 7421
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[snip]
> Hi McKirahan thanks for the reply. Using "ini1.txt" as my original text
> file, your script created a new text file "ini2.txt", which had a new
> entry in the [LEVEL] section only.
Did you forget to add this line:
If booIN2 Then objOT2.WriteLine(strNEW)
> I need to update the original file, versus creating a new file. I also
> need the entry text ("MY NEW ENTRY IS HERE") to be two different
> variables, one for the [LEVEL] section and one for the [INSTALL]
> section.
>
> The entries for each section would look something like this:
>
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> [LEVEL]
> ...
> ...
> 3/6/2006 12:28:47 PM=ASDT v4.8
>
> [INSTALL]
> ...
> ...
> 3/6/2006 12:28:47 PM=User6 - ASDT Code Release - STR 7421
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
Try this version which overwrites the input file.
Option Explicit
'*
'* Declare Constants
'*
Const cVBS = "ini.vbs"
Const cOTF = "ini.txt"
Const cIN1 = "[LEVEL]"
Const cIN2 = "[INSTALL]"
'*
Const ForReading = 1
Const ForWriting = 2
'*
'* Delare Variables
'*
Dim booIN1
booIN1 = False
Dim booIN2
booIN2 = False
Dim arrNEW()
Dim intNEW
intNEW = 0
Dim strNEW
strNEW = Now
strNEW = Month(strNEW) & "/" & Day(strNEW) & "/" & Year(strNEW) & "
"
strNEW = strNEW & Time
strNEW = strNEW & "=MY NEW ENTRY IS HERE"
Dim arrOTF
Dim intOTF
Dim strOTF
'*
'* Declare Objects
'*
Dim objFSO
Set objFSO = CreateObject("Scripting.FileSystemObject")
Dim objOTF
'*
'* Read File
'*
Set objOTF = objFSO.OpenTextFile(cOTF,ForReading)
strOTF = objOTF.ReadAll()
arrOTF = Split(strOTF,vbCrLf)
ReDim arrNEW(UBound(arrOTF)+3)
For intOTF = 0 To UBound(arrOTF)
strOTF = arrOTF(intOTF)
If Left(strOTF,Len(cIN1)) = cIN1 Then booIN1 = True
If Left(strOTF,Len(cIN2)) = cIN1 Then booIN2 = True
If strOTF = "" Then
If booIN1 Then
booIN1 = False
intNEW = intNEW + 1
arrNEW(intNEW) = strNEW
ElseIf booIN2 Then
booIN2 = False
intNEW = intNEW + 1
arrNEW(intNEW) = strNEW
End If
End If
intNEW = intNEW + 1
arrNEW(intNEW) = strOTF
Next
If booIN2 Then
intNEW = intNEW + 1
arrNEW(intNEW) = strNEW
End If
Set objOTF = Nothing
'*
'* Write file
'*
Set objOTF = objFSO.OpenTextFile(cOTF,ForWriting,True)
For intNEW = 1 To UBound(arrNEW)
strOTF = arrNEW(intNEW)
objOTF.WriteLine(strOTF)
Next
Set objOTF = Nothing
'*
'* Destroy Objects
'*
If booIN2 Then objOT2.WriteLine(strNEW)
The result is always the same - I get a new entry in the [LEVEL]
section only. Plus, each text file I have to edit is different; some
may have a last line that contains CrLf, some may not.
I still also need two variables that will each contain different text,
one for each section [LEVEL] and [INSTALL].
I'm stumped.
My first solution only had one Next statement.
Did you try my second solution "as is"?
[snip]
> I still also need two variables that will each contain different text,
> one for each section [LEVEL] and [INSTALL].
In your example the new lines (variables?) did not contain "different text";
"3/6/2006 9:25:37 AM=MY NEW ENTRY IS HERE" is repeated.
[LEVEL]
1/25/2006 9:01:28 AM=ASDT v4.5
2/13/2006 11:02:00 AM=ASDT v4.6
2/24/2006 12:58:25 PM=ASDT v4.7
2/27/2006 2:08:48 PM=ASDT v4.8
3/6/2006 9:25:37 AM=MY NEW ENTRY IS HERE
[INSTALL]
1/25/2006 9:01:28 AM=User3 - ASDT Code Release - STR 7009
2/13/2006 11:02:00 AM=User5 - ASDT Code Release - STR 7212
2/24/2006 12:58:25 PM=User5 - ASDT Code Release - STR 7359
I had also tried your solution as is, before inserting the line after
the Next statements - that wouldn't work either.
After searching the newsgroup and combining some code snippets, I tried
a new approach. So far it works great. I think it's a little clunky
though; it could probably be cleaned up and consolidated a bit:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Const OverwriteExisting = True
Set fso = CreateObject("Scripting.FileSystemObject")
'~~~ Remove all blank lines from current INI file
Dim INIFile, Temp1, Backup
INIFile = "ini.txt"
Temp = "Temp.txt"
Backup = "ini.backup.txt"
Set curfile = fso.OpenTextFile(INIFile)
Set newfile = fso.CreateTextFile(Temp)
Do until curfile.AtEndOfStream
line = curfile.readLine
IF len(line)>0 Then newfile.writeLine line
Loop
curfile.Close
newfile.Close
'~~~ Backup original INI file
IF fso.FileExists(Backup) Then
fso.DeleteFile(Backup)
End IF
fso.MoveFile INIFile , Backup
'~~~ Copy new (de-blanked) file to INI file
fso.CopyFile Temp, INIFile, True
fso.DeleteFile(Temp)
'~~~ Read the INI file and create arrays
'~~~ from the Level and Install sections
Dim AllText, delim, ptr, Level, Install
Set TextFile = FSO.OpenTextFile(INIFile , 1)
AllText = TextFile.ReadAll
delim = "[INSTALL]"
ptr = inStrRev(AllText,delim)
IF NOT ptr = 0 then
Level = left(AllText, ptr-1)
Install = mid(AllText, ptr)
End IF
TextFile.Close
'~~~ Append the timestamp and new text entries to each array
Dim LevelNew, InstallNew
LevelNew = Level & NOW & "=" & "New LEVEL section text here."
InstallNew = Install & NOW & "=" & "New INSTALL section text here."
'~~~ Write the completed arrays to the INI file
Set TextFile = FSO.OpenTextFile(INIFile, 2, True)
Dim ArrLevel
ArrLevel = Split(LevelNew,vbCrlf)
For i = 0 To UBound(ArrLevel)
EachLine = ArrLevel(i)
TextFile.WriteLine EachLine
Next
TextFile.WriteLine vbCrLf
TextFile.Close
Set TextFile = FSO.OpenTextFile(INIFile, 8, True)
Dim ArrInstall
ArrInstall = Split(InstallNew,vbCrlf)
For i = 0 To UBound(ArrInstall)
EachLine = ArrInstall(i)
TextFile.WriteLine EachLine
Next
TextFile.Close
Set fso = nothing
Set curfile = nothing
Set newfile = nothing
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Thanks again for all your help!
Looks like I'm good to go. Any suggestions for improving the above code
would be greatly appreciated.
- Dave
Below is a minor update to my last solution.
It supports different text for [LEVEL] and [INSTALL].
I'm curious as to why doesn't it work for you?
Option Explicit
'*
'* Declare Constants
'*
Const cVBS = "ini.vbs"
Const cOTF = "ini.txt"
Const cIN1 = "[LEVEL]"
Const cIN2 = "[INSTALL]"
Const cLEV = "=New LEVEL section text here."
Const cINS = "=New INSTALL section text here."
'*
Const ForReading = 1
Const ForWriting = 2
'*
'* Delare Variables
'*
Dim booIN1
booIN1 = False
Dim booIN2
booIN2 = False
Dim arrNEW()
Dim intNEW
intNEW = 0
Dim strNEW
strNEW = Now
' uncomment the following if you need "m/d/yyyy" instead of "mm/dd/yyyy":
' strNEW = Month(strNEW) & "/" & Day(strNEW) & "/" & Year(strNEW) & "
"
' strNEW = strNEW & Time
Dim arrOTF
Dim intOTF
Dim strOTF
'*
'* Declare Objects
'*
Dim objFSO
Set objFSO = CreateObject("Scripting.FileSystemObject")
Dim objOTF
'*
'* Read File
'*
Set objOTF = objFSO.OpenTextFile(cOTF,ForReading)
strOTF = objOTF.ReadAll()
arrOTF = Split(strOTF,vbCrLf)
ReDim arrNEW(UBound(arrOTF)+3)
For intOTF = 0 To UBound(arrOTF)
strOTF = arrOTF(intOTF)
If Left(strOTF,Len(cIN1)) = cIN1 Then booIN1 = True
If Left(strOTF,Len(cIN2)) = cIN1 Then booIN2 = True
If strOTF = "" Then
If booIN1 Then
booIN1 = False
intNEW = intNEW + 1
arrNEW(intNEW) = strNEW & cLEV
ElseIf booIN2 Then
booIN2 = False
intNEW = intNEW + 1
arrNEW(intNEW) = strNEW & cINS
End If
End If
intNEW = intNEW + 1
arrNEW(intNEW) = strOTF
Next
If booIN2 Then
intNEW = intNEW + 1
arrNEW(intNEW) = strNEW & cINS
End If
Set objOTF = Nothing
'*
'* Write file
'*
Set objOTF = objFSO.OpenTextFile(cOTF,ForWriting,True)
For intNEW = 1 To UBound(arrNEW)
strOTF = arrNEW(intNEW)
objOTF.WriteLine(strOTF)
Next
Set objOTF = Nothing
'*
'* Destroy Objects
'*
Set objFSO = Nothing
'*
'* Finished
'*
MsgBox strNEW,vbInformation,cVBS
I ensure that both entries have the same timestamp.
Using "Now" twice may give different timestamps.
Also, when I use now, it gives me "mm/dd/yyyy"
not "m/d/yyyy" as you say you want.