【发布时间】:2015-07-20 13:43:42
【问题描述】:
假设我在自定义控件中实现了一些 UIA 模式。说,TablePattern。如果出现任何问题,现有实现将返回 null。但是调试起来不是很方便。我可能在自动化同行中有更多的上下文。例如,对于GetItem(int row, int column),我可能会说提供的参数超出范围,而不仅仅是返回 null。
如果我从自动化对等方抛出异常 - 在 UIA 客户端,我会从 IUIAutomationPatternInstance 对象获得 TargetInvocationException,但没有任何详细信息(InnerException 属性为空)。
有没有办法让 UIA 将带有一些附加信息的错误从 UIA 服务器端传递到 UIA 客户端?
UPD: 在与 cmets 中提供的示例 @SimonMourier 进行一些调查和比较后,我发现 TargetInvocationException 是我的错。修复它here。
现在我得到了正确的异常类型,但只有一个标准的异常消息。对于IndexOutBoundsException,它是“索引超出了数组的范围。”不管我一直试图在 UIA 服务器端设置什么异常。
不同之处在于我不是通过标准托管 UIAutomationClient 调用 UIA 方法,而是使用我自己的代码一直到 COM 调用(标准托管库不支持我想要的自定义 UIA 模式采用)。标准库可以很好地传递异常消息。我试图追踪其中的区别并发现以下内容:
- 标准托管库通过定义为
private static extern int RawGridPattern_GetItem(SafePatternHandle hobj, int row, int column, out SafeNodeHandle pResult);的方法通过 InternallCall here 调用 P/Invoke。它返回 HRESULT,由CheckError方法通过调用Marshal.ThrowExceptionForHR(hr);处理。此时会出现带有正确消息的异常,正如在 UIA 服务器端引发的那样。 - 我使用的 UIAComWrapper 看起来与
c:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include\UIAutomationClient.idl中定义的 COM call 与HRESULT GetItem ([in] int row, [in] int column, [out, retval] IUIAutomationElement ** element );相同。根据我对 COM 互操作的理解,重写返回值机制会自动检查 HRESULT,如有必要则抛出异常,否则返回out result参数。除了异常消息由于某种原因没有被翻译之外,它确实如此。
要重现该问题,您可以尝试this project。 lib 文件夹中的文件是从this repository 构建的。如果 ConsoleApplication1 引用 UIAComWrapper 库 - 异常带有默认消息。如果您将引用更改为使用标准 UIAutomationClient - 它会收到自定义的。
【问题讨论】:
-
您是否检查过 SystemAlert 事件 (UIA_SystemAlertEventId / 20023)? msdn.microsoft.com/en-us/library/windows/desktop/…(仅适用于 Windows 8+,标准 .NET UIAutomation dll 不支持,但您似乎知道的 UIAComWrapper 不支持它:-)
-
@SimonMourier 事件是可能的,但这意味着应该先有人在那里订阅。并且应该在每次调用之前完成以获取此类错误信息。以类似的方式,可以声明返回最后一个错误详细信息的独立 UIA 属性 - 类似于
GetLastError。不是很吸引人的解决方案(但当然可以实施)。 -
好吧,对于 UIA 来说,Windows 8 SDK 中的 UIAutomationCore.idl 和 UIAutomationClient.idl 中的内容并没有更多。那里的接口不是 IDispatch 接口,因此不是为了携带额外的异常信息(.NET 喜欢的 EXCEPINFO 结构)而设计的。我认为你必须想出一种传统的方法来定义什么是错误(从 UI 角度)以及它们是如何发生的。您还可以使用非常通用的 IAnnotationProvider 或 IObjectModelProvider
-
@SimonMourier 如果我理解正确,UIA 客户端会在调用后查看 HRESULT,如果有适当的异常(例如
ElementNotAvailableException),则将其转换为异常。但我不明白 UIA 服务器端如何在那里设置 HRESULT - 即使在自动化对等中我抛出ElementNotAvailableException- 客户端仍然看到TargetInvocationException。也许我做错了什么,但不知道如何实际调试它。 -
事实上,我无法重现您的问题。这是一个示例 WPF UserControl,它引发了一个异常,该异常显示在示例控制台应用服务器中:pastebin.com/xH7QmHhe
标签: c# .net wpf ui-automation