Home All Groups Group Topic Archive Search About

Application crashing - trying to track down the problem.

Author
2 Mar 2007 4:41 AM
Paul Lambert
System is a windows 2000 server machine, 2Gb ram, 40Gb hard drive - most
unused.

I have an application written in VB6 which receives messages from a 3rd
party program called DMQ (DECMessageQ - developed by HP to transfer
messages between different OS's. In my case passing messages from
OpenVMS to Windows) and using an ODBC connection over DAO pipes the data
received into a PostgreSQL database.

After receiving a number of messages and updating the database, which is
working perfectly, the application shuts itself down without any errors
written to the log or showing on-screen - I do however get a DrWatson in
the eventlog suggesting an access violation.

I've added some debug code by way of some extra writes to the logfile to
try narrowing down where it is crashing, but my problem is that the
writes don't seem to get cleared into the file from memory, thus I have
incomplete information in the logfile that does not show up to the point
of the actual failure, so I'm having some trouble finding exactly where
the error is coming from.

Is there any way after doing a write statement to flush the buffers and
get the write actually commited to the file on disk?

The file is being opened with the following command:

Open App_Path + STRLOGFILENAME For Append Access Write Shared As log_file

And writes are being done with the following function:

Public Sub log_message(error_text As String)
On Error GoTo finish

     Write #log_file,
     Write #log_file, Now & " " & error_text
     'Would like to put some sort of flush command here??
finish:

End Sub

Any thoughts or suggestions would be appreciated.

Thanks,
Paul.
--
Paul Lambert
Database Administrator
AutoLedgers

--
Posted via a free Usenet account from http://www.teranews.com

Author
2 Mar 2007 5:39 AM
Bob O`Bob
Paul Lambert wrote:
>
> Is there any way after doing a write statement to flush the buffers and
> get the write actually commited to the file on disk?

It'll beat up your performance something fierce, but yeah - and
you'll probably kick yourself, it's so simple:  close the file.

Might be okay for limited debug use, but it's really not a good way
to log progress.


    Bob
--
Author
2 Mar 2007 5:58 AM
Paul Lambert
Bob O`Bob wrote:
> Paul Lambert wrote:
>>
>> Is there any way after doing a write statement to flush the buffers
>> and get the write actually commited to the file on disk?
>
> It'll beat up your performance something fierce, but yeah - and
> you'll probably kick yourself, it's so simple:  close the file.
>
> Might be okay for limited debug use, but it's really not a good way
> to log progress.
>
>
>     Bob

I did consider that... I'll give it a go anyway.

Thanks,

P.

--
Posted via a free Usenet account from http://www.teranews.com
Author
2 Mar 2007 7:53 AM
J French
On Fri, 02 Mar 2007 14:58:54 +0900, Paul Lambert
<paul.lamb***@autoledgers.com.au> wrote:

