Solved

DCOM - Dr. Watson (access violation) Error

Posted on 2001-06-07
22
509 Views
Last Modified: 2010-05-18
Hi,

I have a Asynchronous DCOM application with the following Architecture:

VB Client on User Machine(WinNT4.0Workstation)
VB ActiveX Exe on NT4.0Server

When I call a method in ActiveX Server, everything works fine and I get Successful message, then my form in the Client program closes.  At this point Dr.Watson Error pops up on the NTServer Machine.

Actual Error on the NTServer:

An applicaton error has occurred
and an application error log is being generated.
SunchronizeExch.exe
Exception: access violation(0xc0000005), Address:0x5177a600

This error occurs as soon as I close the form, which has DCOM calls, that means, the error is happening as soon as I close the reference to DCOM.

I searched MSDN, and found an article Q272373, it says I need to install WIN2000SP, but mind is WINNT, so, I installed latest MDAC(2.5 SP2), but I am still getting this error.

Any Comments/Ideas/Suggestions?

Chandu
0
Comment
Question by:chandukb
  • 11
  • 6
  • 2
  • +3
22 Comments
 
LVL 1

Expert Comment

by:tommy_boy
ID: 6166458
I would need to see your code on the server object.  Also I need to know are you calling any functions/methods in modules from the Public Method/Function on the server object?  Also, what is your threed pool?  Also, your 'connecting' class - how is it defined - single use - multi use - PUBLIC NOT CREATABLE etc.

Off the top of my head, your connecting class is mutli use and you are calling a global function inside a bas module from your public class.  This would cause two instances of code to collide when more than one client tries to connect to the object.  Another symptom would be that the memory violation error would occur at different times if this was the case.

My advice - get rid of the bas modules.
0
 
LVL 1

Expert Comment

by:morgan_peat
ID: 6166979
How is your asynch code running?
If you do not close down that properly, then it may still be running when you release your objects.
If it's a timer or something like that, it might be trying to call back to your app when there is nothing there to receive the callback.

Try putting some sort of Public Sub AsychStop() method in your object, rather than relying on Class_Terminate().

(Because Class_Terminate(), by definition, fires when there are no outstanding references on your object left, so by the time it fires, there is nothing left to handle callback events).
0
 
LVL 2

Author Comment

by:chandukb
ID: 6167590
My clsSync Class:
----------------

Option Explicit

Public Event ProcessComplete(blnSuccess As Boolean, strString As String)
'Timer Component
Private WithEvents tmrEvent As ccrpTimer
Dim strHelloString As String
Dim strErrorString As String


I am Calling the below method from my Client:
--------------------------------------------

Public Sub RunAsync(lstrProc As String)
On Error GoTo ErrHandler

'New Timer object
Set tmrEvent = New ccrpTimer

With tmrEvent
   .EventType = TimerOneShot 'Fire only once
   .Interval = 10000 'After 10 seconds
   .Tag = lstrProc 'Procedure to be called
   .Enabled = True 'Start Timer
End With

Exit Sub
ErrHandler:
'Err.Raise Err.Number, Err.Source, Err.Description

End Sub


Private Sub Class_Initialize()
'gDAS, and gLOG are global variables declared in my bas module

strErrorString = ""
If gDAS Is Nothing Then
    Set gDAS = New clsDAS
End If

If gLOG Is Nothing Then
    Set gLOG = New clsLOG
End If
End Sub


Private Sub Class_Terminate()
If Not tmrEvent Is Nothing Then
    Set tmrEvent = Nothing
End If
If Not gDAS Is Nothing Then
    Set gDAS = Nothing
End If
If Not gLOG Is Nothing Then
    Set gLOG = Nothing
End If
End Sub


Private Sub tmrEvent_Timer(ByVal Milliseconds As Long)
'Timer Event to start different methods
On Error GoTo ErrHandler

Dim lstrString As String
Dim lblnSuccess As Boolean

Select Case tmrEvent.Tag

    Case "SayHelloToClientAsync" 'Say Hello to Client
   
        Call gDAS.ActivateConnection 'Open Connection
        Call gDAS.LockUnlockDB("T") ''LockDatabase, just updates a flag in a table

        'Start the processing
        lblnSuccess = SayHelloToClientAsync
        If lblnSuccess = True Then
            lstrString = strHelloString
        Else
            lstrString = "Hello To Client Failed." & vbCrLf & strErrorString
        End If
       
        Call gDAS.LockUnlockDB("F") 'Unlock Database 'releases a flag in a table
        Call gDAS.DeActivateConnection 'Close Connection

End Select

