Discussion:
IDispatch Invoke - propertyget or method. Whats the difference ?
(too old to reply)
R.Wieser
2020-04-30 10:15:13 UTC
Permalink
Hello all,

I'm currently looking at the Invoke method from IDispatch, and specificaly
its flags. I ran a testscript like this:
- - - - - - - - - - - - - - -
MsgBox MyObject.MyData("foo",42)
h = MyObject.MyData("foo",42)
- - - - - - - - - - - - - - -
For the first I got just the DISPATCH_METHOD flag, but for the second I got
both the DISPATCH_METHOD and DISPATCH_PROPERTYGET flags, and I have no idea
why. Does anyone have an idea ?

Also, I have a bit of a problem interpreting the MSDN page regarding to the
wFlags member:
- - - - - - - - - - - - - - -
DISPATCH_METHOD - The member is invoked as a method. If a property has the
same name, both this and the DISPATCH_PROPERTYGET flag can be set.
- - - - - - - - - - - - - - -
First: "invoked as a method" ? How is that relevant ? But in that case,
whats the difference between the two lines of my example code ?
Second: "has the same name" ? The same as which other name where ?

- - - - - - - - - - - - - - -
DISPATCH_PROPERTYGET - The member is retrieved as a property or data member.
- - - - - - - - - - - - - - -
What is (if at all) the difference between a "property" and a "data member"
(preferrably explained codewise) ?

- - - - - - - - - - - - - - -
DISPATCH_PROPERTYPUTREF - The member is changed by a reference assignment,
rather than a value assignment. This flag is valid only when the property
accepts a reference to an object.
- - - - - - - - - - - - - - -
"This flag is valid only when" ? I don't get that distinction. To me it
looks like it indicates that the provided argument is a(n object only ?)
reference, leaving it up to the code handling the assignment to do something
with it or not. Not doing something with that flag certainly doesn't
magically invalidate the flag itself. So, what than are they trying to tell
me/us there ?

Reference:
The above object was added to a scriptengine using
IActiveScript::AddNamedItem. It also doesn't have a typelib (no peeking
into the ammount and types of arguments that a method accepts).

Regards,
Rudy Wieser
JJ
2020-04-30 20:53:31 UTC
Permalink
Post by R.Wieser
Hello all,
I'm currently looking at the Invoke method from IDispatch, and specificaly
- - - - - - - - - - - - - - -
MsgBox MyObject.MyData("foo",42)
h = MyObject.MyData("foo",42)
- - - - - - - - - - - - - - -
For the first I got just the DISPATCH_METHOD flag, but for the second I got
both the DISPATCH_METHOD and DISPATCH_PROPERTYGET flags, and I have no idea
why. Does anyone have an idea ?
Also, I have a bit of a problem interpreting the MSDN page regarding to the
- - - - - - - - - - - - - - -
DISPATCH_METHOD - The member is invoked as a method. If a property has the
same name, both this and the DISPATCH_PROPERTYGET flag can be set.
- - - - - - - - - - - - - - -
First: "invoked as a method" ? How is that relevant ? But in that case,
whats the difference between the two lines of my example code ?
Second: "has the same name" ? The same as which other name where ?
I also got confused by that when I was writing a COM library. I see no
difference between DISPATCH_METHOD and DISPATCH_PROPERTYGET when the method
is being called when reading a property, or when it's just a function
method.

I've read somewhere that the VBScript engine doesn't distinguish between a
property, or a function method.

Ah, found it! It's stated in the "Getting and Setting Properties (Component
Automation)" MSDN sub article of "IDispatch::Invoke".

[quote]
Properties are accessed in the same way as methods, except you specify
DISPATCH_PROPERTYGET or DISPATCH_PROPERTYPUT instead of DISPATCH_METHOD.
Some languages cannot distinguish between retrieving a property and calling
a method. In this case, you should set the flags DISPATCH_PROPERTYGET and
DISPATCH_METHOD.
[/quote]