Show quoteHide quote
>Bob O`Bob wrote:
>> Paul Lambert wrote:
>>>
>>> Is there any way after doing a write statement to flush the buffers
>>> and get the write actually commited to the file on disk?
>>
>> It'll beat up your performance something fierce, but yeah - and
>> you'll probably kick yourself, it's so simple:  close the file.
>>
>> Might be okay for limited debug use, but it's really not a good way
>> to log progress.
>>
>>
>>     Bob

>I did consider that... I'll give it a go anyway.

Open, Write, Close  is the safest way

However the API's do have a FlushFileBuffers but that means you have
to use the deprecated OpenFile or messy CreateFile
Author
2 Mar 2007 8:04 PM
Bob O`Bob
Paul Lambert wrote:
> Bob O`Bob wrote:

>> It'll beat up your performance something fierce, but yeah - and
>> you'll probably kick yourself, it's so simple:  close the file.

>
> I did consider that... I'll give it a go anyway.


Something I've done with much lower performance penalties is write
trace info into a section of an INI file.  Windows handles cache for
those, so performance is good and losses are almost unheard-of.

I set a value for how many lines to retain, and overwrote numeric keys,
along with constantly updating a pointer, so I'd get something a little
like this as results:

[debug]
retain = 10 ;just for posting; more like 100 in real testing
latest = 5
1 = checkpoint 42
2 = checkpoint 83
3 = checkpoint 43
4 = checkpoint 50
5 = checkpoint 61
6 = checkpoint 11
7 = checkpoint 13
8 = checkpoint 21
9 = checkpoint 33
10 = checkpoint 26


(...something after checkpoint 61 may be the problem there)

In other implementations, I included gettickcount results as part of the
trace string, so I could dispense with updating a pointer.  But that was
because I already had the gettickcount value handy.

Sometimes I turn the retention way down (maybe 25) and just leave those
in, even in production code (assuming the INI file is already being used)
But it's been a long time since I've done that.  I have a vague memory
of finding some good reason to disable it by default.

But it's really cool to be able to turn it back on by giving a remote
user instructions how to use a simple text editor on an INI file, and
have them mail me a copy of the same file after the next crash.


    Bob
--
Author
3 Mar 2007 12:32 PM
Johan_Stäck
Bob O`Bob skrev:
Show quoteHide quote
> Paul Lambert wrote:
>> Bob O`Bob wrote:
>
>>> It'll beat up your performance something fierce, but yeah - and
>>> you'll probably kick yourself, it's so simple:  close the file.
>
>>
>> I did consider that... I'll give it a go anyway.
>
>
> Something I've done with much lower performance penalties is write
> trace info into a section of an INI file.  Windows handles cache for
> those, so performance is good and losses are almost unheard-of.
>
> <SNIP>
Does this mean that when the .EXE crashes, Windows will write the cache
of the .INI file to disk?

/Johan
Author
3 Mar 2007 5:22 PM
Ralph
"Johan Stäck" <jo***@stack.se> wrote in message
news:%23n41LAZXHHA.596@TK2MSFTNGP06.phx.gbl...
> > <snipped>
>
> Does this mean that when the .EXE crashes, Windows will write the cache
> of the .INI file to disk?
>
> /Johan

In appearance yes.

The OS handles the INI file and not your App. While there is obviously a
'handle' involved (the OS knows who's writing to what) it isn't a direct
File Handle and the INI doesn't exist in an Apps address space.

One can never say for sure what might happen if an App 'crashed', but in all
these years with 32-bit OSs I have never seen a corrupted INI file. Bad data
occasionally, concurrancy issues with multiple Apps, but never an integrity
problem. The last successful write always appears to be there. But then I
may have just been lucky. <g>

-ralph
Author
3 Mar 2007 10:27 PM
Bob O`Bob
Johan Stäck wrote:
> Bob O`Bob skrev:

>> Something I've done with much lower performance penalties is write
>> trace info into a section of an INI file.  Windows handles cache for
>> those, so performance is good and losses are almost unheard-of.
>>
>> <SNIP>
> Does this mean that when the .EXE crashes, Windows will write the cache
> of the .INI file to disk?


Generally, yes.

The only [apparent] exceptions I have encountered have been when I was
doing "tricky" things with threads, and even then not much was lost.
Actually, I might possibly have been misinterpreting the results - in
retrospect, my understanding of threading in those days was relatively weak.

In Ralph's terminology, at worst I was just "unlucky" a couple of times.

Plus, the API does have a "flush buffers" facility, if you ever seem to be
running into trouble.


    Bob
Author
4 Mar 2007 3:37 PM
Johan_Stäck
Bob O`Bob skrev:
Show quoteHide quote
> Johan Stäck wrote:
>> Bob O`Bob skrev:
>
>>> Something I've done with much lower performance penalties is write
>>> trace info into a section of an INI file.  Windows handles cache for
>>> those, so performance is good and losses are almost unheard-of.
>>>
>>> <SNIP>
>> Does this mean that when the .EXE crashes, Windows will write the
>> cache of the .INI file to disk?
>
>
> Generally, yes.
>
> The only [apparent] exceptions I have encountered have been when I was
> doing "tricky" things with threads, and even then not much was lost.
> Actually, I might possibly have been misinterpreting the results - in
> retrospect, my understanding of threading in those days was relatively
> weak.
>
> In Ralph's terminology, at worst I was just "unlucky" a couple of times.
>
> Plus, the API does have a "flush buffers" facility, if you ever seem to be
> running into trouble.
>
>
>     Bob
This is very interesting!

I think I will try and write a VB6 "tracer class" that utilizes the .INI
system.

I have a large VB6 project that receives lots of callbacks from multiple
DV firewire camcorders, and it is very difficult to debug using "normal"
methods. VBtracer has helped me a lot, but this might be even better...

/Johan
Author
4 Mar 2007 9:44 PM
Bob O`Bob
Johan Stäck wrote:
>
> I think I will try and write a VB6 "tracer class" that utilizes the .INI
> system.
>
> I have a large VB6 project that receives lots of callbacks from multiple
> DV firewire camcorders, and it is very difficult to debug using "normal"
> methods. VBtracer has helped me a lot, but this might be even better...


