Accessing Windows Contacts (pre Win10) from JScript (or any ActiveScripting) - com

I want to use the COM object with the progID Windows.Contact.1 via ActiveScripting (JScript, VBScript, Python, etc).
This COM resides in C:\Program Files (x86)\Common Files\System\wab32.dll. It seems, there is no TypeLib available for it. The COM delivers, amongst others, IContact for the "Windows Address Book" (storing contacts as XML in folders, as in Windows 7). IContact is documented here.
In JScript I did:
var co = new ActiveXObject("Windows.Contact.1");
typeof co; // results in: unknown
Since it results in unknown, I have the suspicion, that this COM could not be usable for scripting. Somewhere I read, that everything, that inherits from IUnknown can not be used for scripting, instead it must inherit from IDispatch. But I am unsure, as to how much of this is valid, and whether there are workarounds.
I would like to ask for acknowledgement of my suspicions (since I am new to all of this and have no C++ or C# background) or to ask for a way, as to how to use Windows.Contact.1 from scripting, including a way, to find out, which methods/objects I can use, without resorting to a TypeLib.
I have access to pages like Programming Windows Contacts and related ones, but first I need to get an instance in ActiveScript (JScript, VBScript, Python, Lua will do). I also have access to applications like "MS OLE View" and "OLEView DotNet". Thank you.

There are entire books on the subject, but here's a very simplified story. There are basically 3 "categories" of COM interfaces:
Interfaces deriving from IUnknown
aliases for programming against: early binding, (custom) vtable binding
the simplest way to implement a COM "server"
it's only a binary contract (methods layout, method signature, parameters behavior like in/out for cross-apartment/process support, ...)
you need to somewhow tell your callers what is this binary contract you support (you can use .idl, .tlb or anything that your caller can understand)
there are some official ways of documenting your IUnknown-derived interfaces: .idl -> .h and .tlb is the most standard one
only supported by a certain class of languages (for example C/C++, .NET, Delphi), those who understand .tlb (or .idl, or equivalent .h), or those who allow redefining layout manually (like .NET). You can perfectly define a language that can do that w/o ever using .tlb. That's the beauty of COM, it's just a binary contract.
if your language doesn't support it, you just can't use it, you'll have to write or use a wrapper with a language that supports it and exposes it in a way your language supports. Powershell for example doesn't support IUnknown-derived interfaces (I'm not 100% sure) but supports .NET so it can use .NET as a "super wrapper".
IDispatch interface
only requires one IUnknown well-known interface implementation: IDispatch
aliases for programming against: late binding, OLE automation, COM automation, or simply Automation (not to confuse with UI Automation)
invented for higher level languages (VB/VBA first, ActiveScripting a bit later)
only supported by a certain class of language, and the way it's supported varies (for example it's supported in C++ of course but it's not super easy w/o wrappers or tooling like Visual Studio's C++ #import directive). JScript and VBScript don't exactly support the same set of features with regards to Automation.
you're supposed to use only a predefined list of types "Automation-Compatible types":
these types where initially very related to VB/VBA (VARIANT, SAFEARRAY, BSTR which means "Basic String"...)
from the higher level language, it really makes COM much transparent and easier as that was the whole point (and can make it harder from the lower level ones...), it also allows "syntactic sugar" niceties
note the IDispatch implementation can be very dynamic and really late-bound at runtime (get id of name -> invoke) but most available programming tooling quite freezes the list of ids/names at compile time (ex: .NET) because they support Dual interfaces.
Dual interfaces:
interfaces that implement a custom IDispatch-derived interface and implement IDispatch itself to match the custom interface (both implementations supposedly being "equivalent" of course). Have a look at the link below, it has nice images.
because of IDispatch, you're supposed to use only Automation compatible data types in the IDispatch-derived method.
it's more work to implement (so it's usually done by programming tools, for ex: ATL)
a bit easier for native (C/C++, etc.) callers (no need to use IDispatch wrappers) but you still have to digest automation data types
IMHO, one of the best 1-page introduction to COM is here: Introduction to COM

Related

Scripting MFC Dialogs via COM

MS Word has a very useful mechanism to wrap up its dialog boxes to use via COM or .Net. You can execute a "Display" method - which does the obvious - and also an "Execute" method which is equivalent to pressing "OK". I have a legacy MFC app which I am attempting to attach a COM object model to for scripting and regression testing, and I would like to do the same thing. It has a number of dialogs that I want to control programmatically from my test harness. It's been years since I really delved into MFC, and I can't find anything useful on t'internet so far.
My guess would be to wrap up the CDialog derived classes, perhaps within an ATL class (ATL is used extensively in the project), but I have a suspicion that there may be a better way.
Worst case scenario, I'll move the dialogs to C# and make them COMVisible (which is probably more strategic), but that's going to be more work.
Any thoughts and help appreciated - obviously this is rather antiquated technology!
All CDialog derived classes in MFC are a subclass of CCmdTarget.
CCmdTarget is the baseclass for MFC COM functionality.
There is a lot of work you have to do under the hood. You should define and IDL file for your interfaces, compile the IDL, and then have the compiled typelibrary be a resource in your program.
There are helper macros for your CCmdTarget derived classes like:
DECLARE_INTERFACE_MAP()
BEGIN_INTERFACE_PART()
END_INTERFACE_PART()
BEGIN_INTERFACE_MAP()
INTERFACE_PART()
END_INTERFACE_MAP()
I would say that if you want to see how MFC does it, use the App Wizard and generate an MFC application that has OLE Automation enabled and then look at the generated code. It will show you what you need to wire up your MFC app for OLE Automation.

Two simple COM IDL syntax questions: is there a way to specify the threading model, and do I need void to say "no arguments"?

Two simple COM IDL file questions I can't seem to find answers for, even with searching MSDN and the general internet:
Is there an interface attribute which lets me specify my interface is to be implemented by STA objects only, or is this a detail for my documentation alone? I already have [object, local] which I think is correct for non-remoting (in-process) COM objects.
Do I need void in the parentheses of my method declarations (like in C) to specify no arguments? MSDN is inconsistent about this; so are header files. My own personal implementations of this interface will be in C.
Thanks.
You are talking about the threading model you want to specify for your COM component. No, you cannot put that in the IDL, it is far too important. A client doesn't have to use your IDL, a scripting language like Javascript never will for example. It must go in the registry, in the CLSID key for your component. You want ThreadingModel = "Apartment" to request the client to provide an STA thread. If it is missing then COM assumes that by default.
Do keep in mind that this does not force the client programmer to provide one. If he favors MTA for some reason then COM will provide the STA thread to give your component as safe home. If your proxy makes it too slow to be usable then you do have a documentation requirement.
No HRESULT Method(void) in the IDL is not necessary, using HRESULT Method() is sufficient. Midl.exe doesn't care what language you use.

For a lanuage to work with com object does it need to have an api and compiler developed specific for com?

In the documentation for com it says that it works literally with every language. Do you need to have a specific API for that language so it can interface with com, or can any language literally just use it out of box? Also do you need a special compiler? Sorry if this is a stupid question but I have never used it before, and I have been trying to find this answer. When I look at demos of com examples it all seems to access the objects in a c style syntax, are their bindings and apis for other languages (literally all)?
The key thing about COM is that it is a "binary standard": which is to say that it doesn't care what the language used is, so long as the bits and bytes in memory end up in the right place.
COM basically specifies that all COM objects must have a specific layout in memory: the interface pointer points to a pointer that in turn points to a table of function pointers, which has at least three members, the first three of which are pointers to the IUnknown functions (AddRef, Release, QueryInterface), and the remainder are pointers to the other functions in the interface. COM also specifies how arguments are passed to these functions - so that the caller and callee agree on how the stack is used, and who pops off the values.
This requirement happily matches how C++ just happens to work on Windows; so most C++ classes that implement IUnknown will just happen to ends up as being valid COM classes: this is because Microsoft's implementation of C++ happens to use an object layout that matches what COM requires: the C++ object vtable pointer is the same as the COM pointer-to-table-of-function-pointers, the C++ table of function pointers is exactly what COM requires for its table-of-function-pointers, and so on. (This isn't entirely just a happy coincidence: COM was likely designed to take advantage of the most common way that C++ objects are implemented in memory which is the technique that MS's compiler uses. Note that C++ the language specification doesn't actually specify any particular object layout - so you could have a 3rd party C++ compiler that implemented C++ in a way that gave you classes that are not usable by COM. But no compiler vendor in their right mind would do that, since they would appear to be broken compared to the others!)
In plain C, you can create a COM object by creating suitable structs-containing-pointers manually. This works because C essentially allows you to specify binary-level memory layout for structs manually; you can create structs that you know will have the appropriate layout that COM is expecting.
In other languages, especially those that don't allow the user to specify memory layout explicitly, you need support from the language to allow for COM support. All the .Net languages - C#, VB.Net, and so on - use support in the .Net runtime that understands what COM expects, and produces the appropriate wrappers as needed to allow the interop to work.
So, long story short, it's not the case that any language under the sun will automatically work with COM; it's really the case that a couple of languages - namely C and C++ - are already aligned with COM's requirements; and most other languages will need some compiler support to make it work.

