Tuesday, July 19, 2011

COM ByteArray and Dynamic type issues in .NET

In .NET 4.0 the dynamic type has made it A LOT easier to work with COM interop components.  I'm still working quite a bit with customers that need to work with FoxPro COM objects in .NET and there are some extra fun issues to deal with when working with COM SafeArrays (byte arrays) returned from a COM client. Currently I'm working with a customer who needs to work with Web Services that publish and capture a lot of binary data. A couple of interesting things came up when returning byte arrays over COM to .NET via a dynamic type.

I've written about COM binary arrays before in a previous post. The issue is that when you make a COM call to retrieve a binary result from a COM object the result gets returned as byte[*] type rather than byte[].

To demonstrate imagine you have a simple COM client that returns a binary result as a SafeArray of bytes. The following dumbed down example is a FoxPro method in  COM published component where an object is returned that contains a ByteResult property that holds binary data:

************************************************************************
*  SendBinaryFile
****************************************
FUNCTION SendBinaryFile(lcPath)
LOCAL lvBinary, lcBinary, loResult as ServiceResult

TRY
    *** Grab the file from disk into a string
    lcBinary = FILETOSTR(lcPath)

    *** Turn the string to binary - over COM this turns into a SAFEARRAY
    lvBinary = CREATEBINARY(lcBinary)  && OR CAST(lcBinary as Q)

    *** Return value is standard Service Response object
    loResult = CREATEOBJECT("ServiceResult")

    *** Attach the binary response to the ServiceResult
    loResult.ByteResult = lvBinary
CATCH TO loException
    loResult = this.ErrorToServiceResult(loException,20)
ENDTRY

RETURN loResult
ENDFUNC

The interesting part in relation to this post is the binary result which in this case is the content of a file. Internally FoxPro treats binary values as strings since it's stuck with ANSI codepages, so string can easily contain binary data. However FoxPro cannot return that string as a binary value over COM. In order to return a binary value the value needs to be explicitly converted using CREATEBINARY() or CAST(val as Q) which turns it into a SAFEARRAY when passed back over COM. This binary value is then assigned to a ServiceResult object that returns actual result value(s) back to the .NET Web Service which in turn publishes these values through the Service interface.

Read more: Rick Strahl blog
QR: COM-ByteArray-and-Dynamic-type-issues-in-NET

Posted via email from Jasper-Net