Angenommen, ich implementiere ein UIA-Muster in meinem benutzerdefinierten Steuerelement. Sag, TablePattern
. Vorhandene Implementierungen geben NULL zurück, wenn etwas schief gelaufen ist. Aber es ist nicht sehr bequem zu debuggen. Ich könnte mehr Kontext im Automatisierungspeer haben. Zum Beispiel könnte ich für GetItem(int row, int column)
sagen, dass die bereitgestellten Argumente außerhalb der Grenzen liegen und nicht nur null zurückgeben.Wie können Fehler vom UI Automation-Musteranbieter zurückgegeben werden?
Wenn ich eine Ausnahme von Automatisierung Peer werfen - auf der UIA-Client-Seite bekomme ich TargetInvocationException
von IUIAutomationPatternInstance
Objekt ohne Details (InnerException-Eigenschaft ist null).
Gibt es eine Möglichkeit, UIA Fehler mit einigen zusätzlichen Informationen von UIA-Server-Seite zu UIA-Client-Seite übergeben?
UPD: Nach einigen Untersuchungen und Vergleich mit Beispiel @SimonMourier in Kommentaren versehen Ich fand, dass TargetInvocationException
meine Schuld war. Es wurde behoben here.
Jetzt bekomme ich korrekte Ausnahme-Typ, aber nur eine Standard-Ausnahme-Nachricht. Für IndexOutBoundsException
ist es "Index war außerhalb der Grenzen des Arrays." unabhängig davon, was ich versucht habe, eine Ausnahme auf der UIA-Serverseite zu machen.
Der Unterschied ist, dass ich versuche, UIA-Methode nicht über Standard verwaltet UIAutomationClient, sondern mit meinem eigenen Code bis hin zu COM-Aufruf (Standard verwaltete Bibliothek unterstützt benutzerdefinierte UIA-Muster, die ich möchte benutzen). Die Standardbibliothek übergibt Exceptions-Nachrichten einfach. Ich habe versucht, zu verfolgen, was der Unterschied ist, und fanden die folgende:
- Standard-verwalteten Bibliothek Aufruf P macht/Invoke durch InternallCall here über Verfahren wie
private static extern int RawGridPattern_GetItem(SafePatternHandle hobj, int row, int column, out SafeNodeHandle pResult);
definiert. Es gibt HRESULT zurück, das vonCheckError
Methode über Aufruf anMarshal.ThrowExceptionForHR(hr);
behandelt wird. An dieser Stelle erscheint die Ausnahme mit der korrekten Nachricht, die auf der Seite des UIA-Servers geworfen wurde. - UIAComWrapper, die ich benutze scheinbar gleich definiert in
c:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include\UIAutomationClient.idl
alsHRESULT GetItem ([in] int row, [in] int column, [out, retval] IUIAutomationElement ** element);
. Nach meinem Verständnis von COM Interop überprüft der Mechanismus zum Umschreiben des Rückgabewerts automatisch HRESULT, löst bei Bedarf eine Ausnahme aus und gibt ansonsten das Argumentout result
zurück. Es tut wirklich, außer dass Ausnahmemeldung aus irgendeinem Grund nicht übersetzt wird.
Um das Problem zu reproduzieren, können Sie versuchen this project. Dateien im lib-Ordner wurden von this repository erstellt. Wenn ConsoleApplication1 auf die UIAComWrapper-Bibliothek verweist, wird die Standardnachricht ausgegeben. Wenn Sie stattdessen den Verweis auf den Standard-UIAutomationClient ändern, wird dieser benutzerdefiniert.
Haben Sie das SystemAlert-Ereignis (UIA_SystemAlertEventId/20023) überprüft? https://msdn.microsoft.com/en-us/library/windows/desktop/ee671223(v=vs.85).aspx (nur für Windows 8+, wird nicht von den Standard-.NET UIAutomation dlls unterstützt, sondern von der UIAComWrapper, das Sie zu kennen scheinen: –
@SimonMourier Ereignisse sind möglich, aber es würde bedeuten, dass jemand zuerst dort abonniert haben sollte. Und es sollte vor jedem Anruf gemacht werden, um solche Fehlerinformationen zu erhalten. In ähnlicher Weise könnte man eine eigenständige UIA-Eigenschaft deklarieren, die Details des letzten Fehlers zurückgibt - etwa "GetLastError". Nicht sehr ansprechende Lösung (aber natürlich umsetzbar). –
Nun, es gibt nichts mehr zu UIA, was in UIAutomationCore.idl und UIAutomationClient.idl vom Windows 8 SDK ist. Da Schnittstellen keine IDispatch-Schnittstellen sind, sind sie nicht dafür ausgelegt, zusätzliche Ausnahmeinformationen (EXCEPINFO-Struktur, die .NET mag) zu tragen. Ich denke, dass Sie eine konventionelle Methode finden müssen, um Fehler zu definieren (aus einer UI-Perspektive) und wie sie passieren. Sie könnten auch IAnnotationProvider oder IObjectModelProvider verwenden, die ziemlich generisch sind –