Win32::OLE - "Member not found" in PROPERTYPUTREF

Win32::OLE - "Member not found" in PROPERTYPUTREF

am 19.08.2010 18:07:05 von Michael.Ludwig

I encountered an issue using MSXML from Win32::OLE.

MSDN - MSXML - createProcessor Method
http://msdn.microsoft.com/en-us/library/ms753809%28VS.85%29. aspx

There's a JScript example on that page, which works.

I translated it to Perl (see script below), and I'm getting the
following error message:

perl createProcessor.pl
Win32::OLE(0.1709) error 0x80020003: "Mitglied nicht gefunden"
in PROPERTYPUTREF "input" at createProcessor.pl line 26

"Mitglied nicht gefunden" translates to "Member not found".

Seen with ActivePerl 5.12.1:

Binary build 1201 [292674] provided by ActiveState
Built May 14 2010 00:34:27

\,,,/
(o o)
------oOOo-(_)-oOOo------ createProcessor.pl
use strict;
use warnings;
use Win32::OLE;
Win32::OLE->Option(Warn => 3);
my $xslt = Win32::OLE->new("Msxml2.XSLTemplate.3.0");
my $xslDoc = Win32::OLE->new("Msxml2.FreeThreadedDOMDocument.3.0");
my $xslProc;
my $myErr;
$xslDoc->{async} = 0;
$xslDoc->load("createProcessor.xsl");
if ($xslDoc->parseError->errorCode != 0) {
$myErr = $xslDoc->parseError;
printf("You have error %s\n" + $myErr->reason);
}
else {
$xslt->{stylesheet} = $xslDoc;
my $xmlDoc = Win32::OLE->new("Msxml2.DOMDocument.3.0");
$xmlDoc->{async} = 0;
$xmlDoc->load("books.xml");
if ($xmlDoc->parseError->errorCode != 0) {
$myErr = $xmlDoc->parseError;
printf("You have error %s\n" + $myErr->reason);
}
else {
$xslProc = $xslt->createProcessor();
$xslProc->{input} = $xmlDoc;
$xslProc->addParameter("param1", "Hello");
$xslProc->transform();
print( $xslProc->output );
}
}
__END__

The stylesheet createProcessor.xsl is the one given on the MSDN page.
The input document books.xml is just .

What am I doing wrong?

If it works in JScript, why does it not work in Perl? Do individual
methods and properties have to be registered somewhere in the Perl COM
bindings, or are they simply passed on as is?

What could I do to track down the cause of the error?

Thanks!
--
Michael Ludwig
_______________________________________________
ActivePerl mailing list
ActivePerl@listserv.ActiveState.com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs

RE: Win32::OLE - "Member not found" in PROPERTYPUTREF

am 19.08.2010 18:47:27 von Michael.Ludwig

> -----Original Message-----
> From: Ludwig, Michael
> Subject: Win32::OLE - "Member not found" in PROPERTYPUTREF
>
> I encountered an issue using MSXML from Win32::OLE.

> perl createProcessor.pl
> Win32::OLE(0.1709) error 0x80020003: "Mitglied nicht gefunden"
> in PROPERTYPUTREF "input" at createProcessor.pl line 26
>
> "Mitglied nicht gefunden" translates to "Member not found".

Hehe, I found the reason for this error.

> $xslProc = $xslt->createProcessor();
> $xslProc->{input} = $xmlDoc;

Quoted from the web:

this looks like an indexed property. The correct syntax
to assign to them would be

$COMComponent->LetProperty("Value", "Identity", $varUserStr);

"Value" is the property name, "Identity" is the first (and only)
argument to the property, and $varUserStr is the new value.

http://www.mail-archive.com/perl-win32-users@listserv.active state.com/msg27982.html

So I tried the following and it worked:

$xslProc->LetProperty( input => $xmlDoc );

Thanks, Jan!

> What could I do to track down the cause of the error?

Well, I could have re-read the fine Win32::OLE manual first! :-)

I haven't understood the underlying issue, though. Is it that JScript
handles different cases transparently that require different syntaxes
in Perl and Visual Basic? Pointers welcome.

--
Michael Ludwig
_______________________________________________
ActivePerl mailing list
ActivePerl@listserv.ActiveState.com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs

RE: Win32::OLE - "Member not found" in PROPERTYPUTREF

am 19.08.2010 19:31:04 von Michael.Ludwig

> -----Original Message-----
> From: Ludwig, Michael

> Quoted from the web:
>
> this looks like an indexed property. The correct syntax
> to assign to them would be
>
> $COMComponent->LetProperty("Value", "Identity", $varUserStr);

> So I tried the following and it worked:
>
> $xslProc->LetProperty( input => $xmlDoc );