That could be really cool, and I hope if it works out, you'll be willing
to share a generic version.


Just in case it helps, I'm happy to share a generic version of the CINI.cls
that I use.  It's not great code or anything like that, but it is
a beginning of an object wrapper around most of the API.
You'd need to patch in your own error reporting needs where I use
  "LogError()", and there may be more little holes to patch.



    Bob

Some of it is very likely derivative of a product I made a lot of use of
many years ago called "Start Developing with VB" from MossMicro.
I don't know if they're still around, or if the traces of their work are
still even significant in here, but they gave me a good head start
a long time ago.


-------file CINI.cls---------

VERSION 1.0 CLASS
BEGIN
   MultiUse = -1  'True
   Persistable = 0  'NotPersistable
   DataBindingBehavior = 0  'vbNone
   DataSourceBehavior  = 0  'vbNone
   MTSTransactionMode  = 0  'NotAnMTSObject
END
Attribute VB_Name = "CINI"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Attribute VB_Ext_KEY = "SavedWithClassBuilder6" ,"Yes"
Attribute VB_Ext_KEY = "Top_Level" ,"Yes"
'---------------------------------------------------------------------------------------
' Module    : CINI
' DateTime  : 5/20/06 17:47
' Author    : Bob
' Purpose   :
'---------------------------------------------------------------------------------------

Option Explicit

Private sIniFile As String

Private Const me_debug = " CINI "
#If False Then  'removed by compiler
Dim end_of_declarations
#End If
'

'---------------------------------------------------------------------------------------
' Procedure : AppIniFileName
' DateTime  : 5/20/06 15:43
' Author    : Bob
' Purpose   :
'---------------------------------------------------------------------------------------
'
Public Property Get AppIniFileName() As String
    On Error GoTo AppIniFileName_Error

     AppIniFileName = App.Path & "\" & App.EXEName & ".INI"

    On Error GoTo 0
    Exit Property

AppIniFileName_Error:

     LogError "Error " & Err.Number & " (" & Err.Description & ") in procedure AppIniFileName of Class Module CINI"
End Property

'---------------------------------------------------------------------------------------
' Procedure : FormPosRestore
' DateTime  : 5/20/06 18:04
' Author    : Bob
' Purpose   :
'---------------------------------------------------------------------------------------
'
Public Sub FormPosRestore(frmTgt As Form, Optional full)
'restores form's position to saved value
'if no saved value or error, does not move form
'
'modified 11-22 -bo'b
'   removed width and height from the .Move
'   none of the forms in this project need to be sizable
'replaced sizing optionally 24 Feb 97 for the Splash screen
'
'Mod 3 jun 03 to utilize form.tag as well

Dim t$
Dim sfLeft As Single, sfTop As Single
Dim sfWidth As Single, sfHeight As Single
    On Error GoTo FormPosRestore_Error

     t$ = IniGetString("forms", frmTgt.Name & frmTgt.Tag, "")
     If Len(t$) Then
         On Error GoTo err_FPRexit
         sfLeft = CSng(GetToken(t$, ","))
         sfTop = CSng(GetToken(t$, ","))
         If IsMissing(full) Then
             frmTgt.Move sfLeft, sfTop
         Else
             sfWidth = CSng(GetToken(t$, ","))
             sfHeight = CSng(GetToken(t$, ","))
             frmTgt.Move sfLeft, sfTop, sfWidth, sfHeight
         End If
     End If

Exit Sub
err_FPRexit:
     'no task if error occurs

    On Error GoTo 0
    Exit Sub

