Jump to content
Sign in to follow this  
mdwerne

Missing data and fractured log file....

Recommended Posts

mdwerne

Hello,

I have a script that gathers data and writes that data to a log file on a server. The problem I'm seeing is that sometimes the data in the log file is missing or incomplete. Can anyone see anyway to improve my code so that the risk of losing data or incomplete log entries is minimized?

Sample of log file:

Good Row:

2012-02-27 11:20:41 : ComputerName, WIN_7 - 2009/09/08, Service Pack 1 - 8/4/2011, 1508 error on - 2010-07-01

Bad/Fractured rows:

2012-02-

1508 error on - 2010-07-01

2012-02-27 11:23:45 : ComputerName, WIN_7 - 2009/09/08, Service Pack 1 - 8/4/2011, 1508 error on - 2010-07-012012-02-27 11:20:41 : ComputerName, WIN_7 - 2009/09/08, Service Pack 1 - 8/4/2011, 1508 error on - 2010-07-01

The errors happen about 2% of the time...enought that I thought I should look for a better way.

Opt('MustDeclareVars', 1)
Opt("TrayMenuMode", 1)
#include <File.au3>
#include <Date.au3>
Global $ErrorDate, $objWMIService, $colItems, $sWMIService, $HFID, $SPDate, $DateRead, $OSInstallDate
Global $Log = "MainFileServerCheck1508$1508Errors.log"
Global $OSSP = @OSServicePack
If $OSSP = "" Then $OSSP = "No service pack"
If @OSArch = "X64" Then
$DateRead = RegRead("HKEY_LOCAL_MACHINE64SOFTWAREMicrosoftWindows NTCurrentVersion", "InstallDate")
Else
$DateRead = RegRead("HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersion", "InstallDate")
EndIf
$OSInstallDate = _DateAdd('s', $DateRead, "1970/01/01")
If @OSVersion = "WIN_7" Then
If FileExists(@TempDir & "1508Error.txt") Then FileDelete(@TempDir & "1508Error.txt")
Local $Result = RunWait(@ComSpec & " /c wevtutil.exe qe Application /rd:true /c:1 /q:*[System[(EventID=1508)]] /f:text > " & @TempDir & "1508Error.txt", @SystemDir, @SW_HIDE)
Global $hFile = FileOpen($Log, 1)
Global $ErrorLog = @TempDir & "1508Error.txt"
Local $Size = FileGetSize($ErrorLog)
If $Size > 0 Then
  CheckWMI()
  GetDate()
  _FileWriteLog($hFile, @ComputerName & ", " & @OSVersion & " - " & $OSInstallDate & ", " & $OSSP & " - " & $SPDate & ", 1508 error on - " & $ErrorDate)
Else
  CheckWMI()
  _FileWriteLog($hFile, @ComputerName & ", " & @OSVersion & " - " & $OSInstallDate & ", " & $OSSP & " - " & $SPDate)
EndIf
FileClose($hFile)
Exit
Else
Local $hFile = FileOpen($Log, 1)
_FileWriteLog($hFile, @ComputerName & ", " & @OSVersion & " - " & $OSInstallDate & ", " & $OSSP)
FileClose($hFile)
Exit
EndIf
Func GetDate()
Local $File = FileOpen($ErrorLog)
Local $sString = FileRead($File)
Local $iPosSeqStart = StringInStr($sString, "Date: ")
Local $iPosSeqEnd = StringInStr($sString, "T", 0, 1, $iPosSeqStart)
$ErrorDate = (StringMid($sString, $iPosSeqStart + 6, $iPosSeqEnd - $iPosSeqStart + 8))
EndFunc   ;==>GetDate
Func CheckWMI()
$sWMIService = "winmgmts:" & @ComputerName & "rootCIMV2"
$objWMIService = ObjGet($sWMIService)
If IsObj($objWMIService) Then
  $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_QuickFixEngineering WHERE HotFixID = 'KB976932'")
  If IsObj($colItems) Then
   For $oItem In $colItems
    $HFID = $oItem.HotFixID
    $SPDate = $oItem.InstalledOn
   Next
  Else
   _FileWriteLog($hFile, @ComputerName & ", " & @OSVersion & " - " & $OSInstallDate & ", " & $OSSP & ", QFE failure")
  EndIf
Else
  _FileWriteLog($hFile, @ComputerName & ", " & @OSVersion & " - " & $OSInstallDate & ", " & $OSSP & ", WMI Failure")
EndIf
If $SPDate = "" Then $SPDate = "Original OS install"
EndFunc   ;==>CheckWMI