RaiseEvent ProcessComplete(lblnSuccess, lstrString)

Exit Sub
ErrHandler:
'Err.Raise Err.Number, Err.Source, Err.Description

End Sub


Public Function SayHelloToClientAsync() As Boolean
'This Function is just for test
On Error GoTo ErrHandler

Dim lstrBuff As String * 25
Dim llret As Long
Dim lstrComputerName As String

Dim lcv As Long

' Get the Computer Name minus any trailing spaces found in the name.
llret = GetComputerName(lstrBuff, 25)
lstrComputerName = Trim(Left(lstrBuff, InStr(lstrBuff, Chr(0)) - 1))

For lcv = 1 To 20000
    DoEvents
    Debug.Print lcv
Next

strHelloString = "Machine: " & lstrComputerName & vbCrLf & "Status:     Hello! I am an ActiveX and I am Ready."

SayHelloToClientAsync = True

Exit Function
ErrHandler:
SayHelloToClientAsync = False
strErrorString = Err.Description

End Function



My Client Clode as follows:
--------------------------

Private WithEvents MySyncObj As SynchronizeExchange.clsSync

Private CallX()

Set MySyncObj = CreateObject("SynchronizeExchange.ClsSync", lstrComMachineName)
MySyncObj.RunAsync "SayHelloToClientAsync"

End Sub


Private Sub MySyncObj_ProcessComplete(blnSuccess As Boolean, strString As String)
On Error GoTo ErrHandler

MsgBox strString, vbInformation + vbOKOnly, "ActiveX Synchronize Status"

Unload Me
Set frmSynch = Nothing

Exit Sub
ErrHandler:
Screen.MousePointer = vbDefault
MsgBox "Error Description: " & ExtractErrorDescription(Err.Description) & vbCrLf & "Please Call Technical Support.", vbInformation + vbOKOnly, "Location: MySyncObj_ProcessComplete"

End Sub

Private Sub cmdClose_Click()
Unload Me
Set frmSynch = Nothing
End Sub



Please Help.  Thanks a lot.

Chandu

0
 
LVL 1

Expert Comment

by:morgan_peat
ID: 6167675
Do you actually set MySynchObj to Nothing anywhere?
Put 'SetMySynchObj = Nothing' in the sections where you call 'Unload Me'.  This should (hopefully) solve the problem.
0
 
LVL 2

Author Comment

by:chandukb
ID: 6167736
I do have the following code in my form_unload, I even
try this code in the close button, but same error.

If Not MySyncObj Is Nothing Then
    Set MySyncObj = Nothing
End If


Chandu
0
 
LVL 1

Expert Comment

by:morgan_peat
ID: 6167788
OK.  Shot-in-the-dark time here.
Try the same, but don't unload your form in the event.
Get it so you have a fire_async command button, which fires the method off, then waits.
When the event fires (& shows a msgbox, or whatever) have another kill_object button which releases all references to the remote object.
Then have a close / form_unload event to close the app.