FormPosRestore_Error:

     LogError "Error " & Err.Number & " (" & Err.Description & ") in procedure FormPosRestore of Class Module CINI"
End Sub

Public Sub FormPosSave(frmTgt As Form)
     On Error Resume Next
'saves form's position to INI by form.name
Dim temp As Boolean
     temp = IniWriteString("forms", frmTgt.Name & frmTgt.Tag, _
         (frmTgt.Left & ", " & frmTgt.Top & ", " & frmTgt.Width & ", " & frmTgt.Height))

End Sub

'------------------------------------------------------------------------------
' Function: IniDeleteKey
'
' Purpose:  Delete the specified key in the specified section.
' Params:   sSection    (I) Section name
'           sKey        (I) Key name
' Returns:  TRUE on success, else FALSE.
'------------------------------------------------------------------------------
Public Function IniDeleteKey(sSection As String, sKey As String) As Boolean
     On Error Resume Next
     IniDeleteKey = (WritePrivateProfileString(sSection, sKey, vbNullString, sIniFile) <> 0)
End Function

'------------------------------------------------------------------------------
' Function: IniDeleteSection
'
' Purpose:  Delete the specified section from this application's .INI file.
' Params:   sSection    (I) Name of section to delete
' Returns:  TRUE on success, else FALSE.
'------------------------------------------------------------------------------
Public Function IniDeleteSection(sSection As String) As Boolean
     On Error Resume Next
     IniDeleteSection = (WritePrivateProfileString(sSection, vbNullString, vbNullString, sIniFile) <> 0)
End Function

Public Property Get INIFileName() As String
     INIFileName = sIniFile
End Property

Public Property Let INIFileName(ByVal sNewValue As String)
     sIniFile = sNewValue
     QueueLogMsg "INI File: " & sNewValue
End Property

'------------------------------------------------------------------------------
' Function: IniGetBool()
'
' Purpose:  Retrieve a boolean value from the INI file.
' Params:   sSection    (I) Section name
'           sKey        (I) Key entry
'           bDefault    (I) Default value
' Notes:    TRUE and FALSE are stored as "Yes" and "No" strings respectively.
'           The default value is returned when no entry is found,
'           however, it is never written.
' Returns:  The value from the INI file if found, else the default value.
' See also: IniWriteBool(), IniGetInt(), IniGetRect(), IniGetString().
'------------------------------------------------------------------------------
Public Function IniGetBool(sSection As String, sKey As String, bDefault As Boolean) As Boolean
     On Error Resume Next
     IniGetBool = (IniGetString(sSection, sKey, IIf(bDefault, "Yes", "No")) = "Yes")
End Function

'------------------------------------------------------------------------------
' Function: IniGetInt
'
' Purpose:  Retrieve a numeric value from the INI file.
' Params:   sSection    (I) Section name
'           sKey        (I) Key name
'           nDefault    (I) Default value
' Returns:  The numeric value if found, else the default.
' See also: IniWriteInt(), IniGetBool(), IniGetRect(), IniGetString()
'------------------------------------------------------------------------------
Public Function IniGetInt(sSection As String, sKey As String, nDefault As Integer) As Integer
     On Error Resume Next
     IniGetInt = GetPrivateProfileInt(sSection, sKey, nDefault, sIniFile)
End Function

'------------------------------------------------------------------------------
' Function: IniGetString
'
' Purpose:  Retrieve a string from the INI file.
' Params:   sSection    (I) Section name
'           sKey        (I) Key name
'           sDefault    (I) Default value
' Returns:  The string if found, else the default.
' See also: IniWriteString(), IniGetBool(), IniGetInt(),
'           IniGetRect()
'------------------------------------------------------------------------------
Public Function IniGetString(sSection As String, sKey As String, sDefault As String) As String
     On Error Resume Next
     IniGetString = IniPrivateGetString(sSection, sKey, sDefault, sIniFile)
End Function