Thanks for any suggestions you can offer,

-Mike

Edited by mdwerne

Share this post


Link to post
Share on other sites
Spiff59

It runs on my new WIN7X64 machine, but generates an empty .txt file.

I'm sure your wevtutil.exe call isn't tweaked for my machine, and I may not have any 1508 errors in my event logs.

Looking at the code, nothing jumps out at me...

You're missiing a fileclose, I don't think the @CRLF is wanted, I see room for some clean-up, but nothing appears blatantly wrong.

From the look of your output I'd think more error checking in your GetDate() function might be called for.

Share this post


Link to post
Share on other sites
mdwerne

It runs on my new WIN7X64 machine, but generates an empty .txt file.

I'm sure your wevtutil.exe call isn't tweaked for my machine, and I may not have any 1508 errors in my event logs.

Looking at the code, nothing jumps out at me...

You're missiing a fileclose, I don't think the @CRLF is wanted, I see room for some clean-up, but nothing appears blatantly wrong.

From the look of your output I'd think more error checking in your GetDate() function might be called for.

Thanks for the feedback Spiff59.

Yes, the empty txt file in the TEMP dir indicated that there was no 1508 error. If you replace the eventID ([(EventID=1508)]]) with one that does exist in your application log, you will see the last one listed in the TXT file. Maybe try 4101.

I removed the extra @CRLF and fixed this line:

This

If FileExists(@TempDir & "1508Error.xml") Then FileDelete(@TempDir & "1508Error.xml")

to this

If FileExists(@TempDir & "1508Error.txt") Then FileDelete(@TempDir & "1508Error.txt")

Originally was writing to an XML file.

I know the output from the dates is ugly....this was a quick and dirty to get some quick answers.

I have modified the code above to reflect the changes.

Where was the missing FileClose? I can't seem to see it.

Any other suggestions would be greatly appreciated!

-Mike

Edited by mdwerne

Share this post


Link to post
Share on other sites
mdwerne

Bummer...

I recomplied and had our SCCM guy push the new program to another 50 machines...sadly the log file is still horrible. About 10% of the lines are coming back messed up.

See below:

2012-02-28 13:23:38 : CompName, WIN_7 - 2011/03/22, No service pack - Original OS install

2012-02-28 13:23:42 : CompName, WIN_7 - 2011/06/01, No service pack - Original OS install

2012-02-28 13:23:46 : CompName WIN_7 - 2010/12/22, No service pack - Original OS install, 1508 error on - 2012-02-14

2012-02-28 13:23:48 : CompName, WIN_7 - 2010/12/01, No service pack - Original OS install

2012-02-28 13:23:52 : CompName WIN_7 - 2010/09/09, No service pack - Original OS install

2012-02-28 13:23:54 : CompName, WIN_7 - 2011/09/08, No service pack - Original OS install

1508 error on - 2010-09-13

4, WIN_7 - 2010/07/15, No service pack - Original OS install

pack - Original OS install

2012-02-28 13:23:59 :CompName, WIN_7 - 2010/08/18, No service pack - Original OS install

0, WIN_7 - 2010/09/20, No service pack - Original OS install

k 1 - Original OS install

2012-02-28 13:24:08 : CompName WIN_7 - 2011/06/16, No service pack - Original OS install

1508 error on - 2011-11-17

2012-02-28 13:24:07 : CompName, WIN_7 - 2012/02/09, Service Pack 1 - Original OS install

2012-02-28 13:24:10 : CompName, WIN_7 - 2011/03/10, No service pack - Original OS install, 1508 error on - 2011-10-24

2012-02-28 13:24:13 : CompName, WIN_7 - 2010/12/06, No service pack - Original OS install, 1508 error on - 2011-10-06

2012-02-28 13:24:18 : CompName WIN_7 - 2012/01/04, Service Pack 1 - Original OS install

1508 error on - 2012-01-12

2012-02-28 13:24:21 : CompName WIN_7 - 2010/11/04, No service pack - Original OS install

2012-02-28 13:24:32 : CompName, WIN_7 - 2010/09/23, No service pack - Original OS install

2012-02-28 13:26:24 : CompName, WIN_7 - 2011/03/01, Service Pack 1 - 2/11/2012

Maybe it's not my code? Maybe something else?

Any insight would be awesome,

-Mike

Share this post


Link to post
Share on other sites
willichan

It sounds like you may have more than one machine trying to write at the same time. File locking may help. Try

Share this post


Link to post
Share on other sites
Spiff59

I don't think you need the filedelete at all as it's >> that appends to a file and the > pipe creates a new file?

