1
votes

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*
}
2
What happens if you move the line Dim request As New... after the End If and split declaration from assignment (i.e., change Dim request As New... to Dim request As PS_Terminal... followed by Set request = New PS_Terminal...)? - Andrew
I will try that, butif I remove all references to the 'request' object it still fails even with just the MsgBox code. If I comment all lines out that involve the 'request' object and the MsgBox the method executes and returns without error... unfortunately this isn't a valid fix. - MVCutter
Thanks. I presume that just commenting out the code from intResponse = MsgBox... to End If still fails? Also, what is the code (presumably .NET or COM) that defines ITerminalCallbackComClient.VerifySignature? - Andrew
Still running into the issue, thanks for the suggestions, I have added the updated code I am running on the VB6 side and the definition of the Service contract and the callback. - MVCutter

2 Answers

0
votes

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.

0
votes

You can also start in a debugger.

windbg or ntsd (ntsd is a console program and maybe installed). Both are also from Debugging Tools For Windows.

Download and install Debugging Tools for Windows

http://msdn.microsoft.com/en-us/windows/hardware/hh852363

Install the Windows SDK but just choose the debugging tools.

Create a folder called Symbols in **C:**

Start Windbg. File menu - Symbol File Path and enter

srv*C:\symbols*http://msdl.microsoft.com/download/symbols

then

windbg -o -g -G c:\windows\system32\cmd.exe /k batfile.bat

You can press F12 to stop it and kb will show the call stack (g continues the program). If there's errors it will also stop and show them.

Type lm to list loaded modules, x *!* to list the symbols and bp symbolname to set a breakpoint

If programming in VB6 then this environmental variable link=/pdb:none stores the symbols in the dll rather than seperate files. Make sure you compile the program with No Optimisations and tick the box for Create Symbolic Debug Info. Both on the Compile tab in the Project's Properties.

Also CoClassSyms (microsoft.com/msj/0399/hood/hood0399.aspx) can make symbols from type libraries.

Put a breakpoint on the COM call (use x *!* to find it).

Now you can examine parameters and/or see detailed exception info.

.