Предположим, что я использую шаблон UIA в своем настраиваемом элементе управления. Скажем, TablePattern
. Существующие реализации возвращают null, если что-то пошло не так. Но отлаживать не очень удобно. У меня может быть больше контекста в узле автоматизации. Например, для GetItem(int row, int column)
я могу сказать, что предоставленные аргументы за пределами границ, а не просто возвращают null.
Если я выдаю исключение из peer автоматизации - на стороне клиента UIA я получаю объект TargetInvocationException
из IUIAutomationPatternInstance
без каких-либо подробностей (свойство InnerException равно null).
Есть ли способ заставить МАУ пройти ошибку с некоторой дополнительной информацией со стороны UIA-сервера на стороне UIA-клиента?
UPD: После некоторого исследования и сравнения с примером @SimonMourier, представленным в комментариях, я обнаружил, что TargetInvocationException
был моей ошибкой. Исправлено это здесь.
Теперь я получаю правильный тип исключения, но только стандартное сообщение об исключении. Для IndexOutBoundsException
это "Индекс находился за пределами массива". независимо от того, что я пытался исключить на стороне сервера UIA.
Разница в том, что я пытаюсь вызвать метод UIA не через стандартный управляемый UIAutomationClient, но с моим собственным кодом вплоть до COM-вызова (стандартная управляемая библиотека не поддерживает пользовательские шаблоны МАУ, которые я бы хотел использования). Стандартная библиотека отлично передает сообщения об исключениях. Я попытался отслеживать разницу и нашел следующее:
- Стандартная управляемая библиотека делает вызов P/Invoke через InternallCall здесь с помощью метода, определенного как
private static extern int RawGridPattern_GetItem(SafePatternHandle hobj, int row, int column, out SafeNodeHandle pResult);
. Он возвращает HRESULT, который обрабатывается методомCheckError
посредством вызоваMarshal.ThrowExceptionForHR(hr);
. В этот момент появляется исключение с правильным сообщением, которое было выбрано на стороне сервера UIA. - UIAComWrapper, который я использую, выглядит как бы COM-вызов, определенный в
c:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include\UIAutomationClient.idl
какHRESULT GetItem ([in] int row, [in] int column, [out, retval] IUIAutomationElement ** element );
. В моем понимании COM Interop механизм перезаписи возвращаемого значения автоматически проверяет HRESULT, при необходимости выдает исключение и возвращает аргументout result
в противном случае. Это действительно так, за исключением того, что сообщение об исключении не может быть переведено по какой-либо причине.
Чтобы воспроизвести проблему, вы можете попробовать этот проект. Файлы в папке lib были созданы из этого репозитория. Если ConsoleApplication1 ссылается на библиотеку UIAComWrapper - исключение поставляется с сообщением по умолчанию. Если вы измените ссылку на использование стандартного UIAutomationClient вместо этого - он получает пользовательский.