Search code examples
c#wcfvb6com-interopsta

COM Interop AccessViolationException intermittently WCF Callback


We have a .NET 4 based service that self hosts a WCF service with callbacks. We encapsulate this service in a .NET 4 dll that exposes COM objects. This service is used by a large variety of clients, the majority being .NET based.

Unfortunately we have some VB6 clients that we can not change and we are getting AccessViolationExceptions when some callback methods are invoked.

The way the service is structured is with callbacks is illustrated below.

MethodA invoked by VB6 Client, proxied through the .NET dll to the WCF service (has not returned yet)

WCF CallbackA invoked providing Enum status values

Possibly WCF CallbackB will be invoked requiring further input from the VB6 Client (This information can not be obtained at the start of MethodA and impacts the outcome of MethodA)

MethodA Returns

CallbackA (Works great, no Exceptions!) it is a OneWayOperation that provides an Enum, the VB application currently is writing this value to a RichTextbox.

CallbackB (Causes an AccessViolationException) is a Method that provides an object and expects a different object back with two value based properties back.

I feel this is some sort of an issue with attempting to create COM objects on a different thread than the main thread (since its currently hanging on MethodA). Unfortunately I am not sure how to correct this. We have control over the code within the service, the encapsulating dll and we can advise on code within the VB6 client.

We have our own VB6 testing application and we can bypass the AccessViolation error.... but it involves commenting out any code within the callback method (See code below) I have highlighted the lines that are causing the exception if left in "<----- Causes Exception". Any help is much appreciated, please let me know if you need more information.

Private Function ITerminalCallbackComClient_VerifySignature() As Long
Dim result As Long

'Not-Authorized = 0 and Authorized = 1'
result = 0

Dim msgResponse As Long

msgResponse = MsgBox("Signature Accepted?", vbYesNo + vbQuestion, "Signature Verification")

If msgResponse = vbYes Then
    result = 1
End
End If

ITerminalCallbackComClient_VerifySignature = result
End Function

UPDATE 2014-11-13

The callback works while debugging in Visual Studio 6. But as soon as we "Make" the sample project it crashes when the callback is executed. If we remove the reference to the MsgBox and just map back a static value, it works as expected.

We have updated the Signature to our COM Interop to remove all object references and are not just returning a 0 or 1 to avoid object naming issues.

I have updated the VB6 callback code above.

Callback Contract

[CallbackBehaviorAttribute(ConcurrencyMode = ConcurrencyMode.Reentrant, UseSynchronizationContext = false)]
public abstract class PS_Terminal_Link_Callback : ITerminalCallback
{

public abstract long VerifySignature();

}

Service Contract

[ServiceContract(CallbackContract=typeof(ITerminalCallback))]
public interface ITerminal
{
   *MethodA*
}

Solution

  • If that is VB6 code, LONG is a win32 integer in VB6. For compatability with 16 bit basic integers are 16 bit in VB6. Longs are 32 bit. You are putting a VB6 long (32 bit) into a VB6 integer (16 bit) in the message box line.

    Your other object is private to you so we can't look up it's specs and docs.