Racket COM:无法获取对象的 IDispatch 接口 - 下一步是什么?

Racket COM: cannot get IDispatch interface for object - what's next?

我正在尝试使用来自 Racket 6.x 的 MS UI Automation(UIAutomationCore.idl 在 MS SDK 下用于 UIAutomationcore.dll 在系统下)并且安全球拍调用失败并显示无法获取 IDispatch 错误。代码如下:

#lang racket
(require ffi/com)

(define clsid-cuia (string->clsid "{ff48dba4-60ef-4201-aa87-54103eef594e}"))
(define cuia-instance (com-create-instance clsid-cuia))
(com-methods cuia-instance)

适用于同一接口的 C++ 代码:

CoCreateInstance(CLSID_CUIAutomation, NULL,
                        CLSCTX_INPROC_SERVER, IID_IUIAutomation,
                        reinterpret_cast<void**>(ppAutomation));

我的问题是,我应该怎么做才能使用这个界面?我一直试图在球拍参考中找到答案,但花了很多时间没有答案。我还没有研究过 Racket C FFI(COM 的 5.12 节除外),想知道在尝试使用比上面的代码更高级的任何东西之前我是否应该学习整个 FFI。

在参考资料上花了更多时间(感谢 Hans 最初的评论)后,我现在知道了答案。这不是如何充分使用 UIA 界面的答案,而是继续进行的方式(正如我在问题中所问的那样)。

由于 UIAutomation 等派生自 IUnknown,我们需要使用 (define-com-interface ...) 定义 COM 接口。

开始的方法是:

(define-com-interface (_IUIAutomation _IUnknown)
  ; a better approach would be to write a macro to read the idl file,
  ; and parse it, then use the result to define the methods
  ; and define each corresponding method in order below. The first two
  ; doesn't have the full description yet
  ([CompareElements _fpointer]
  [CompareRuntimeIds _fpointer]
  [GetRootElement (_hmfun (p : (_ptr o _IUIAutomationElement-pointer))
                          -> GetRootElement p)]
  ))

并且由于上面的 _IUIAutomationElement-pointer 尚未定义,我们应该定义它以及我们将单独使用的其他接口 (define-com-interface ...)。

还有其他细节需要注意,因为转换函数的 return 值 to/from Racket 值,所以了解 C FFI 会有所帮助,这就是为什么人们应该更好地学习 Racket C FFI在进一步研究之前。

这里更新了如何使用 IUnknown 接口。请注意,_IUIAutomation 指针定义自动来自上面的 define-com-interface。

(define clsid-cuia (string->clsid "{ff48dba4-60ef-4201-aa87-54103eef594e}"))
(define IID_IUIAutomation (string->iid "{30cbe57d-d9d0-452a-ab13-7ac5ac4825ee}"))

(define cuia (com-create-instance clsid-cuia))
(define iuia (QueryInterface (com-object-get-iunknown cuia)
                               IID_IUIAutomation
                               _IUIAutomation-pointer))
(define root-element (GetRootElement iuia))

您应该查看 com-create-instance 命令的文档,因为该函数(如 C++ 代码中所示)需要更多参数。特别是,您应该为接口提供 IID,它可以是 IDispatch IID {00020400-0000-0000-C000-000000000046}。最有可能的是,IID_IUIAutomation 参数代表了这一点。