> I haven't understood the underlying issue, though. Is it that JScript
> handles different cases transparently that require different syntaxes
> in Perl and Visual Basic? Pointers welcome.

Using oleview.exe (from the ResKit) and the ITypeLib Viewer, I've
extracted the following info:

\,,,/
(o o)
------oOOo-(_)-oOOo------
(1) interface IXMLDOMDocument, async property:
[id(0x0000003d), propput, helpstring("flag for asynchronous download")]
HRESULT async([in] VARIANT_BOOL isAsync);

(2) interface IXSLProcessor, input property:
[id(0x00000002), propput, helpstring("XML input tree to transform")]
HRESULT input([in] VARIANT pVar);
-------------------------

Consider the following in Perl:

$dom->{async} = 1; # correct
$xslProc->{input} = $xmlDoc; # error
$xslProc->LetProperty(input => $xmlDoc); # correct

Is there anything in the type viewer information telling me which syntax
to use in each instance?

--
Michael Ludwig
_______________________________________________
ActivePerl mailing list
ActivePerl@listserv.ActiveState.com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs

RE: Win32::OLE - "Member not found" in PROPERTYPUTREF

am 19.08.2010 20:11:17 von Jan Dubois

On Thu, 19 Aug 2010, Ludwig, Michael wrote:
> > Quoted from the web:
> >
> > this looks like an indexed property. The correct syntax
> > to assign to them would be
> >
> > $COMComponent->LetProperty("Value", "Identity", $varUserStr);
>
> > So I tried the following and it worked:
> >
> > $xslProc->LetProperty( input => $xmlDoc );
>
> > I haven't understood the underlying issue, though. Is it that JScript
> > handles different cases transparently that require different syntaxes
> > in Perl and Visual Basic? Pointers welcome.

You are actually *not* dealing with an indexed property here, which
would take an additional index value in addition to the property name.

The issue you are running into is that there are two different mechanisms
to assign to a property, by value, or by reference. In VB there is different
syntax for both cases:

by value: Let newVar = oldVar
by ref: Set newVar = oldVar

The "Let" keyword is optional, so it could also be written as a simple assignment:

newVar = oldVar

Both methods produce the same result when oldVar already is a value: they assign
the value to newVar. If oldVar is an object, then the "by value" assignment will
call the default method on this object (typically, but not always called "Value")
and assign that to newVar. So the "by value" assignment will be

newVar = oldVar.Value

The "by reference" assignment will just assign a second reference to newVar,
so oldVar and newVar will reference the same object.

Perl does not have a "Set" keyword for "by reference" assignment, and normal
assignments in Perl are also always "by reference" as the concept of calling
a "default" method or property doesn't even exist. So

$newVar = $oldVar;

will always assign by reference when $oldVar is an object. Consequently it
felt most natural/perlish to use the same semantics for OLE property assignment

$obj->{property} = $other_obj;

You can always turn this into a "by value" assignment by either calling the
default method explicitly (but you have to know its name):

$obj->{property} = $other_obj->Value;

or use the Win32::OLE::LetProperty() function:

$obj->LetProperty("property", $other_value);

You rarely need to do this, so the choice of "by reference" assignment for
the default syntax seems to be sensible in retrospect.

The "by value" and "by reference" assignments are implemented by 2 different
COM operation internally: propertyput and propertyputref. Normally all
OLE properties will implement both, especially if they rely on some automated
framework to implement their IDispatch interface.

You seem to be running into a property that has only implemented propertyput
but not propertyputref, so the default syntax fails for you. It means
the corresponding code in VBscript would fail too:

Set xslProc.input = xmlDoc

and only this one would work:

xslProc.input = xmlDoc

It makes a certain amount of sense to force the user to assign a value and
not an object, but most other OLE objects seem to allow either and simply
call the default method themselves if they can't deal with an object.

I don't want to dive into indexed properties here, as it does not apply to
your situation. The only thing you need to understand about them though is
that there is no default syntax mapped that would accept an index:

$obj->IndexedProperty($index) = $value;

because at the time indexed properties were implemented in Win32::OLE there
was no support for lvalue funtions in Perl. And I'm not sure if this could
be implemented even today, as the whole lvalue attribute stuff needs to be
known at compile time.

Anyways, so you always have to use either SetProperty() or LetProperty()
to assign to indexed properties. The discussion above should already
have explained why there are two different functions for indexed
property assignment.

> Using oleview.exe (from the ResKit) and the ITypeLib Viewer, I've
> extracted the following info:
>
> \,,,/
> (o o)
> ------oOOo-(_)-oOOo------
> (1) interface IXMLDOMDocument, async property:
> [id(0x0000003d), propput, helpstring("flag for asynchronous download")]
> HRESULT async([in] VARIANT_BOOL isAsync);
>
> (2) interface IXSLProcessor, input property:
> [id(0x00000002), propput, helpstring("XML input tree to transform")]
> HRESULT input([in] VARIANT pVar);
> -------------------------
>
> Consider the following in Perl:
>
> $dom->{async} = 1; # correct
> $xslProc->{input} = $xmlDoc; # error
> $xslProc->LetProperty(input => $xmlDoc); # correct
>
> Is there anything in the type viewer information telling me which syntax
> to use in each instance?