And IIRC, with VBScript as a client, assigning a value to a read+write
property, may end up calling the method for reading the property first,
before the method for writing the property is called.
Post by R.Wieser
DISPATCH_PROPERTYGET - The member is retrieved as a property or data member.
- - - - - - - - - - - - - - -
What is (if at all) the difference between a "property" and a "data member"
(preferrably explained codewise) ?
"property" refers to a value. "data member" refers to a member of an object
- which is a reference. In this context, DISPATCH_PROPERTYGET is for methods
which returns either a value or a reference.
Post by R.Wieser
DISPATCH_PROPERTYPUTREF - The member is changed by a reference assignment,
rather than a value assignment. This flag is valid only when the property
accepts a reference to an object.
- - - - - - - - - - - - - - -
"This flag is valid only when" ? I don't get that distinction. To me it
looks like it indicates that the provided argument is a(n object only ?)
reference, leaving it up to the code handling the assignment to do something
with it or not. Not doing something with that flag certainly doesn't
magically invalidate the flag itself. So, what than are they trying to tell
me/us there ?
Yes, it's when a property is being assigned with a reference.
DISPATCH_PROPERTYPUTREF simply tells IDispatch that the given method
argument is a reference. If the COM library doesn't have a type library, COM
clients can't know whether a method accepts a reference or not. If it
doesn't, it's IDispatch's job to convert the reference to a value so that
the method can process it, or reject the invocation.
R.Wieser
2020-05-01 09:44:43 UTC
Permalink
JJ,
Post by JJ
I've read somewhere that the VBScript engine doesn't distinguish
between a property, or a function method.
Thanks for that, rather important tidbit of info.
Post by JJ
Ah, found it! It's stated in the "Getting and Setting Properties
(Component Automation)" MSDN sub article of "IDispatch::Invoke".
Jumping up-and-down in his chair, thinking "Want! Want!". Speaking aloud:
"Do you maybe have a link to that webpage ? Its contents could be
clarifying some other stuff too ?" :-)

To be honest, I have no idea how a "property" and a "method" are, or even
could be different in terms of code. I guess it has something to do with
how they are defined (their intended area of operation).
Post by JJ
And IIRC, with VBScript as a client, assigning a value to a
read+write property, may end up calling the method for reading
the property first, before the method for writing the property is called.
Oh joy, that might cause al kinds of problems when the function has got
"side-effects", like opening data connections (files, pipes, you name it).
Post by JJ
"property" refers to a value. "data member" refers to a member of an
object - which is a reference. In this context, DISPATCH_PROPERTYGET
is for methods which returns either a value or a reference.
Nope, still not geting it. A "member of an object" ? Like a method ?
And are properties not also members of (belong to) an object ?

As for "a value or a reference" ? What does "a reference" mean to you ?
To me /anything/ that isn't a value is a reference. Including those that
refer to arrays, objects and even strings.

Also, you are mentioning "a reference" here, but also while trying to
explain DISPATCH_PROPERTYPUTREF, which muddies the borders between the two.
:-|