What is an "automation-compatible language"?

I have found many references to this term on the web, especially on Microsoft's MSDN website, and even lists of such languages. However, I can't find a definition of this term. (Is it something as simple as a language for which a COM interface has been implemented?)
Please let me know if you know of a link to a definition.
Thanks.
Stripped down to bare essentials, to understand COM you have to understand GUIDs and IUnknown. The equivalent for Automation is ProgIDs and IDispatch.
A ProgID helps you create a COM coclass. A typical ProgID is "Word.Automation", the progid for Microsoft Word. You'll find them listed in the Registry under HKEY_CLASSES_ROOT. A typical name for a helper function in your language is CreateObject(). You pass it the ProgID, optionally a machine name, and you get back an interface reference. Which you can then use to make method calls and get/set properties.
The language runtime uses the IDispatch interface (retrieved with IUnknown::QueryInterface) to discover the names and parameters of the methods that are implemented by the COM server. This is called late-binding, the way any scripting language uses Automation. It has only 4 methods:
IDispatch::GetTypeInfoCount(), returns 1 if the server can provide type info
IDispatch::GetTypeInfo(), returns type information, helpful to make type-safe calls
IDispatch::GetIDsOfNames(), maps an identifier name to a number
IDispatch::Invoke(), calls a numbered method or property getter/setter.
That's all it takes.
In Microsoft Windows applications
programming, OLE Automation (later
renamed by Microsoft to just
Automation,1[2] although the old
term remained in widespread use), is
an inter-process communication
mechanism based on Component Object
Model (COM) that was intended for use
by scripting languages – originally
Visual Basic – but now are used by
languages run on Windows.[3] It
provides an infrastructure whereby
applications called automation
controllers can access and manipulate
(i.e. set properties of or call
methods on) shared automation objects
that are exported by other
applications.
From Wikipedia entry

