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

时间:2016-01-05 21:54:33

标签: com racket

我正在尝试使用来自Racket 6.x的MS UI自动化(系统下用于UIAutomationcore.dll的MS SDK下的UIAutomationCore.idl)并且安全球拍调用失败并且无法获得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。

2 个答案:

答案 0 :(得分:2)

在参考之后花了一些时间(感谢汉斯的初步评论),我现在知道了答案。这不是如何充分利用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 ...)。

还有其他细节需要注意将函数的返回值转换为/从Racket值转换,因此了解C FFI会有所帮助,这就是为什么在深入研究之前应该更好地学习Racket C FFI。

以下是有关如何使用IUnknown接口的更新。请注意,_IUIAutomation-pointer定义自动来自上面的define-com接口。

(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))

答案 1 :(得分:1)

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