
Signature
Phil Wilson [MVP Windows Installer]
----
Hi Phil,
> There doesn't seem to be an obvious (to me anyway!) way to have an interface
> in .NET that passes an object [] such that it can be used by (say) VBScript.
[quoted text clipped - 11 lines]
>
> What is required (MarshalAs or whatever) is that this kind of script works:
You don't need any special marschal instructions, because
the runtime already has a default marschaler for "object[]".
However, VBScript is not able to pass the expected SAFEARRAY
by value. It simply doesn't support that. You have to change
the managed signature from
public void Connect(object [] initializeData )
to
public void Connect(ref object [] initializeData )
> set obj = createobject("blah.blah")
> dim parm(2)
[quoted text clipped - 5 lines]
> The error is pretty consistent at 0x800A0005 Invalid procedure call or
> argument: 'obj.Connect'
Rob
Willy Denoyette [MVP] - 27 Aug 2004 09:59 GMT
> Hi Phil,
> However, VBScript is not able to pass the expected SAFEARRAY
> by value.
Sure it has just put the arg between parens like this:
obj.Connect (parm)
when calling a function use double parens:
r = obj.Connect((param))
Following calls a method with two params one byval another byref.
r = obj.Method((p1), p2)
Willy.
Robert Jordan - 27 Aug 2004 10:43 GMT
>>However, VBScript is not able to pass the expected SAFEARRAY
>>by value.
[quoted text clipped - 9 lines]
>
> r = obj.Method((p1), p2)
Thanks for the syntax. Does the interop now work?
Rob
Phil Wilson - 27 Aug 2004 19:21 GMT
It's not a syntax issue - that's just me doing sloppy cut&paste - the issue
is the 0x800A0005 Invalid procedure call or
argument: 'obj.Connect'. I tried a ref on the object [], still doesn't work.
This is the entire class library and VBScript. I just have a nagging feeling
it should work with the right incantation somewhere.
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace TestCL
{
[ComVisible(true), GuidAttribute("EBFCDECB-CF01-467c-A15E-D57ABE4E3C6F")]
[ClassInterface(ClassInterfaceType.AutoDispatch)]
[ProgId("blah.blah")]
public class Class1
{
public void Connect(ref object [] initializeData )
{
MessageBox.Show (initializeData[0].ToString());
}
}
}
' VBScript source code
set obj = createobject("blah.blah")
dim parm(2)
parm (1) = "this"
parm(2)="that"
obj.Connect parm

Signature
Phil Wilson
[MVP Windows Installer]
> >>However, VBScript is not able to pass the expected SAFEARRAY
> >>by value.
[quoted text clipped - 13 lines]
>
> Rob
Willy Denoyette [MVP] - 27 Aug 2004 22:13 GMT
Yes it is a syntax issue, try and take a look at following small sample:
1. CS file inprocserver.cs
// Compile with csc /t:library inprocserver.cs
// and use Regasm /codebase inprocserver.dll to register
using System.Runtime.InteropServices;
using System;
// interface
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
[Guid("1ab6f6ea-83b5-4b16-934b-fb98d9af8e0a")]
public interface IDotNetInterface
{
int WriteEx(ref object[] aParam1, string s); }
// class
[ClassInterface(ClassInterfaceType.None)]
[ProgId("Test.DotNetIf")]
public class DotNetInterface : IDotNetInterface
{
public DotNetInterface() {}
public int WriteEx(ref object[] aParam1, string s)
{
Console.WriteLine("Length: {0}", aParam1.Length);
int i = 0;
foreach(byte b in aParam1)
{
Console.WriteLine(b);
aParam1[i] = (byte)aParam1[i] + 1; // change each element in the array
i++;
}
return aParam1.Length
}
}
And the VBScript file:
Dim arr(2)
' pass byte array just for the fun
arr(0) = CByte(10)
arr(1) = CByte(20)
arr(2) = CByte(30)
set o = CreateObject("Test.DotNetIf")
r = o.WriteEx ((arr), "test")
' uncomment next to see how it fails
' r = o.WriteEx (arr, "test")
for each b in arr
WScript.Echo "Array elem = " & b
next
Feel free to ask more questions.
Willy.
> It's not a syntax issue - that's just me doing sloppy cut&paste - the
> issue
[quoted text clipped - 45 lines]
>>
>> Rob
Phil Wilson - 28 Aug 2004 00:29 GMT
Ok, got it, many thanks. Those double parentheses are what I hadn't noticed.

Signature
Phil Wilson
[MVP Windows Installer]
> Yes it is a syntax issue, try and take a look at following small sample:
>
[quoted text clipped - 99 lines]
> >>
> >> Rob
Willy Denoyette [MVP] - 28 Aug 2004 21:54 GMT
Phil,
When using VBScript as client it's better to consider all arguments passes
as VARIANT's in C#. Note that VBScript considers all variables as variants,
but internaly the scripting engine uses the real variant types, so you need
to declare a variant to be passed as arg. Here's a sample.
public int ModArray(ref object aParam1)
{
object[] arr = aParam1 as object[]; // aParam1 is a now a VARIANT wrapping
a SAFEARRAY of VARIANT's
int i = 0;
foreach(object b in arr){ // for each object (VARIANT) in arr
Console.WriteLine(b);
arr[i] =(byte)( (int)arr[i] - 1); // change the values
i++;
}
return (aParam1 as Array).Length;
}
Dim arr(2)
' pass byte array just for the fun
arr(0) = CByte(10)
arr(1) = CByte(20)
arr(2) = CByte(30)
set o = CreateObject("Test.DotNetIf")
dim var 'declare variant variable
var = arr 'set variant variable to array
r = o.ModArray(var) 'pass variant not the array
for each b in var
WScript.Echo "Array elem = " & b
next
Willy.
> Ok, got it, many thanks. Those double parentheses are what I hadn't
> noticed.
[quoted text clipped - 103 lines]
>> >>
>> >> Rob