What is COM?

I searched hard, but was unable to grasp the whole idea. Can anyone tell me:
What COM actually is?
How do GUIDs work, and how are they used by COM?
How does COM resolve the issues of different DLL versions.
Or at least, point me to a good article somewhere that explains these concepts?
Thanks!
COM is "Component Object Model". It is one of the first technologies designed to allow "binary reuse" of components... Originally, it was the rewrite of what was, in Microsoft Office circa 1988-1992 time frame, referred to as Dynamic Data Exchange (DDE), a technology designed to allow the various Office applications to talk to one another. The first attempt to rewrite it was called OLE-Automation (Object Linking and Embedding). But when they got done they renamed it to COM.
How it works:
Essentially, before COM, when a client component wanted to use a component (written as a C++ library), it had to be compiled WITH the library, so it could know exactly how many bytes into the compiled binary file to find each method or function call.
With COM, there is a defined mechanism as to how these methods will be structured, and then the compiler produces a separate file (called a type library or an Interface Definition Language (IDL) file, that contains all this function offset data.
Then, as a user of the component, you have to "register" it, which writes all this information (Keyed off of GUIDs) into the OS Registry, where any client app can access it, and by reading the data from the registry, it can know where in the binary file to find each method or class entry point.
Your question is a little large for a full explanation here. A quick high-level introduction to COM can be found in the book Understanding ActiveX and OLE. A more detailed but still introductory introduction is Inside COM. The best book on the subject is Don Box's Essential COM.
A couple of quick answers:
COM is a binary interface standard for objects. It allows various programs to write to interfaces without all having to have been written in the same langauge with the same compiler. There are also related services available.
GUIDs are globally unique numbers that COM uses to identify interfaces.
COM doesn't resolve different DLL version problems. It only allows a single DLL to be registered for each GUID.
COM enables reusable software. Like building blocks, you can create COM objects (or now Assemblies in .NET) to provide functionality to a larger piece of software. I have used COM to provide DB integration for Excel and MS BizTalk. Software like MS BizTalk use COM/Assemblies to extend the processing capabilities of a standard process; you can insert a COM into the message workflow to do more processing than is implemented by Microsoft. COM also allows use of Component Services providing built in object pooling, security, and control interface.
Wikipedia has a good definition of GUID. Note that Microsoft has a formatting that is not necessarly used in the rest of development community.
COM by itself does not resolve DLL version issues. It enables you to extend software incrementally if you use the COM versioning capability. So if you have an application that uses a COM to convert XML to Text (for example) and you want to enhance, you can create a new version (2.0) which you can roll-out slowly as you update the source application to use the new COM. This way you could (if need be) have a switch statement that can still use the old COM if required by system limitations, or use the new one (they would be different DLLs).
COM is a lot of different things. I recommend Don Box's book, Essential COM as a good way to learn.
At a bare minimum, a COM object is an object that exposes a single interface, IUnknown. This interface has 3 methods, AddRef, Release, and QueryInterface. AddRef/Release enables the object to be reference counted, and automatically deleted when the last reference is released. QueryInterface allows you to interrogate the object for other interfaces it supports.
Most COM objects are discoverable. They are registered in the registry under HKEY_CLASSES_ROOT with an identifying GUID, called a CLSID (class ID). This enables you to call CoCreateInstance to create an instance of a registered object if you know a GUID. You can also query the registry via a COM API for the CLSID that backs a ProgId (program id), which is a string that identifies the object.
Many COM objects have typelibs that specify the interfaces and methods the object supports, as well as IDispatch which has a method, Invoke, that allows you to dynamically call methods on the object. This enables the object to be used from scripting languages that don't support strong typing.
Some objects support being run in a different process, on a different thread, or on a different machine. COM supports marshalling for these types of objects. If possible, a standard marshaller can use the object's typelib to marshal calls to the object, but custom marshallers can be provided as well.
And there's a whole lot more to COM objects, I'm barely scratching the surface.
10,000 foot view:
COM is the communication mechanism for software components. Example, you can interact with COM interfaces (COM interop in .NET) to use functionality not exposed through a common interface (.NET assembly).
GUIDs are explained fairly decent on Wikipedia http://en.wikipedia.org/wiki/Globally_Unique_Identifier
I always understood LIB files to be object files for the C++ linker. They contain the code for all objects in a cpp file. The compiler optimizes when it links disregarding portions of the object file that it doesn't need.
Someone please clarify as I am sure I butchered some of this.
COM is Microsoft's Component Object Model, a binary-compatible interface for programs written in various languages to interoperate with each other. It is the "evolutionary step" between the OLE and .NET technologies.
If you want to learn about COM from the C++ perspective, take a look at Don Box's Essential COM, or ATL Internals by Rector and Sells.
The group microsoft.public.vc.atl is probably the best place to ask questions you can't get answers for here. It's primarily an ATL newsgroup, but it seems to be the newsgroup with the most traffic for general COM questions as well. (just be prepared for the usual newsgroup curtness & impatience)
COM is a method to develop software components, small binary exe, that provides services for applications, OS and other components. Developing custom COM comnponent is like developing Object oriented API. GUID is a Global unique ID and used to identify a COM component uniquely.
You can refer a very good book by Dale Rogerson for more details. Inside COM