Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which method overload will be accessible from VBScript? [duplicate]

System.Collections.ArrayList is ComVisible(true). It contains three overloads of IndexOf (see here):

public virtual int IndexOf(Object value)
public virtual int IndexOf(Object value, int startIndex)
public virtual int IndexOf(Object value, int startIndex, int count)

From VBScript, only the second overload can be accessed:

Dim oList
Set oList = CreateObject("System.Collections.ArrayList")

'oList.IndexOf "foo"        'Error: Invalid procedure call or argument: 'IndexOf'
 oList.IndexOf "foo", 0
'oList.IndexOf "foo", 0, 1  'Error: Wrong number of arguments or property assignment was not valid: 'IndexOf'

In 'Overloading a method in com visible dll' Hans Passant explains that overload methods exist in the assembly, but from script one cannot get their dispid and therefore call them. This seems to imply that one method might make it through though.

  • Can I determine from the ArrayList source (or elsewhere), which method will be accessible? What are the rules, that govern this selection process?
  • Why are the error messages different for case one and three?
like image 598
Micha Wiedenmann Avatar asked May 03 '16 10:05

Micha Wiedenmann


2 Answers

Short answer: All of them.


Let's analyse what @hans-passant has written;

Answer to Overloading a method in com visible dll
COM does not have support for member overloads, each name must be unique. An inevitable side-effect of IDispatch::GetIDsOfNames(). The function that the script interpreter uses to translate "Write" as used in the scripting code to a dispid. The method still exists, there's just no way to get GetIDsOfNames() to return its dispid. The type library exporter solves this problem by renaming the overloaded method, it will be Write_2().

It's in two parts

  1. Explaining the behaviour of IDispatch::GetIDsOfNames()
  2. How the Type Library Exporter solves uniqueness issue.

It doesn't say they are not available, on the contrary they have been renamed to avoid the uniqueness constraint that IDispatch::GetIDsOfNames() has when assigning DISPID to the method name.

So all three overloads are available just renamed using the following format

oList.IndexOf
oList.IndexOf_2
oList.IndexOf_3

Note: There is no IndexOf_1 because the first overload always takes the original method name and subsequent overloads start from _2 onwards.

Depending on how the Type Library Exporter renames the overloads will depend which one takes which set of arguments, the only way to work this out is trial and error.

Quick attempt at a test

Dim oList
Set oList = CreateObject("System.Collections.ArrayList")

oList.Add "bar"
oList.Add "foo"

WScript.Echo oList.IndexOf("foo", 0)
WScript.Echo oList.IndexOf_2("foo", 0, 1)
WScript.Echo oList.IndexOf_3("foo")

Output:

1
-1
1

Why do the two statements fail with different errors?

If we go back to your original example

Dim oList
Set oList = CreateObject("System.Collections.ArrayList")

'oList.IndexOf "foo"        'Error: Invalid procedure call or argument: 'IndexOf'
 oList.IndexOf "foo", 0
'oList.IndexOf "foo", 0, 1  'Error: Wrong number of arguments or property assignment was not valid: 'IndexOf'

Statement one and three fail with different errors due to how VBScript evaluates the method signatures. The correct signature in the above example accepts two arguments so the first statement;

oList.IndexOf "foo"

will fail because the only matching signature has two arguments not one hence the error;

Invalid procedure call or argument: 'IndexOf'

The third statement

oList.IndexOf "foo", 0, 1

contains one more argument then the expected signature so instead of not finding a match it finds one but reports;

Wrong number of arguments or property assignment was not valid: 'IndexOf'

as the number of arguments exceeds what is expected by the method signature IndexOf(arg, arg).


Useful Links

  • CA1402: Avoid overloads in COM visible interfaces (thanks to @Pikoh for this one)

  • Determining .Net method suffix number in VBScript (COM-interop)

  • Overloads in COM interop (CCW) - IDispatch names include suffix (_2, _3, etc)

  • Is there a tool for exploring/testing COM objects?

like image 151
user692942 Avatar answered Sep 21 '22 04:09

user692942


The overloads have numbered aliases:

>> Set al = CreateObject("System.Collections.ArrayList")
>> al.Add "poo"
>> al.Add "foo"
>> WScript.Echo al.IndexOf("poo", 0)
>>
0
>> WScript.Echo al.IndexOf("poo", 1)
>>
-1
>> WScript.Echo al.IndexOf_1("foo")
>>
Error Number:       438
Error Description:  Object doesn't support this property or method
>> WScript.Echo al.IndexOf_2("foo")
>>
Error Number:       5
Error Description:  Invalid procedure call or argument
>> WScript.Echo al.IndexOf_3("foo")
>>
1
>>

I use trial and error to figure it out; there may be docs or introspection tools for a more scientific approach.

like image 44
Ekkehard.Horner Avatar answered Sep 20 '22 04:09

Ekkehard.Horner