Check that that works OK.
If not, try instantiating the remote object, & closing the app (i.e. instantiate it, but don't call any async methods).

Either way, let me know what happens.
0
 
LVL 2

Author Comment

by:chandukb
ID: 6167843
I removed the unload code in my event, and had a new button
to release MySyncObj.  When I click my new button to release the object, same error pops up on the server, so,
as I mentioned earlier, this error occurs as soon as I
release the reference.

And, I commented out my call to remove method, I just instatiated the remote object and close my form and app, no
error occurs.  So, when I call a method, which has ADO calls, this error occurs.

To be make sure I commented out my ADO calls on the server and no error.  Ao, as I mentioned above the Microsoft
article has got to do something.



My Thred Pool on my ActiveX Server is : Thred Pool 1 threds

clsSync in ActiveX has the following properties:
DataBindingBehaviour 0-vbNone
Instancing 5-Multiuse
Persistable 0-NotPersistable

My clsDAS(ADO Methods), clsBAS has Instancing - Private

Chandu
0
 
LVL 3

Expert Comment

by:jrspano
ID: 6167858
what service packs are you running on the client and server?  you might want to upgrade them.
0
 
LVL 1

Expert Comment

by:morgan_peat
ID: 6167893
Your ADO class - how are you using ADO?
The recommended usage is as follows:

Open Connection
Open RS
Close Connection
Use RS
Close RS

Is this how you are using it?
Looking at the knowledge base article, that error should only happen on multiprocessor systems, and only with ADO 2.5.

ADO 2.6 is out now, and there is an SP2 for ADO 2.5 (Q293312, from that article of yours).  I've got 2.5 SP2, and 2.6 on my NT4 w'sn, and it works OK.
0
 
LVL 2

Author Comment

by:chandukb
ID: 6167975
I have latest Service Pack 6a on my both Client and Server Machines.


My ClsDAS CODE:
--------------

Option Explicit

Private moconnection     As ADODB.Connection
Private moCommand       As ADODB.Command    
Private moRecordset     As ADODB.Recordset  

Public Sub ActivateConnection()
On Error GoTo ErrHandler

'Open a Connection to the Database.
If moconnection Is Nothing Then
    Set moconnection = New ADODB.Connection
    moconnection.CursorLocation = adUseClient
End If

'Opening Connection using Net8 configured DLAdmin Service.
moconnection.Open "Provider=MSDAORA;Data Source=" & gstrDSN & ";User ID= " & gstrUserID & ";Password=" & gstrPassword

Exit Sub
ErrHandler:
Call Err.Raise(Err.Number, "clsDAS_ActivateConnection", Trim(Err.Description))

End Sub

Public Sub LockUnlockDB(lstrFlag As String)
On Error GoTo ErrHandler

Dim lrsRecordset As ADODB.Recordset
Dim llngReturnValue As Long
ReDim garyParameterArray(0 To 2)
   
garyParameterArray(0) = gstrLockID
garyParameterArray(1) = lstrFlag
garyParameterArray(2) = llngReturnValue

Set lrsRecordset = gDAS.GetRecordset("USP_TB_DB_INFO_UPD", garyParameterArray, llngReturnValue)
Set lrsRecordset = Nothing
   
Exit Sub
ErrHandler:
Call Err.Raise(Err.Number, "GetRecordset", Trim(Err.Description))

end sub

Public Sub DeActivateConnection()
On Error GoTo ErrHandler

If Not moconnection Is Nothing Then
    moconnection.Close
    Set moconnection = Nothing
End If

Exit Sub
ErrHandler:
Call Err.Raise(Err.Number, "clsDAS_ActivateConnection", Trim(Err.Description))

End Sub

Private Sub Class_Terminate()
If Not moconnection Is Nothing Then
    moconnection.Close
    Set moconnection = Nothing
End If
End Sub


I also installed SP2 for MDAC 2.5 yesterday on my Server, but no luck.

Chandu
0
 
LVL 1

Expert Comment

by:morgan_peat
ID: 6168013
Try keeping the Connection object local to the procedure.
You shouldn't cache connection objects these days.  Let OLE DB do this for you.  Just instantiate & open one whenever you need it, and close it as soon as possible afterwards.

It could be (shot in the dark time again) your connection object staying open that is causing problems(?)

And, you haven't closed your recordset.  do
rs.Close
Set rs = Nothing
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 2

Author Comment

by:chandukb
ID: 6168134
I commented out LockUnlockDB methods, and also commented out openining connection. This is what I have:

Public Sub ActivateConnection()
On Error GoTo ErrHandler

'Open a Connection to the Database.
If moconnection Is Nothing Then
    Set moconnection = New ADODB.Connection
    moconnection.CursorLocation = adUseClient
End If

Exit Sub
ErrHandler:
Call Err.Raise(Err.Number, "clsDAS_ActivateConnection", Trim(Err.Description))

end usb

Public Sub DeActivateConnection()
On Error GoTo ErrHandler

''Open a Connection to the Database.
If Not moconnection Is Nothing Then
    Set moconnection = Nothing
End If

Exit Sub
ErrHandler:
Call Err.Raise(Err.Number, "clsDAS_ActivateConnection", Trim(Err.Description))

End Sub

Private Sub Class_Terminate()
If Not moconnection Is Nothing Then
    Set moconnection = Nothing
End If
End Sub

Then, I call

        Call gDAS.ActivateConnection 'Open Connection

        'Start the processing
        lblnSuccess = SayHelloToClientAsync
        If lblnSuccess = True Then
            lstrString = strHelloString
        Else
            lstrString = "Hello To Client Failed." & vbCrLf & strErrorString
        End If
       
'        Call gDAS.LockUnlockDB("F") 'Unlock Database
        Call gDAS.DeActivateConnection 'Close Connection


0
 
LVL 2

Author Comment

by:chandukb
ID: 6168138
The above code works, because I am not opening any connection, just instantiate connection object and close, no dr.watson, so what should I do, I must open a connection to do some processing.

Chandu'
0
 
LVL 1

Expert Comment

by:morgan_peat
ID: 6168255
Try:
1. Make ActivateConnection & DeActiveConnection Private within the class.  Whatever method you call within the class, let it call active/deactivate itself.  Nothing outside your class should be able to say when or when not to connect to a DB.  This may mean that you open/close a connection several times, but this is the Microsoft recommended way :-)