'------------------------------------------------------------------------------
' Function: IniPrivateGetString()
'
' Purpose:  Get a string from the requested INI file.
' Params:   sSection    (I) INI section (e.g. Administrator, Options, etc.).
'           sKey        (I) Key within the requested section (e.g. Option1).
'           sDefault    (I) Default value if the entry is blank or does not exist.
'           sIniFile    (I) Name of the INI file to get the string from.
' Returns:  The requested string or the default passed.
' See Also: IniPrivateWriteString()
' Notes:    Do not use this function unless you want to use an INI file other
'           than the standard INI file for your application.
'------------------------------------------------------------------------------
Private Function IniPrivateGetString(sSection As String, sKey As String, sDefault As String, sIniFile As String) As String
     On Error Resume Next

     Const INI_BUF_SIZE = 255
     Dim cch As Integer
     Dim sBuf As String

     sBuf = String$(INI_BUF_SIZE + 1, 0)

     cch = GetPrivateProfileString(sSection, sKey, sDefault, sBuf, INI_BUF_SIZE, sIniFile)
     IniPrivateGetString = C2ABStr(sBuf)

End Function

'------------------------------------------------------------------------------
' Function: IniPrivateWriteString()
'
' Purpose:  Write a string to specified INI file at the requested section and key.
' Params:   sSection    (I) Section in the INI file to write to (e.g. Options).
'           sKey        (I) Entry within the requested section (e.g. Option1).
'           sValue      (I) String to write into the entry.
'           sIniFile    (I) Name of the INI file to write the string to.
' Returns:  TRUE on success, else FALSE.
' Notes:    Do not use this function unless you want to use an INI file other
'            than the standard INI file for your application.
'           If sKey is empty, all keys for the specified section are deleted.
' See Also: IniPrivateGetString()
'------------------------------------------------------------------------------
Private Function IniPrivateWriteString(sSection As String, sKey As String, sValue As String, sIniFile As String) As Boolean

     On Error Resume Next

     If (Len(sKey) > 0) Then
         IniPrivateWriteString = (WritePrivateProfileString(sSection, sKey, sValue, sIniFile) <> 0)
     Else
         '----- Delete all keys in this section

         IniPrivateWriteString = (WritePrivateProfileString(sSection, vbNullString, sValue, sIniFile) <> 0)
     End If
End Function

'------------------------------------------------------------------------------
' Function: IniWriteBool
'
' Purpose:  Write a boolean value to the INI file.
' Params:   sSection    (I) Section name
'           sKey        (I) Key name
'           bValue      (I) Value to set
' Notes:    TRUE and FALSE are stored as "Yes" and "No" strings respectively.
' Returns:  TRUE on success, else FALSE.
' See also: IniGetBool(), IniWriteInt(),
'           IniWriteRect(), IniWriteString().
'------------------------------------------------------------------------------
Public Function IniWriteBool(sSection As String, sKey As String, bValue As Boolean) As Integer
     On Error Resume Next
     IniWriteBool = IniWriteString(sSection, sKey, IIf(bValue, "Yes", "No"))
End Function

'------------------------------------------------------------------------------
' Function: IniWriteInt
'
' Purpose:  Write an integer value to the INI file.
' Params:   sSection    (I) Section name
'           sKey        (I) Key name
'           nValue      (I) Value to write
' Returns:  TRUE on success, else FALSE.
' See also: IniGetInt(), IniWriteBool(), IniWriteRect(), IniWriteString().
'------------------------------------------------------------------------------
Public Function IniWriteInt(sSection As String, sKey As String, nValue As Integer) As Boolean
     On Error Resume Next
     IniWriteInt = IniPrivateWriteString(sSection, sKey, CStr(nValue), sIniFile)
End Function

'------------------------------------------------------------------------------
' Function: IniWriteString
'
' Purpose:  Write a string to the INI file.
' Params:   sSection    (I) Section name
'           sKey        (I) Key name
'           sValue      (I) Value to write
' Returns:  TRUE on success, else FALSE
' See also: IniGetString(), IniWriteBool(), IniWriteInt(),
'           IniWriteRect().
'------------------------------------------------------------------------------
Public Function IniWriteString(sSection As String, sKey As String, sValue As String) As Boolean
     On Error Resume Next
     IniWriteString = IniPrivateWriteString(sSection, sKey, sValue, sIniFile)
End Function

Public Function IniGetSectionItems(sSection As String, sDefault As String) As String
     On Error Resume Next
     IniGetSectionItems = IniPrivateGetSectionItems(sSection, sDefault, sIniFile)
End Function

