tesonep / pharo-com

MIT License
8 stars 3 forks source link

Support for enumeration / _NewEnum / [VBScript] FOR EACH obj IN collection #12

Open Mr-Dispatch opened 3 years ago

Mr-Dispatch commented 3 years ago

Hi,

I can't find any way to do basic enumeration. While I can manually obtain the enumerator, it doesn't seem to support IDispatch interface (and my attempts to poke at it with available machinery quickly lead to VM crash).

I've tried to accomplish (as a starting point) the following:

Set objLocator = CreateObject("WbemScripting.SWbemLocator")
Set objService = objLocator.ConnectServer(".", "root\cimv2")
Set Products = objService.ExecQuery("SELECT * FROM Win32_Product")
For each Product in Products ' <-- this is what I can't figure out how to do
   ' ...
Next

In some cases, I can use Count and a numerical index to fake it, but SWbemPropertySet insists on using name as an index, or it can give you an enumerator.

So I can get at the properties if their name is specified beforehand, but I'd very much like to support cases like "give whatever WQL query, and the method will enumerate all the key/value pairs itself".

Maybe - if my assumption is correct & it will need COM enumeration interface support - it would be also nice to document it ("tutorial it" ?), it seems it would be a pretty small / isolated example of "how to support arbitrary COM interface".

eftomi commented 3 years ago

Maybe this will help: there is no support yet to translate COM / VB collections to Pharo collections. For instance, to open Word, add two empty documents into collection Documents and get the name of the first one, you have to issue the following:

Ole32Lib uniqueInstance initLibrary.
wrd := COMDispatchInstance createInstanceByName: 'Word.Application'.
wrd propertyNamed: 'Visible' put: true.
documents := wrd propertyNamed: 'Documents'.
documents dispatch: 'Add'.
documents dispatch: 'Add'.
doc1 := documents dispatch: 'Item' withArguments: { 1 }.
Transcript show: (doc1 propertyNamed: 'Name'); cr.

Word collection Documents has a property Count, you can get it with

Transcript show: (documents propertyNamed: 'Count')

An example of how to prepare a code to "translate" VBA / COM collections to Pharo can be found here: https://github.com/eftomi/PharoADO/blob/master/src/PharoADO/ADOFields.class.st, where the Fields collection is done.

In your case, you can try to go step by step and check with Inspector how specific COM object is visible to Pharo, especially when trying to distinguish between properties and functions (methods). Properties should be get/set with propertyNamed:set:,, functions with dispatch:withArguments:. VBA debugger sometimes obscures the inner workings with additional magic, so it's better to use Inspector in Pharo.

Hope this helps.

Mr-Dispatch commented 3 years ago

@eftomi Thank you very much for trying to help, but I already knew how to list IDispatch instance properties / methods (it's Smalltalk, just browse for it), knew how to manage in cases where count / numerical indexing works, etc.

Sadly, it isn't possible in all cases, and supporting the enumeration protocol / interface strikes me as the next required step (without it, not even "COM Automation / IDispatch" support can really be claimed).

For my use-case (pulling a bunch of stuff from WMI - like Win32_Product, MSFT_NetAdapter, Win32_Printer, ...), knowing the names of the properties is sufficient, but without enumeration support, I can't really package it (generic what-ever WMI access code) for general consumption.

[EDIT:] PS: I'm gonna take a look at how Racket implements it (they have both Automation/IDispatch layer, and a low-level "full COM interface support" layer). And they have a functions for enumeration (ie. com-enumerate-to-list) -- https://gist.github.com/Mr-Dispatch/7d575c3f53e1888d60eb7d9a906dce0b

I saw a flash of some Pharo VM support for VTables during installation, where should one look for best example usage (not too simple, not too complex, preferably) ?

PPS: Anyone has access through research paper paywalls ? I heard that the paper (can't remember the name, googling it failed, will try to post the name ASAP) on how Harlequin implemented COM support in Dylan is pretty informative.

eftomi commented 3 years ago

I don't know much about WMI, but I'd say that it is pretty specific.

https://stackoverflow.com/questions/20386875/iterating-over-swbempropertyset-objects

Maybe you can try to implement it yourself and contribute to pharo-com :-)

PS: I have access to some collections

Mr-Dispatch commented 3 years ago

What I'm trying to do might be a bit specific, but the enumeration support is so general / useful that probably every com interface I touched supported it (in most cases as language-native iterators/generators/...)..

The link you posted is probably the best I saw on the subject (back when Dolphin Smalltalk got open-sourced).

Sadly, there is no type library support in Pharo-COM (that I could find), and I can't find any examples of the VTable-FFI-Extension usage, so any implementation would have to be pointer+offset poking / direct memory address calls & arranging parameters. And since I know squat about Pharo FFI, I don't feel confident to try it.

Is the VTable extension even complete ? Nothing seems to reference it.