I can see that an element with specific Automation ID has children in the Inspect tool:
But when I try to retrieve them like this:
AutomationElement aPane = mainWindow.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.AutomationIdProperty, "8264"));
AutomationElementCollection theChildren = aPane.FindAll(TreeScope.Subtree, Condition.TrueCondition);
The aPane
element is retrieved correctly, but theChildren
element is empty. Any ideas what went wrong?
On rare occasions I've found that the
Find*
calls don't find all automation objects. The only consistent case I've seen with this that WPFTextBlock
controls, when in a data template, won't be found by those calls. In these cases, you can try theRawViewWalker
which is probably closer to what Inspect is doing internally.Actually the problem is that Inspect.exe is written in unmanaged code while I was trying to achieve the same results in managed code. Unmanaged code returns slightly different results than the managed version (e. g. manged code would return control type document where the unmanaged code would return edit in my application).
While it took me some time to understand it, unmanaged code is much faster, more accurate and therefore more reliable.
Some examples of unmanaged UI automation code for C# can be found in the Microsoft Windows UI Automation Blog e. g. here,
My original example is simplified. I tried to access children using 3 techniques:
Only the VB6 (unmanaged) code gave the same results as Microsoft's Inspect tool. I believe this confirms what others have said above: There are severe problems with Microsoft's UI Automation implementation in .Net. It may be that the only solution to this is to write a custom UI Automation client in .Net, but this assumes that the UI Automation servers in the target applications behave correctly. And those are beyond my control because the target applications are written by other companies, not mine.
A bit of a late answer, but I wanted to correct the answer chosen here. Yes, it's true that the VS provided COM wrapper may use a different UIAutomationClient.dll, and that using native code will be different to managed code while calling UIAutomation methods, but nonetheless the question asked here is a different issue. (By the way, you can use a COM wrapper from managed code to call the correct version of the UIAutomation dll's, which will solve issues like "inspect.exe finds it but my managed code cannot").
I also ran into the problem asked here (mine was: FindAll(TreeScope.Children, TrueCondition) not returning anything although FindFirst() was successfully returning children on the same control).
I tried mike-z's approach using RawViewWalker to find children and it worked fine for this case. I'm writing this separate answer to say that it wasn't Find* methods being the problem, but a difference between FindAll & FindFirst methods that caused August's problem.
Update
Inconsistent behavior seems to be the norm when it comes to MS tools. The reason for this update is, I've bumped into a similar issue with my tlbimp.exe'd RCW for uia using C#, and this time I wrote a direct equivalent C code and to my surprise it was working perfectly while the C# code refused working in any way while trying to find a simple OpenFileDialog's controls, then another control on the main form. The only difference between the two worlds is the mysterious MS RCW magic. I'm not sure if it's the way the marshaling is handled with the automatically created COM wrappers (by tlbimp) or something else. And the [ComConversionLoss] attribute that appears for the created interface doesn't sound right to me. Anyways I'm now considering manually crafting the COM interface or converting my whole project to native environment.
The difference between managed and unmanaged UI Automation is because the managed use old implementation but Inspect uses COM directly and this is newer version 3.0