The GetDate() routine didn't have a file close, but that's really just a "good form" issue.

I modified it to snag a different error and ran it repeatedly with the slightly tinkered version belopw and had no problems.

Not sure if the GetDate() routine below is functionally the same as yours.

Maybe there's an timing issue with your runwait? Where the task ends but the output file has not finished being written to and has not yet closed? Just brainstorming... Someone else may have to figure this one out.

Opt('MustDeclareVars', 1)
Opt("TrayMenuMode", 1)
#include <File.au3>
#include <Date.au3>
Global $hFile, $ErrorDate, $objWMIService, $colItems, $sWMIService, $HFID, $SPDate, $DateRead, $OSInstallDate
Global $Log = @ScriptDir & "1508Errors.log"
Global $ErrorLog = @ScriptDir & "1508Errors.txt"
Global $OSSP = @OSServicePack
If $OSSP = "" Then $OSSP = "No service pack"
If @OSArch = "X64" Then
    $DateRead = RegRead("HKEY_LOCAL_MACHINE64SOFTWAREMicrosoftWindows NTCurrentVersion", "InstallDate")
Else
    $DateRead = RegRead("HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersion", "InstallDate")
EndIf
$OSInstallDate = _DateAdd('s', $DateRead, "1970/01/01")

$hFile = FileOpen($Log, 1)
If @OSVersion = "WIN_7" Then
    $SPDate = CheckWMI()
    RunWait(@ComSpec & " /c wevtutil.exe qe Application /rd:true /c:1 /q:*[System[(EventID=1503)]] /f:text > " & $ErrorLog, @SystemDir, @SW_HIDE)
    If FileGetSize($ErrorLog) Then $ErrorDate = GetDate()
EndIf
_FileWriteLog($hFile, @ComputerName & ", " & @OSVersion & " - " & $OSInstallDate & ", " & $OSSP & " - " & $SPDate & $ErrorDate)
FileClose($hFile)
Exit

Func GetDate()
    Local $sString = FileRead($ErrorLog)
    Local $iPosSeqStart = StringInStr($sString, "Date: ")
    If $iPosSeqStart Then Return ", 1508 error on - " & StringMid($sString, $iPosSeqStart + 6, 10)
EndFunc   ;==>GetDate

Func CheckWMI()
    Local $date
    $sWMIService = "winmgmts:" & @ComputerName & "rootCIMV2"
    $objWMIService = ObjGet($sWMIService)
    If IsObj($objWMIService) Then
        $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_QuickFixEngineering WHERE HotFixID = 'KB976932'")
        If IsObj($colItems) Then
           For $oItem In $colItems
               $HFID = $oItem.HotFixID
               $date = $oItem.InstalledOn
           Next
       Else
           _FileWriteLog($hFile, @ComputerName & ", " & @OSVersion & " - " & $OSInstallDate & ", " & $OSSP & ", QFE failure")
       EndIf
Else
      _FileWriteLog($hFile, @ComputerName & ", " & @OSVersion & " - " & $OSInstallDate & ", " & $OSSP & ", WMI Failure")
EndIf
Return $date
EndFunc   ;==>CheckWMI

Share this post


Link to post
Share on other sites
BrewManNH

I'm with Willichan on this, you have multiple machines writing to the file at the same time, of course it's going to be messed up like that.


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites
mdwerne

It sounds like you may have more than one machine trying to write at the same time. File locking may help. Try

Yes Will, multiple computers write to the file at the same time...I will give your UDF a try and see what happens.

Thanks, Mike

Share this post


Link to post
Share on other sites
kylomas

mdwerne,

IF the corruption does NOT follow a pattern than multiple concurrent access is the prime suspect. As a test you might imbed the workstation name into the file name and merge the files under a controlled environment. If the corruption goes away that is your problem. If it does not, I would look very closely at unexpected line feeds in your source.

kylomas


Forum Rules         Procedure for posting code

"I like pigs.  Dogs look up to us.  Cats look down on us.  Pigs treat us as equals."

- Sir Winston Churchill

Share this post


Link to post
Share on other sites
mdwerne

Thanks to all for the input. I've never done a script like this so taking into consideration multiple machines writing to the same file at the same time didn't cross my mind. I'm sure you're all right and that is the my issue. I will see if I can get Will Chans UDF to work for me as I don't know of any other options. kylomas idea of dumping to individual files and then merging them into a single file is a good one, but if I can learn how to lock the file for each write, I think that knowledge will be more beneficial for me in the future.

Thanks again,

-Mike

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×