West Wind .NET Tools and Demos
Passing Object from VFP to .NET via COM / wwDotnetBridge
Gravatar is a globally recognized avatar based on your email address. Passing Object from VFP to .NET via COM / wwDotnetBridge
  Manni Borg
  All
  Nov 22, 2021 @ 10:31am

Dear experts,

I'm using wwDotnetbridge to call a COM / DLL created with C#, but having trouble passing an object to .NET.

I have to call the class SendMessages() to send for example two messages. In order to do that I first have to create two message-objects of the type DataSendMessage, populate it's properties, and then create an array of these two object and pass the array via SendMessages() to the COM module. The last part is where the problem occurs.

In the follwing code I'm creating two messages and trying to send them (I tried to simplify the code and class names to make it more understandable):

DIMENSION arrMessages(2)

loBridge.LoadAssembly("ComInterop.dll")

oMessage1 = loBridge.CreateInstance("ComInterop.DataSendMessage")
oMessage1.documentId = "11d3894c-04b4-45e5-ae0a-37df42c550dd“
oMessage1.Recipient = "test@test.com"
oMessage1.LoadDocumentBytes("C:\Temp\11d3894c-04b4-45e5-ae0a-37df42c550dd.xml")

arrMessages(1) = oMessage1

oMessage2 = loBridge.CreateInstance("ComInterop.DataSendMessage")
oMessage2.documentId = "05d60f20-4b17-4b3a-9a86-7911436666cf“
oMessage2.Recipient = "test@test.com"
success = oMessage2.LoadDocumentBytes("C:\Temp\05d60f20-4b17-4b3a-9a86-7911436666cf.xml")  && returns .T.

arrMessages(2) = oMessage2

com = loBridge.CreateInstance("ComInterop.Operations")
success = com.SendMessages(nWindowHandle, cCardHandle, cUserId, arrMessages)

