469,607 Members | 2,205 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,607 developers. It's quick & easy.

Passing SAFEARRAY of Bytes from VBScript to Managed COM object (C#

Attempting to pass a VBScript Array of Bytes to a C# Managed COM object has
resulted in some very undesirable and strange behavior. When definining a
method in my C# COM class as "void Write(byte[] bBytes)" or "void
Write(byte[] bBytes, int nLen)" or "int Write(byte[] bBytes, int
nLen)"VBScript returns a "Invalid procedure call or argument" exception.
However when I define the method as "int Write(byte[] bBytes)" it works just
fine. Unfortunately the method definition that works is not the one I need.
Regardless of whether one works or one doesn't work, they should all work.
Does anyone know why the CCW can't handle the method definition, and why it
is behaving in such a flakey manner?

Things I have tried to make it work:
- I have used the appropriate MarshalAs attribute in front of the byte[]
array.
- I have used the [ClassInterface(ClassInterfaceType.None)] attribute with
an explicit interface to make the tlbexp tool explicitly define the interface
methods.
Jul 21 '05 #1
2 13036
Complex types as arrays are expected to be VARIANT's when calling into COM
through COM interop.
So you have to declare them as Object (or ref Object for [in,out]) in
CSharp.

Here's a sample that illustrates this...

// CS file
using System.Runtime.InteropServices;
using System;

// interface
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[Guid("1ab6f6ea-83b5-4b16-934b-fb82d9af8e0a")]
public interface IDotNetInterface
{
int Write( Object aParam1); //[in]VARIANT
}

// class
[ClassInterface(ClassInterfaceType.None)]
[ProgId("Test.DotNetIf")]
public class DotNetInterface : IDotNetInterface
{
public DotNetInterface() {}
public int Write( Object aParam1)
{
foreach(byte b in aParam1 as Array)
Console.WriteLine(b);
return (aParam1 as Array).Length; // Return Array.Length (will be
marshalled as a VARIANT containing an int type)
}
}

'VBS file
On Error Resume Next
Dim o
Dim ar 'Variant
Dim arr(2) 'Array 3 elements
arr(0) = CByte(1) 'add 1 as byte value in element 0
arr(1) = CByte(2)
arr(2) = CByte(3)
ar = arr 'set ar to array
set o = CreateObject("Test.DotNetIf")
r = o.Write (ar) 'pass Variant containing an array of bytes to callee
if Err.Number <> 0 then
Wscript.Echo "Failure :" & Err.Description
else
Wscript.Echo r
end if

Willy.
"Ken Layton" <Ke*******@discussions.microsoft.com> wrote in message
news:E9**********************************@microsof t.com...
Attempting to pass a VBScript Array of Bytes to a C# Managed COM object
has
resulted in some very undesirable and strange behavior. When definining a
method in my C# COM class as "void Write(byte[] bBytes)" or "void
Write(byte[] bBytes, int nLen)" or "int Write(byte[] bBytes, int
nLen)"VBScript returns a "Invalid procedure call or argument" exception.
However when I define the method as "int Write(byte[] bBytes)" it works
just
fine. Unfortunately the method definition that works is not the one I
need.
Regardless of whether one works or one doesn't work, they should all work.
Does anyone know why the CCW can't handle the method definition, and why
it
is behaving in such a flakey manner?

Things I have tried to make it work:
- I have used the appropriate MarshalAs attribute in front of the byte[]
array.
- I have used the [ClassInterface(ClassInterfaceType.None)] attribute with
an explicit interface to make the tlbexp tool explicitly define the
interface
methods.

Jul 21 '05 #2
Note that you can also pass them byval as SAFEARRAY(VARIANT) (Variant array)

//CS file
public interface IDotNetInterface
{
int Write(object[] aParam1);
}
....

public int Write( object[] aParam1) // Object [] == SAFEARRAY(Variant)
{
foreach(byte b in aParam1) // Variant encapsulates a byte
Console.WriteLine(b);
return aParam1.Length;
}

'SCRIPT
Dim ar
Dim arr(2)
arr(0) = CByte(1)
arr(1) = CByte(2)
arr(2) = CByte(3)
ar = arr
WScript.Echo TypeName(arr)
set o = CreateObject("Test.DotNetIf")
r = o.Write ((ar)) 'Pass ar byval
'OR
r = o.Write ((arr)) 'Pass arr byval

Willy.

"Ken Layton" <Ke*******@discussions.microsoft.com> wrote in message
news:E9**********************************@microsof t.com...
Attempting to pass a VBScript Array of Bytes to a C# Managed COM object
has
resulted in some very undesirable and strange behavior. When definining a
method in my C# COM class as "void Write(byte[] bBytes)" or "void
Write(byte[] bBytes, int nLen)" or "int Write(byte[] bBytes, int
nLen)"VBScript returns a "Invalid procedure call or argument" exception.
However when I define the method as "int Write(byte[] bBytes)" it works
just
fine. Unfortunately the method definition that works is not the one I
need.
Regardless of whether one works or one doesn't work, they should all work.
Does anyone know why the CCW can't handle the method definition, and why
it
is behaving in such a flakey manner?

Things I have tried to make it work:
- I have used the appropriate MarshalAs attribute in front of the byte[]
array.
- I have used the [ClassInterface(ClassInterfaceType.None)] attribute with
an explicit interface to make the tlbexp tool explicitly define the
interface
methods.

Jul 21 '05 #3

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

4 posts views Thread by Roland Moschel | last post: by
5 posts views Thread by Maxim | last post: by
17 posts views Thread by =?Utf-8?B?U2hhcm9u?= | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.