从 JScript(或任何 ActiveScripting)访问 Windows 个联系人(Win10 之前的版本)

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

我想通过 ActiveScripting(JScript、VBScript、Python 等)使用 progID Windows.Contact.1 的 COM 对象。

此 COM 位于 C:\Program Files (x86)\Common Files\System\wab32.dll。似乎没有可用的 TypeLib。除其他外,COM 为 "Windows Address Book" 提供 IContact(在文件夹中将联系人存储为 XML,如 Windows 7) . IContact is documented here.

我在 JScript 中做了:

var co = new ActiveXObject("Windows.Contact.1");
typeof co;  // results in: unknown

因为它导致 unknown,我怀疑这个 COM 不能用于脚本。我在某处读到,从 IUnknown 继承的所有内容都不能用于脚本,而必须从 IDispatch 继承。但我不确定其中有多少是有效的,以及是否有解决方法。

我想请求确认我的怀疑(因为我对所有这些都是新手并且没有 C++ 或 C# 背景)或寻求一种方法,关于如何使用 Windows.Contact.1 来自编写脚本,包括一种方法,以找出我可以使用哪些 methods/objects,而无需诉诸 TypeLib。

我可以访问 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" 这样的页面。谢谢。

关于这个主题的书籍很多,但这里有一个非常简单的故事。 COM接口基本上有3个"categories":

接口派生自 IUnknown

  • 用于编程的别名:早期绑定、(自定义)vtable 绑定
  • 实现 COM 的最简单方法"server"
  • 它只是一个 二进制 契约(方法布局、方法签名、参数行为类似于 in/out 以支持 cross-apartment/process,...)
  • 您需要以某种方式告诉您的调用者您支持的二进制合约是什么(您可以使用调用者可以理解的 .idl、.tlb 或 任何内容
  • 有一些官方方法可以记录您的 IUnknown 派生接口:.idl -> .h 和 .tlb 是最标准的方法
  • 仅受某些 class 语言支持(例如 C/C++、.NET、Delphi),理解 .tlb(或 .idl,或等效文件)的人.h),或那些允许手动重新定义布局的文件(如 .NET)。您可以使用 .tlb 完美地定义一种可以做到 w/o 的语言。这就是 COM 的美妙之处,它只是一个二进制契约。
  • 如果您的语言不支持它,您就不能使用它,您必须使用支持它的语言编写或使用包装器,并以您的语言支持的方式公开它。例如,Powershell 不支持 IUnknown-derived 接口(我不是 100% 确定)但支持 .NET,因此它可以将 .NET 用作 "super wrapper".

IDispatch界面

  • 只需要一个IUnknown众所周知的接口实现:IDispatch
  • 用于编程的别名:后期绑定、OLE 自动化、COM 自动化或简单的自动化(不要与 UI 自动化混淆)
  • 为高级语言发明(VB/VBA 首先,ActiveScripting 稍后)
  • 仅受某种 class 语言的支持,并且它的支持方式各不相同(例如,它当然在 C++ 中受支持,但它不是超级简单 w/o 包装器或像 Visual Studio 的 C++ #import 指令)。 JScript 和 VBScript 并不完全支持相同的自动化功能集。
  • 你应该只使用预定义的类型列表“Automation-Compatible types”:
  • 这些类型最初与 VB/VBA 非常相关(VARIANTSAFEARRAYBSTR,这意味着 "Basic String"...)
  • 从高级语言开始,它确实使 COM 变得更加透明和容易,因为这就是重点(并且可以使它从低级语言变得更难......),它还允许 "syntactic sugar" 细节
  • 请注意,IDispatch 实现在运行时可能非常动态且非常晚绑定(获取名称的 id -> 调用),但大多数可用的编程工具在编译时完全冻结了 ids/names 的列表时间(例如:.NET),因为它们支持 Dual 接口。

Dual 接口:

  • 实现自定义 IDispatch-derived 接口并实现 IDispatch 自身以匹配自定义接口的接口(当然,这两种实现都应该是 "equivalent")。看看下面的 link,它有漂亮的图像。
  • 由于 IDispatch,您应该在 IDispatch 派生方法中仅使用自动化兼容数据类型。
  • 实现起来比较麻烦(因此通常通过编程工具来完成,例如:ATL)
  • 对于本机(C/C++ 等)调用者来说更容易一些(无需使用 IDispatch 包装器)但您仍然需要消化自动化数据类型

恕我直言,最好的 COM 单页介绍之一在这里:Introduction to COM