As for that,
Post by JJ
DISPATCH_PROPERTYPUTREF simply tells IDispatch that the given
method argument is a reference.
why is that important (why should I care) ? I mean, I can simple store
variants in its whole, without any consideration to whats in it (I can,
can't I ?).
Post by JJ
If the COM library doesn't have a type library, COM clients
can't know whether a method accepts a reference or not.
Thats what I'm currently working with by the way. The called method gets
the flags, an array of variant arguments, a count thereof and a pointer to a
variant to dump its result into. Its upto the method to do "stuff" with
it - or not.
Post by JJ
If it doesn't, it's IDispatch's job to convert the reference to a value
That does not compute to me. If it doesn't know if the targetted method can
(or want to) handle references (whatever they may be), than why should it
presume it should convert those to something else ? It might even be
counter-productive ...
Post by JJ
or reject the invocation
About that:

Do you have any idea why theOnScriptError's error object allows me to
retrieve the correct string of the, by me, returned status (0x80020007 -
"Object doesn't support named arguments"), but when I look at the error code
in the "scode" field of the retrieved ExcepInfo record it shows a fully
different one (0x800A01BE). Its confusing to say the least ...

Regards,
Rudy Wieser
JJ
2020-05-01 11:45:52 UTC
Permalink
Post by R.Wieser
JJ,
Post by JJ
I've read somewhere that the VBScript engine doesn't distinguish
between a property, or a function method.
Thanks for that, rather important tidbit of info.
Post by JJ
Ah, found it! It's stated in the "Getting and Setting Properties
(Component Automation)" MSDN sub article of "IDispatch::Invoke".
"Do you maybe have a link to that webpage ? Its contents could be
clarifying some other stuff too ?" :-)
Oh, sorry. I found that in my MSDN Library 2008 (from DVD). The online
version is this: (long URL warning)

https://docs.microsoft.com/en-us/previous-versions/windows/desktop/automat/getting-and-setting-properties
Post by R.Wieser
To be honest, I have no idea how a "property" and a "method" are, or even
could be different in terms of code. I guess it has something to do with
how they are defined (their intended area of operation).
In COM, a property is much like C object property. The only difference is, a
COM property is just in definition - where the object doesn't actually have
a static storage for the property. Instead, a property has a "getter" and
"setter" very similar to JavaScript's property getter & setter. Those getter
and setter are methods of an object. So, a property read operation will call
the getter method of that property, and a property write operation will call
the setter method of that property.

A good example is the type library for WScript.Shell object's
CurrentDirectory property:

interface IWshShell3 : IWshShell2 {
[id(0x00000bc4)]
HRESULT Exec([in] BSTR Command,
[out, retval] IWshExec** ppExec);
[id(0x00000bc5), propget]
HRESULT CurrentDirectory([out, retval] BSTR* out_Directory);
[id(0x00000bc5), propput]
HRESULT CurrentDirectory([in] BSTR out_Directory);
};

As you can see, there are two CurrentDirectory methods. One for getter
(propget), and one for setter (propput). Those two make up the
CurrentDirectory property. If there's no setter method, then a property is a
read-only one. If there's only a setter method, then a property is a
write-only and can't be read. Methods without any property flag, are just
plain methods.
Post by R.Wieser
As for "a value or a reference" ? What does "a reference" mean to you ?
To me /anything/ that isn't a value is a reference. Including those that
refer to arrays, objects and even strings.
In that context, a value is literal value in a variant type. A reference is
a pointer of a value stored in a variant type.
Post by R.Wieser
why is that important (why should I care) ? I mean, I can simple store
variants in its whole, without any consideration to whats in it (I can,
can't I ?).
That flag just for formality. If the COM object doesn't have a type library,
you can do whatever you want.
Post by R.Wieser
Post by JJ
If it doesn't, it's IDispatch's job to convert the reference to a value
That does not compute to me. If it doesn't know if the targetted method can
(or want to) handle references (whatever they may be), than why should it
presume it should convert those to something else ? It might even be
counter-productive ...
That's assuming that the given and the accepted argument type is different.
For example, if the method calculates two numbers from the arguments, it'd
means that the method can only handle numbers. If the given arguments are
strings, type conversion is required. It can be done either by IDispatch, or
by the method itself. If the programming language handles variant types
natively, then there would be no need to manually call type conversion
function.
Post by R.Wieser
Do you have any idea why theOnScriptError's error object allows me to
retrieve the correct string of the, by me, returned status (0x80020007 -
"Object doesn't support named arguments"), but when I look at the error code
in the "scode" field of the retrieved ExcepInfo record it shows a fully
different one (0x800A01BE). Its confusing to say the least ...
Both report the same error, just different source. 0x80020007 is Win32
API's. 0x800A01BE is VBScript's.
R.Wieser
2020-05-01 14:49:46 UTC
Permalink
JJ,
Post by JJ
Oh, sorry. I found that in my MSDN Library 2008 (from DVD).
The online version is this: (long URL warning)
Thanks. From it I found that going one directory up resulted in a
"automation-programming-reference" page, which references even more stuff
that looks to be worthwile to take a peek at.
Post by JJ
The only difference is, a COM property is just in definition
Yeah, I already got that feeling.
Post by JJ
- where the object doesn't actually have a static storage for the
property.
Well, which object does ? Throw the object away and the storage is gone.
:-)
But if you mean that COM doesn't seem to offer direct access to values
stored inside the object that I agree with you.

Shucks. I just thought of a possibility to handle properties in the
"Invoke" method itself (no name-bound getter or setter methods needed, just
use the ID as the offset in the property-storage). But when I checked even
a true property as in "MsgBox SubObj.Property1" got tagged as a method. It
also doesn't help that in "MsgBox SubObj.Property1(42)" it still got tagged
as a property. :-(
Post by JJ
A good example is the type library for WScript.Shell object's
...
Post by JJ
As you can see, there are two CurrentDirectory methods.
I'm sorry, but I disagree. All I see is two /descriptions/, both, by way of
having the same ID, leading to the same method. Its their main purpose is
so that caller can pre-check the syntax, but means little to the callee
(don't worry, for the sake of briefness I'm ignoring that, when using an IDL
file, the way the arguments are provided to the method also changes :-) ).
Post by JJ
Post by R.Wieser
As for "a value or a reference" ? What does "a reference" mean to you ?
..
Post by JJ
In that context, a value is literal value in a variant type. A reference is
a pointer of a value stored in a variant type.
I know what the regular meaning of "value" is, but I've also seen strings,
dates and other stuff being stored as properties - heck, even your own above
"CurrentDirectory" IDL example does it. Which (still) causes the problem
that I have no idea what "a reference" in that context means.
Post by JJ
Both report the same error, just different source. 0x80020007
is Win32 API's. 0x800A01BE is VBScript's.
Duplicate definitions. Great. And no MS link when I google either. Even
better. :-(

And also, the 0x80020007 status is generated by /my/ object - cause I told
it to do so. Seeing that error back would be a nice indication of
where/what the source actually is. Now seeing a fully different value
makes it appear as if the error source is actually somewhere else ... :-(

Thanks for the explanation and help.

Regards,
Rudy Wieser
JJ
2020-05-02 14:19:49 UTC
Permalink
Post by R.Wieser
I know what the regular meaning of "value" is, but I've also seen strings,
dates and other stuff being stored as properties - heck, even your own above
"CurrentDirectory" IDL example does it. Which (still) causes the problem
that I have no idea what "a reference" in that context means.
If you have a method whose argument is a callback (i.e. a function), the
argument type must be a reference. It can not be a value. e.g.

obj.setcallback getref("myfunc")
Post by R.Wieser
Post by JJ
Both report the same error, just different source. 0x80020007
is Win32 API's. 0x800A01BE is VBScript's.
Duplicate definitions. Great. And no MS link when I google either. Even
better. :-(
VBScript error codes are available in MSDN, but they list only the value for
the Code field of HRESULT. The page doesn't seem to be searchable by Google
either. But it's there.

https://docs.microsoft.com/en-us/previous-versions/5ta518cw%28v%3dvs.85%29

Also, the page doesn't list all of the error codes. The complete codes can
be retrieved from the string resources of the VBSCRIPT.DLL. Or the
VBSCRIPT.DLL.MUI if Vista+.
Post by R.Wieser
And also, the 0x80020007 status is generated by /my/ object - cause I told
it to do so. Seeing that error back would be a nice indication of
where/what the source actually is. Now seeing a fully different value
makes it appear as if the error source is actually somewhere else ... :-(
VBScript uses 0x0A for HRESULT's Facility field - an unlisted facility code.
Instead of 0x02 (FACILITY_DISPATCH).
R.Wieser
2020-05-02 15:19:24 UTC
Permalink
JJ,
Which (still) causes the problem that I have no idea what
"a reference" in that context means.
If you have a method whose argument is a callback (i.e. a
function), the argument type must be a reference. It can not
be a value. e.g.
obj.setcallback getref("myfunc")
That certainly clarifies it. I must say that I've /never/ seen VBS using
something like that (and I've been surfing/cruising the web for a while
now).
VBScript error codes are available in MSDN, but they list only the value for
the Code field of HRESULT. The page doesn't seem to be searchable by Google
either. But it's there.
https://docs.microsoft.com/en-us/previous-versions/5ta518cw%28v%3dvs.85%29
Thanks. That will certainly make it easier.
Also, the page doesn't list all of the error codes. The complete codes
can be retrieved from the string resources of the VBSCRIPT.DLL.
Or the VBSCRIPT.DLL.MUI if Vista+.
Possibly even better. :-)

You know, its odd. Although "FormatMessage" does return an (a bit
shorthand) error mesage for 0x80020007, it has no clue about 0x800A01BE.
VBScript uses 0x0A for HRESULT's Facility field - an unlisted facility code.
:-|

Thanks for the info. But goddamnit, its tiresome to have to work with
partial, and even worse, confusing documentation :-(

Just a few days ago I discovered , by chance, the answer to a problem of a
number of years ago: When I provided a script to
IActiveScriptParse::ParseScriptText it alway ran instantly, even though I
didn't supply the SCRIPTTEXT_ISEXPRESSION flag. As it turns out it was
caused by supplying a non-null "pvarResult" argument - even though *no
result was-or-could-be returned*. Sigh.

It also explained why in many examples the parsing was directly followed
with code switching the engine to the "connected" state (which did nothing
for me).

Regards,
Rudy Wieser
JJ
2020-05-03 04:16:14 UTC
Permalink
Post by R.Wieser
That certainly clarifies it. I must say that I've /never/ seen VBS using
something like that (and I've been surfing/cruising the web for a while
now).
One of the reasons is probably because among WSH, WSH related, and VBScript
objects, none of them use references. That kind of code is usually found
only in MSIE web pages or HTML Applications (*.hta) for setting up an event
handler of an HTML element at runtime. e.g.:

set btn = document.getelementbyid("thebutton")
set btn.onclick = getref("btnclicked")

That last line won't work without the SET statement, BTW. i.e. The SET
statement is required and strictly for assigning a reference to a
variable/property. Because, objects and functions can only be stored as
references.
Post by R.Wieser
But goddamnit, its tiresome to have to work with
partial, and even worse, confusing documentation :-(
Exactly. Many small parts of the supposedly be documented are either
missing, or incorrect, or just stated as "reserved" or "not used". Rogue
researches mostly provide more detailed information in this case.
R.Wieser
2020-05-03 07:31:14 UTC
Permalink
JJ,
Post by JJ
set btn = document.getelementbyid("thebutton")
set btn.onclick = getref("btnclicked")
Good example.
Post by JJ
That last line won't work without the SET statement, BTW. i.e.
The SET statement is required and strictly for assigning a reference
to a variable/property.
:-) I already got a feeling that the "Set" statement might be involved (its
the obvious trigger for the DISPATCH_PROPERTYPUTREF flag), but at that time
without any kind of pertinent information ...

Than again, when the source is a variant the type of contained data is
described as part of it, so it (being a reference) could have been be
discovered that way.
Post by JJ
Exactly. Many small parts ... are ... just stated as "reserved" or "not
used".
I always auto-translate "reserved" as being short for "reserved for future
use" - in the pen, but not (yet) implemented. Might be wishfull thinking
though.

As for missing ? Just recently I did some batteling with the
GetNumberFormat function, trying to make it stop adding a fractional part
where none was provided (I posted about it here). As such I did an quick
scan of all possible flags. Most caused an error, but having the highest
bit set did again return a result. I didn't see that described anywhere.
And no idea what it does (didn't see an change). Oh well ...

Regards,
Rudy Wieser

Loading...