Private Function IniPrivateGetSectionItems(sSection As String, sDefault As String, sIniFile As String) As String
     On Error Resume Next

     'TBD can't count on this being enough space!
     '   Maybe do an LOF(filename) first?  or read cch and loop?

     Const INI_BUF_SIZE = 1024
     Dim cch As Integer
     Dim sBuf As String

     sBuf = String$(INI_BUF_SIZE + 1, 0)

     cch = GetPrivateProfileValues(sSection, 0&, sDefault, sBuf, INI_BUF_SIZE, sIniFile)

     cch = InStr(sBuf, vbNullChar & vbNullChar)
     sBuf = Left$(sBuf, cch + 1)

     IniPrivateGetSectionItems = sBuf

End Function

-------file ModINI.bas---------

Attribute VB_Name = "modINI"
'---------------------------------------------------------------------------------------
' Module    : modINI
' DateTime  : 5/20/06 18:11
' Author    : Bob
' Purpose   :
'---------------------------------------------------------------------------------------

Option Explicit

Public Declare Function GetPrivateProfileInt Lib "kernel32.dll" Alias "GetPrivateProfileIntA" (ByVal lpApplicationName As String, ByVal lpKeyName As String, ByVal nDefault As Long, ByVal lpFileName As String) As Long
Public Declare Function GetPrivateProfileString Lib "kernel32.dll" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Long, ByVal
lpFileName As String) As Long
Public Declare Function GetPrivateProfileValues Lib "kernel32.dll" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal nZero As Long, ByVal sDefault As String, ByVal lpReturnedString As String, ByVal MaxSize As Integer, ByVal
FileName As String) As Long
Public Declare Function WritePrivateProfileString Lib "kernel32.dll" Alias "WritePrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpString As Any, ByVal lpFileName As String) As Long

Private Const me_debug = " modINI "
#If False Then  'removed by compiler
Dim end_of_declarations
#End If
'

'

'------------------------------------------------------------------------
' Function: C2ABStr
'
' Purpose:  Convert a C string (NULL terminated) to a BASIC string.
' Params:   sCString  (I) C string to convert.
' Returns:  The converted string.
'------------------------------------------------------------------------
Function C2ABStr(sCString As String) As String

     On Error Resume Next

     Dim nPos As Integer

     nPos = InStr(sCString, Chr$(0))             ' Find the Null terminator.

     If nPos Then                                ' If Null terminator exists...
         C2ABStr = Left$(sCString, nPos - 1)     ' extract the string.
     Else                                        ' Otherwise...
         C2ABStr = sCString                      ' return the string "as is".
     End If

End Function


'---------------------------------------------------------------------------------------
' Procedure : CheckCommand
' DateTime  : 5/20/06 16:54
' Author    : Bob
' Purpose   :
'---------------------------------------------------------------------------------------
'
Public Sub CheckCommand(oINI As CINI)
'reads command$ to override default INI filename
'   some command$ rules:
'       leading space ignored
'       if first charater is dash, then all parameters must be
'           delimited by [space]dash-token-space
'           in which case we only care about " -i " or RE "^-i "
'*****this is only a prototype - just use the whole string

Dim cs As String

    On Error GoTo CheckCommand_Error

     cs = LTrim$(Command$)
     If Len(cs) Then
         oINI.INIFileName = cs
     Else
         'default
         oINI.INIFileName = oINI.AppIniFileName
     End If

'TBD add a verify step where we read one of the critical INI values,
'   and if that's not found, then try the default filename next

    On Error GoTo 0
    Exit Sub

CheckCommand_Error:

     LogError "Error " & Err.Number & " (" & Err.Description & ") in procedure CheckCommand of Module modINI"

End Sub




--
Author
2 Mar 2007 8:56 AM
Johan_Stäck
For tricky situations like this one I have had good results with Vbtracer:
http://www.vbaccelerator.com/home/vb/code/Techniques/RunTime_Debug_Tracing/article.asp

You do pay a performance penalty, but much less than when appending data
to a log file (which I have also tried on a couple of occasions).