When executing the last line, the COM module throws the exception that the parameter arrMessages is incorrect. When debugging, the VFP array arrMessages consists of two objects and the properties of each object have the correct values which were assigned to them before (only the property LoadDocumentBytes has no value, but when calling LoadDocumentBytes() it returned .T., so I suspect that's not the cause of the problem).

Here is what .NET Reflector is telling about the classes:

[return: MarshalAs(UnmanagedType.SafeArray)]
public DataSendMessage[] SendeMessages(int windowHandle, string cardHandle, string userId, [MarshalAs(UnmanagedType.LPArray)] DataSendMessage[] messages)
{
...
}
   [ClassInterface(ClassInterfaceType.AutoDual), Guid("..."), ComVisible(true)]
   public class DataSendMessage
   {
       // Methods
       public DataSendMessage();
       public DataSendMessage(TMS.Models.DataSendMessage message);
       public DataSendMessage(string documentId, string documentAsByteFile, string recipient);
       public DataSendMessage ConvertInt();
       public bool LoadDocumentBytes(string documentAsByteFile);

	// Properties
       public string DocumentId { get; set; }
       public byte[] Document { get; set; }
       public string Recipient { get; set; }
       public bool MessageSend { get; set; }
       public string MessageSendErrorMsg { get; set; }
   }



What do I have to do differently?

Thanks, Manni

Gravatar is a globally recognized avatar based on your email address. re: Passing Object from VFP to .NET via COM / wwDotnetBridge
  Rick Strahl
  Manni Borg
  Nov 22, 2021 @ 10:02pm

For the array you need a use a ComArray() using loBridge.CreateArray() to create each of the messages in the array to pass to the method. YOu need to use InvokeMethod() to call the method and pass the ComArray you created as the parameter for the array.

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: Passing Object from VFP to .NET via COM / wwDotnetBridge
  Manni Borg
  Rick Strahl
  Nov 22, 2021 @ 11:59pm

Hi Rick,

thank you very much for your answer!

I was trying to follow your adivce using CreateArray() and InvokeMethod():

oBridge.LoadAssembly("ComInterop.dll")
loItems = loBridge.CreateArray("ComInterop.DataSendMessage")

loItem1 = loItems.CreateItem()
loItem1.documentId = "11d3894c-04b4-45e5-ae0a-37df42c550dd"
loItem1.Recipient = "test@test.com"
loItem1.LoadDocumentBytes("C:\Temp\11d3894c-04b4-45e5-ae0a-37df42c550dd.xml")

loItem2 = loItems.CreateItem()
loItem2.documentId = "05d60f20-4b17-4b3a-9a86-7911436666cf"
loItem2.Recipient = "test@test.com"
loItem2.LoadDocumentBytes("C:\Temp\05d60f20-4b17-4b3a-9a86-7911436666cf.xml")

loItems.Add(loItem1)  && COM returns an exception: Unknown name
loItems.Add(loItem2)  && COM returns an exception: Unknown name

loInstance = loBridge.CreateInstance("ComInterop.Operations")
loBridge.InvokeMethod(loInstance,"SendMessages", nWindowHandle, cCardHandle, cUserID, loItems)

I get an error when adding the items to the array with Add(). The command loItem1.LoadDocumentBytes("C:\Temp\05d60f20-4b17-4b3a-9a86-7911436666cf.xml") returns true, but in the VFP debugger I see that a property called LoadDocumentBytes has been added to loItem1 and loItem2 and value is "The expression could not be evaluated". Maybe this is causing the excpetion?

Also, I don't know if the last part is correct. Is it correct how I added the array together with the other three parameters when calling the SendMessages method?

Thanks, Manni

Gravatar is a globally recognized avatar based on your email address. re: Passing Object from VFP to .NET via COM / wwDotnetBridge
  Rick Strahl
  Manni Borg
  Nov 23, 2021 @ 06:00pm

Not sure.

I understand why you get an exception when trying to read the values - they can't be read from FoxPro directly - you have to use GetProperty() to read them to handle the conversions from binary to something that FoxPro can use.

The method is .AddItem() not .Add() which would account for the unknown name error.

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: Passing Object from VFP to .NET via COM / wwDotnetBridge
  Manni Borg
  Rick Strahl
  Nov 24, 2021 @ 12:03am

Hi Rick, I'm having trouble understanding what you mean, how to use GetProperty() in this case. Could you please give me an example how to apply it to my code above?

Should I use AddItem() instead of Add()?

Thanks a lot, Manni

Gravatar is a globally recognized avatar based on your email address. re: Passing Object from VFP to .NET via COM / wwDotnetBridge
  Rick Strahl
  Manni Borg
  Nov 25, 2021 @ 12:29pm

There's no Add() method. That's why you're getting the error.

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: Passing Object from VFP to .NET via COM / wwDotnetBridge
  Manni Borg
  Rick Strahl
  Nov 25, 2021 @ 02:40pm

Rick, using AddItem() instead of Add() indeed solves the "Unknown name" error, thanks! 😃 I was using Add() because it was used in the example on the site you posted a link to: https://webconnection.west-wind.com/docs/_3m90jxxxm.htm.

But still the line loBridge.InvokeMethod(loInstance,"SendMessages", nWindowHandle, cCardHandle, cUserID, loItems) gives an error.

So that you can see the whole code again now:

oBridge.LoadAssembly("ComInterop.dll")
loItems = loBridge.CreateArray("ComInterop.DataSendMessage")

loItem1 = loItems.CreateItem()
loItem1.documentId = "11d3894c-04b4-45e5-ae0a-37df42c550dd"
loItem1.Recipient = "test@test.com"
success = loItem1.LoadDocumentBytes("C:\Temp\11d3894c-04b4-45e5-ae0a-37df42c550dd.xml") && this command leads to success = .T. but loItem1 receives a property called LoadDocumentBytes with value "expression could not be evaluated" (as can be seen in the debugger, I translated the message from German).

loItems.AddItem(loItem1)  && no more error

loInstance = loBridge.CreateInstance("ComInterop.Operations")
loBridge.InvokeMethod(loInstance,"SendMessages", nWindowHandle, cCardHandle, cUserID, loItems)  && Exception from the C# DLL, no error from VFP, because of loItems.
public DataSendMessage[] SendeMessages(int windowHandle, string cardHandle, string userId, [MarshalAs(UnmanagedType.LPArray)] DataSendMessage[] messages)
{
...
}

   public class DataSendMessage
   {
       // Methods
       public DataSendMessage();
       public DataSendMessage(TMS.Models.DataSendMessage message);
       public DataSendMessage(string documentId, string documentAsByteFile, string recipient);
       public DataSendMessage ConvertInt();
       public bool LoadDocumentBytes(string documentAsByteFile);

	// Properties
       public string DocumentId { get; set; }
       public byte[] Document { get; set; }
       public string Recipient { get; set; }
       public bool MessageSend { get; set; }
       public string MessageSendErrorMsg { get; set; }
   }

Is there a different way to call loItem1.LoadDocumentBytes("C:\Temp\11d3894c-04b4-45e5-ae0a-37df42c550dd.xml")? As this might be the reason why the last command is not working?

Thanks, Manni

Gravatar is a globally recognized avatar based on your email address. re: Passing Object from VFP to .NET via COM / wwDotnetBridge
  Rick Strahl
  Manni Borg
  Nov 26, 2021 @ 11:35pm

What error exactly?

If it's a generic type error that means the values passed are not of the right type potentially. If it's another error then the code in the called method might be failing and that's a different story.

+++ Rick ---

Gravatar is a globally recognized avatar based on your email address. re: Passing Object from VFP to .NET via COM / wwDotnetBridge
  Manni Borg
  Rick Strahl
  Nov 29, 2021 @ 12:16pm

Rick, I found a workaround by using another function, but I have to get back to this soon to fully understand what went wrong...

Thanks, Manni

© 1996-2021