The "propput" keyword tells you that you should use LetProperty() in both
instances. It just looks like "async" implements "propputref" as well
and does the right thing for you anyways.

I would not bother with this typelib stuff, just always use "by reference"
assignments everywhere, and only when it fails investigate if you are
running into a limitation of that objects implementation and have to use
"by value" assignment explicitly.

Cheers,
-Jan

_______________________________________________
ActivePerl mailing list
ActivePerl@listserv.ActiveState.com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs

Re: Win32::OLE - "Member not found" in PROPERTYPUTREF

am 19.08.2010 23:43:44 von Michael Ludwig

SGkgSmFuLAoKSmFuIER1Ym9pcyBzY2hyaWViIGFtIDE5LjA4LjIwMTAgdW0g MTE6MTEgKC0wNzAw
KToKPiBb4oCmXSBUaGUgImJ5IHZhbHVlIiBhbmQgImJ5IHJlZmVyZW5jZSIg YXNzaWdubWVudHMg
YXJlIGltcGxlbWVudGVkIGJ5IDIKPiBkaWZmZXJlbnQgQ09NIG9wZXJhdGlv biBpbnRlcm5hbGx5
OiBwcm9wZXJ0eXB1dCBhbmQgcHJvcGVydHlwdXRyZWYuCj4gTm9ybWFsbHkg YWxsIE9MRSBwcm9w
ZXJ0aWVzIHdpbGwgaW1wbGVtZW50IGJvdGgsIGVzcGVjaWFsbHkgaWYgdGhl eQo+IHJlbHkgb24g
c29tZSBhdXRvbWF0ZWQgZnJhbWV3b3JrIHRvIGltcGxlbWVudCB0aGVpciBJ RGlzcGF0Y2gKPiBp
bnRlcmZhY2UuCgpUaGFua3MgZm9yIHlvdXIgZ3JlYXQsIGZhYnVsb3VzIGV4 cGxhbmF0aW9uIQoK
PiBZb3Ugc2VlbSB0byBiZSBydW5uaW5nIGludG8gYSBwcm9wZXJ0eSB0aGF0 IGhhcyBvbmx5IGlt
cGxlbWVudGVkCj4gcHJvcGVydHlwdXQgYnV0IG5vdCBwcm9wZXJ0eXB1dHJl Ziwgc28gdGhlIGRl
ZmF1bHQgc3ludGF4IGZhaWxzIGZvcgo+IHlvdS4gIEl0IG1lYW5zIHRoZSBj b3JyZXNwb25kaW5n
IGNvZGUgaW4gVkJzY3JpcHQgd291bGQgZmFpbCB0b286Cj4gCj4gICAgIFNl dCB4c2xQcm9jLmlu
cHV0ID0geG1sRG9jCj4gCj4gYW5kIG9ubHkgdGhpcyBvbmUgd291bGQgd29y azoKPiAKPiAgICAg
eHNsUHJvYy5pbnB1dCA9IHhtbERvYwoKSXQgZG9lcyBmYWlsIGluIFZCU2Ny aXB0IGluZGVlZDoK
CiAgICAgICAgICBcLCwsLwogICAgICAgICAgKG8gbykKLS0tLS0tb09Pby0o Xyktb09Pby0tLS0t
LQpPcHRpb24gRXhwbGljaXQKJyBTZWU6IGh0dHA6Ly9tc2RuLm1pY3Jvc29m dC5jb20vZW4tdXMv
bGlicmFyeS9tczc1MzgwOSUyOFZTLjg1JTI5LmFzcHgKRGltIHhzbHQsIHhz bERvYywgeHNsUHJv
YywgeG1sRG9jClNldCB4c2x0ICAgPSBXU2NyaXB0LkNyZWF0ZU9iamVjdCgi TXN4bWwyLlhTTFRl
bXBsYXRlLjMuMCIpClNldCB4c2xEb2MgPSBXU2NyaXB0LkNyZWF0ZU9iamVj dCgiTXN4bWwyLkZy
ZWVUaHJlYWRlZERPTURvY3VtZW50LjMuMCIpCnhzbERvYy5hc3luYyA9IGZh bHNlCnhzbERvYy5s
b2FkICJjcmVhdGVQcm9jZXNzb3IueHNsIgpJZiAoeHNsRG9jLnBhcnNlRXJy b3IuZXJyb3JDb2Rl
IDw+IDApIFRoZW4KICBteUVyciA9IHhzbERvYy5wYXJzZUVycm9yCiAgV1Nj cmlwdC5FY2hvICJZ
b3UgaGF2ZSBlcnJvciAiICsgbXlFcnIucmVhc29uCkVsc2UKICB4c2x0LnN0 eWxlc2hlZXQgPSB4
c2xEb2MgJyAiU2V0IiB3aWxsIGFsc28gd29yayBoZXJlCiAgU2V0IHhtbERv YyA9IFdTY3JpcHQu
Q3JlYXRlT2JqZWN0KCJNc3htbDIuRE9NRG9jdW1lbnQuMy4wIikKICB4bWxE b2MuYXN5bmMgPSBm
YWxzZQogIHhtbERvYy5sb2FkICJib29rcy54bWwiCiAgSWYgKHhtbERvYy5w YXJzZUVycm9yLmVy
cm9yQ29kZSA8PiAwKSBUaGVuCiAgICBteUVyciA9IHhtbERvYy5wYXJzZUVy cm9yCiAgICBXU2Ny
aXB0LkVjaG8gIllvdSBoYXZlIGVycm9yICIgKyBteUVyci5yZWFzb24KICBF bHNlCiAgICBTZXQg
eHNsUHJvYyA9IHhzbHQuY3JlYXRlUHJvY2Vzc29yCiAgICB4c2xQcm9jLmlu cHV0ID0geG1sRG9j
ICcgIlNldCIgd2lsbCBmYWlsIGhlcmUKICAgIHhzbFByb2MuYWRkUGFyYW1l dGVyICJwYXJhbTEi
LCAiSGVsbG8iCiAgICB4c2xQcm9jLnRyYW5zZm9ybQogICAgV1NjcmlwdC5F Y2hvIHhzbFByb2Mu
b3V0cHV0CiAgRW5kIElmCkVuZCBJZgoKPiBJdCBtYWtlcyBhIGNlcnRhaW4g YW1vdW50IG9mIHNl
bnNlIHRvIGZvcmNlIHRoZSB1c2VyIHRvIGFzc2lnbiBhIHZhbHVlCj4gYW5k IG5vdCBhbiBvYmpl
Y3QsIGJ1dCBtb3N0IG90aGVyIE9MRSBvYmplY3RzIHNlZW0gdG8gYWxsb3cg ZWl0aGVyIGFuZAo+
IHNpbXBseSBjYWxsIHRoZSBkZWZhdWx0IG1ldGhvZCB0aGVtc2VsdmVzIGlm IHRoZXkgY2FuJ3Qg
ZGVhbCB3aXRoIGFuCj4gb2JqZWN0Lgo+IAo+IEkgZG9uJ3Qgd2FudCB0byBk aXZlIGludG8gaW5k
ZXhlZCBwcm9wZXJ0aWVzIGhlcmUsIGFzIGl0IGRvZXMgbm90Cj4gYXBwbHkg dG8geW91ciBzaXR1
YXRpb24uCgpGaW5lLCBJIGNhbiB3YWl0IHRpbGwgSSBidW1wIGludG8gdGhl bS4KCj4gSSB3b3Vs
ZCBub3QgYm90aGVyIHdpdGggdGhpcyB0eXBlbGliIHN0dWZmLCBqdXN0IGFs d2F5cyB1c2UgImJ5
Cj4gcmVmZXJlbmNlIiBhc3NpZ25tZW50cyBldmVyeXdoZXJlLCBhbmQgb25s eSB3aGVuIGl0IGZh
aWxzIGludmVzdGlnYXRlCj4gaWYgeW91IGFyZSBydW5uaW5nIGludG8gYSBs aW1pdGF0aW9uIG9m
IHRoYXQgb2JqZWN0cyBpbXBsZW1lbnRhdGlvbgo+IGFuZCBoYXZlIHRvIHVz ZSAiYnkgdmFsdWUi
IGFzc2lnbm1lbnQgZXhwbGljaXRseS4KCkV4Y2VsbGVudCwgSSdtIGdvaW5n IHRvIGZvbGxvdyB0
aGF0IHJvdXRlLiBUaGFua3Mgb25jZSBtb3JlIQoKTWljaGFlbApfX19fX19f X19fX19fX19fX19f
X19fX19fX19fX19fX19fX19fX19fX19fX19fXwpBY3RpdmVQZXJsIG1haWxp bmcgbGlzdApBY3Rp
dmVQZXJsQGxpc3RzZXJ2LkFjdGl2ZVN0YXRlLmNvbQpUbyB1bnN1YnNjcmli ZTogaHR0cDovL2xp
c3RzZXJ2LkFjdGl2ZVN0YXRlLmNvbS9tYWlsbWFuL215c3Vicw==