2. Ensure that you call oConnection.Close every time you have finished with a connection, and oRS.Close every time you have finished with a recordset.  This is how ADO knows that you have finished with them.
0
 
LVL 2

Author Comment

by:chandukb
ID: 6168810
No Luck.

I made ActivateConnection, and DeActivateConnection Private and calling these two whenever I need to send something to Databse, but still same error, Whenever the
client closes the reference, dr.watson back in action.

Any more ideas/suggestions.

Chandu
0
 
LVL 3

Accepted Solution

by:
Joebob earned 50 total points
ID: 6177933
Looking at the code you initially posted, it doesn't look like you stop the timer in the tmrEvent_Timer.  I suggest that you disable the ccrpTimer as one of the first things you do in the tmrEvent_Timer function.  It is possible that there is a race condition between when you destroy your class and when the next timer event fires.  If this is the case, stopping the timer should solve the problem.

P.S.  If this helps, accept it as a solution but reduce the points.  I already have enough of your points.
0
 
LVL 2

Author Comment

by:chandukb
ID: 6186659
Joebob,  Thanks a lot, It worked.  I just have a question for u.

When I Call a DCOM method and close the Client app. immediately, nothing happens, the method I called didn't executed.  What happened to my call, is my client app. must
be open until DCOM method finishes?  I thought DCOM is useful to just kick off remote ActiveXExe's methods.
Please comment on this.

>
>P.S.  If this helps, accept it as a solution but reduce the points.  I already have enough of your points.
>

Appreciated. How do I reduce the question points.

Chandu
0
 

Expert Comment

by:ComTech
ID: 6187123
As you have requested and Expert Joebob agrees, I am reducing the points to 50 with a grade A.

Thank you,
ComTech
Community Support Moderator
0
 
LVL 2

Author Comment

by:chandukb
ID: 6187188
Joebob,  Thanks a lot, It worked.  I just have a question for u.

When I Call a DCOM method and close the Client app. immediately, nothing happens, the method I called
didn't executed.  What happened to my call, is my client app. must be open until DCOM method finishes?  I thought DCOM is useful to just kick off remote ActiveXExe's methods. Please comment on this.

Thanks again for all your help.

Chandu


0
 
LVL 3

Expert Comment

by:Joebob
ID: 6187399
Here is the oder of operations that will be followed for your app.

Client Opens DCOM       ->    Server Starts
Client Runs DCOM Method ->    Server starts ccrpTimer
Server Timer fires      ->    Asynchronous code is executed

If the client closes after the DCOM method call, but before the timer fires, the asychronous code will never run.  If your asynchronous code starts and you include a doevents call, the code will stop at that point.  If your asynchronous code is running and doesn't have any doevents calls, the server shouldn't actually shut down until execution is complete.

How long of a delay do you have the timer set to generate?  I suggest something along the lines of  1 ms.
0
 
LVL 2

Author Comment

by:chandukb
ID: 6187542
Thanks for the input.

>
>How long of a delay do you have the timer set to >generate?  I suggest something along the lines of  
>1 ms
>

I just chaged to 1, and added DOEVENTS to my
RunSync method(this is the one my client calling to activate the timer), then
I added DOEVENTS to my tmrEvent_Timer procedure, which
calls a designated method.

When I start my client, I kicked off DCOM, then try to
close the form, the CLOSE Button depressed and waited few
seconds to respond then form closes, THE DCOME METHOD WORKS, that is what I want, because I have some methods runs about 45 minutes.  

Is there is anyway to close the form immediately, whenever the user hits close button.  I figured that the close button responding late because it is waiting the doevents line in the server to get back to the client, am i right!

Chandu
0
 
LVL 2

Author Comment

by:chandukb
ID: 6187605
As a matter of fact, the close button on the client form is not responding until the DCOM method done, eventhough I have bunch of DOEVENTS statements, i just tested.  But, it works asynchronously, that means I can do other stuff in my client application.  Eventhough I try to hit END button the client, but it waited to respond until the DCOM method done.

Any input.

Thanks
Chandu
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Enums (shorthand for ‘enumerations’) are not often used by programmers but they can be quite valuable when they are.  What are they? An Enum is just a type of variable like a string or an Integer, but in this case one that you create that contains…
Background What I'm presenting in this article is the result of 2 conditions in my work area: We have a SQL Server production environment but no development or test environment; andWe have an MS Access front end using tables in SQL Server but we a…
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…

759 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now