问题
My problem is simple, I have an event declared in a VB6 library that passes out a boolean argument:
Public Event WriteComplete(ByVal aCommsOk As Boolean, ByVal aBadPIN As Boolean)
I have hooked my c# code up to this event many times but bizarrely my testing department and a couple of other ppl have noticed that although VB6 raises this event with aBadPIN set to false, the c# event handler receives it as true. It is not consistent so it's one of 'those' problems but I'm not finding anything on the internet to help much.
I have found that if I define a new event that converts the bool to a byte and sends that, then it's converted back in the c#, this fixes the issue on those problem machines. However, I really don't want to have to do that since I would have to do it for every single bool that gets marshaled between my COM and .Net libraries (and there's a lot of them).
I also read somewhere that there's a known bug (at least in C++) where you have to force the EAX register to 255 to properly represent false but I've never had this problem before and frankly wouldn't know where to start doing that in VB6 anyway.
Any ideas would be great!
Update: Logging has shown that when this issue occurs the call that raises the event returns control to the VB6 code before the c# event handler fires. What is up with that?
Update: Still seeing event handler receiving event after the raising code has exited but tried marshaling changes to no avail. Time constraints will force me to add a wrapper sadly.
回答1:
Sorry that the problem wasn't as simple as bit-wise Boolean stuff in VB6 world.
If the problem is marshalling, is it possible that the interop DLL that .NET makes is somehow out of sync with its respective VB6 DLL? (As an aside, are you familiar with the Binary Compatibility settings in VB6?)
For the giggles, I did the following - please let me know if this simple set of projects is a representative model for the coding or marshalling issue you are tracking. If this issue is marshalling, it might be helpful to work it through simplified versions of the c# and vb6 projects in tracking it down.
With VB6, I created a simple ActiveX DLL (project named LibBoolBuster), with a class called BoolBuster:
Public Event WriteComplete(ByVal aCommsOk As Boolean, ByVal aBadPIN As Boolean)
Public Sub DoIt(ByVal Mode As Integer)
RaiseEvent WriteComplete(CBool(Mode And 1), CBool(Mode And 2))
End Sub
With VS2003 (old .NET, but should still apply), I created a simple C# Windows app, having a form with four buttons, and making reference to the above VB6 ActiveX DLL. I made a member in the form that accesses the VB6 DLL:
public LibBoolBuster.BoolBuster vb6Obj = new LibBoolBuster.BoolBuster();
DLL via Interop is LibBoolBuster; class BoolBuster has event and DoIt member. In the form initialize, the event hookup is done like so:
vb6Obj.WriteComplete += new LibBoolBuster.__BoolBuster_WriteCompleteEventHandler(vb6Obj_WriteComplete);
The WriteComplete event handler is a member of the form:
private void vb6Obj_WriteComplete ( System.Boolean aCommsOk , System.Boolean aBadPIN )
{
MessageBox.Show(aCommsOk.ToString() + ", " + aBadPIN.ToString());
}
Each button click event handler makes a simple call to DoIt:
vb6Obj.DoIt(0);
(and vb6Obj.DoIt(1), vb6Obj.DoIt(2), etc.)
Very simple project: Click a button, DoIt is called, event WriteComplete is fired. I gave it a try, and things worked as expected.
Take a close look on the VB6 side. You indicated the event is raised with:
RaiseEvent WriteComplete(aCommsReceived, Not (aIsAcknowledged))
Make sure that aIsAcknowledged is only either 0 or -1; otherwise you will not get the result you're expecting.
VB6 Boolean operators are all bitwise; i.e. (Not 1) results in -2 not zero.
Also, in VB6 any non-zero integer will be mapped to True when converting from Integer to Boolean - only zero becomes false.
来源:https://stackoverflow.com/questions/8975403/vb6-event-passing-bool-argument-thats-always-true-in-c-sharp