What's the correct way to pass parameters from VBScript to COM interface implemented in C#?


I'm trying to expose a fairly simple C# class to COM which should be usable from VBScript (among others). Some objects need to be created via COM calls and will be used in furter calls later on. The definition of the exposed classes and interfaces looks like this:

namespace Test { [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] public interface IComInterface { IFoo CreateFoo(); void UseFoo(int x, IFoo f); } [ClassInterface(ClassInterfaceType.None)] public sealed class CComInterface : IComInterface { public CComInterface() {} public IFoo CreateFoo() { return new Foo(); } public void UseFoo(int x, IFoo f) { f.Bar(); } } [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] public interface IFoo { void Bar(); } [ClassInterface(ClassInterfaceType.None)] public class Foo : IFoo { internal Foo() {} public void Bar() {} } }

The simplest thinkable COM client in VBScript does this:

Dim ci Set ci = WScript.CreateObject("Test.CComInterface") Dim foo Set foo = ci.CreateFoo foo.Bar ci.UseFoo 0, foo

While the call to Bar succeeds, calling UseFoo fails with "Error 5: invalid procedure call or invalid argument"

The generated IDL seems ok to me:

dispinterface IComInterface { properties: methods: [id(0x60020003)] IFoo* CreateFoo(); [id(0x60020004)] void UseFoo( [in] long x, [in] IFoo* f); };

The vbs call succeeds when I wrap the second parameter in parentheses like this:

ci.UseFoo 0, (foo)

As far as I understand (I'm no VBScript expert however) this forces the reference to foo to be passed by value, i.e. a copy of the reference is being made.

How can I change the interface so that it can be called with the foo reference directly? Since this will be a public interface used by customers I don't like the idea of having to explain why all the objects created need to be passed back in an extra pair of parentheses...


Louis.fr on msdn social helped me out - the trick is to tell the marshaller how to marshal the parameter like this:

public void UseFoo(int x, [MarshalAs(UnmanagedType.IDispatch)] IFoo f) { f.Bar(); }

Try changing the C# interface to take a ref parameter.



  • What's the correct way to pass parameters from VBScript to COM interface implemented in C#?
  • Snowball Stemming: defining Regions
  • Cocoa: Accepting and responding to keystrokes
  • Python multiprocessing using a lock or manager list for Pool workers accessing a global list variabl
  • Cordova build windows on Windows 10 and VisualStudio 2017
  • Normal Query on Cassandra using DataStax Enterprise works, but not solr_query
  • Checking the string for null or empty space
  • Timeout for launching a bash command in perl
  • short and easy question on spring nested transactions
  • Send post-request with string
  • primefaces datatable selectionMode multiple not working with mojarra
  • node.js eventEmitter : Listen for events across files
  • What I can use subquery instead for search MAX()?
  • NHibernate - Paging with ICriteria and optional ICriteria calls
  • Is there a function to calculate the difference between two times and display a relative result?
  • BREAK ON instruction in MySQL queries?
  • Limit number of button clicks
  • Creating and managing two independent random number sequences
  • Bazel failed to include a external static library .a
  • Spongycastle is missing many algorithms when loaded on android
  • Filtering out choiceless polls in the Django tutorial causes polls in the index to duplicate
  • Could not resolve all files for configuration ':react-native-vector-icons:classpath'
  • How to close a WebView with double-click?
  • Implementation of timeout in LDAP
  • Update all WooCommerce product prices to 2 decimals in database
  • VBScript InputBox and Help Files
  • How convert html to BBcode in C#
  • JavaScript RegExp Replace