/Johan
Author
2 Mar 2007 2:29 PM
Ralph
"Johan Stäck" <jo***@stack.se> wrote in message
news:Ol5ygiKXHHA.5108@TK2MSFTNGP06.phx.gbl...
> For tricky situations like this one I have had good results with Vbtracer:
>
http://www.vbaccelerator.com/home/vb/code/Techniques/RunTime_Debug_Tracing/article.asp
>
> You do pay a performance penalty, but much less than when appending data
> to a log file (which I have also tried on a couple of occasions).
>
> /Johan

In conjunction with this excellent advice you might want to consider
replacing Dr. Watson with a more comprehensive debugger....
http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx

Also take a look at DebugView at
http://www.microsoft.com/technet/sysinternals/miscellaneousutilities.mspx
(This site contains a wealth of useful debugging tools - download all of
them while they are still free. <g>)

-ralph
Author
6 Mar 2007 3:33 AM
Paul Lambert
Paul Lambert wrote:
Show quoteHide quote
> System is a windows 2000 server machine, 2Gb ram, 40Gb hard drive - most
> unused.
>
> I have an application written in VB6 which receives messages from a 3rd
> party program called DMQ (DECMessageQ - developed by HP to transfer
> messages between different OS's. In my case passing messages from
> OpenVMS to Windows) and using an ODBC connection over DAO pipes the data
> received into a PostgreSQL database.
>
> After receiving a number of messages and updating the database, which is
> working perfectly, the application shuts itself down without any errors
> written to the log or showing on-screen - I do however get a DrWatson in
> the eventlog suggesting an access violation.
>
> I've added some debug code by way of some extra writes to the logfile to
> try narrowing down where it is crashing, but my problem is that the
> writes don't seem to get cleared into the file from memory, thus I have
> incomplete information in the logfile that does not show up to the point
> of the actual failure, so I'm having some trouble finding exactly where
> the error is coming from.
>
> Is there any way after doing a write statement to flush the buffers and
> get the write actually commited to the file on disk?
>
> The file is being opened with the following command:
>
> Open App_Path + STRLOGFILENAME For Append Access Write Shared As log_file
>
> And writes are being done with the following function:
>
> Public Sub log_message(error_text As String)
> On Error GoTo finish
>
>     Write #log_file,
>     Write #log_file, Now & " " & error_text
>     'Would like to put some sort of flush command here??
> finish:
>
> End Sub
>
> Any thoughts or suggestions would be appreciated.
>
> Thanks,
> Paul.
> --
> Paul Lambert
> Database Administrator
> AutoLedgers
>

I've change the program to open and close the logfile anytime it does a
write, so I've been able to narrow down exactly where the problem is..
and it is the following line of code:

             Call debug_message(60, "  + updating table")
             table.Update
             Call debug_message(60, "  - updating table")

"> + updating table" is the last line i get in the logfile each time the
program terminates, and I'm getting an access violation in the event
viewer, indicating that table.Update is the cause of the problem.

If the record in question exists in the database already and I am merely
updating it, then it works fine, however if I am adding a new record to
the database it goes bye bye.

Relevant code follows:

         Set table = autodrs_db.OpenRecordset _
             (criteria, dbOpenDynamic, 0, dbOptimistic)
         If table.RecordCount = 0 Then
             Call debug_message(60, "Record not found, adding new")
             task = "Add"
             table.AddNew
         Else
             Call debug_message(60, "Record found, updating")
             task = "Update"
             table.Edit
         End If

         lngStatusDB = load_xxx_to_db(table_name, table, keyname,
keyname2, keyname3, keyname4, keyname5)
         Call debug_message(60, "  - load_xxx_to_db exit status " +
Str(lngStatusDB))
         If lngStatusDB = 0 Then
             Call debug_message(60, "  + updating table")
             table.Update
             Call debug_message(60, "  - updating table")
         Else
             table.CancelUpdate
             load_xxx = lngStatusDB
             GoTo subroutine_exit
         End If

The load_xxx_to_db function parses the received data and sets it into
the appropriate field in the table with lines such as
table(field_name(indexx)) = field_contents(indexx)

Can anyone offer some thoughts on why I would be getting an access
violation now? This part of code has been functioning fine for years!

I am using DAO 3.6 for connections.

Thanks for any assistance you can offer.

Regards,
Paul.

--
Paul Lambert
Database Administrator
AutoLedgers

--
Posted via a free Usenet account from http://www.teranews.com