Sunday, November 29, 2009 5:56 PMI'm trying to use UIAutomation on Excel, but for some reason when I use UIAutomation to access certain elements in Excel -- it can't find them (neither with FindFirst,FindAll, or the TreeWalker). What's interesting though is that this only happens when I use this code from within MSTest (using MSTest as our test harness).
If I do this as a standalone EXE (exact same code) then it finds all of the elements as expected.
I thought maybe it was an STA/MTA issue, so I had my MSTest TestMethod spin up an STA thread as the first thing it did, and then run the tests on that thread, but I get the same problem.
An example of something that I can't get to in Excel is the list of existing connections. To manually get to this location:
1) Stat up Excel 2008
2) Click "Data" tab
3) Click "Existing Connections" (make sure your Excel window is open wide enough, otherwise it is hidden)
4) And then a dialog box pops up with a list of connections. This is where the UIAutomation fails in MSTest. I can't access any of the items in the list, in order to click them.
FindFirst/FindAll simply return null when looking for the list item. TreeWalker gets to the Existing Connections dialog. And finds the first couple of children, but then it returns null on one of the calls to GetNextSibling -- implying the end of the tree walk (as it's right off the root). Of course, I can use UISpy and see the full tree. And likewise everything works perfectly if I run my exact same code from my own EXE.
Any thoughts? Are there known issues I'm hitting?
BTW, this is on Win7 (x64), building x86 managed binaries, C# VS2008 SP1, .NET 3.5 SP1.
Thanks for any help. Let me know if more info would be useful.
Wednesday, March 14, 2012 10:14 PMI'm having a very similar problem. Clicking a Save button opens up a new dialog box. I've solved the problem of the form hanging after being invoked, by clicking the Save button Asynchronously. However, it didn't fix the issue of being able to access the controls on the dialog box. Even UI Spy takes it's time to display the tree, though my testing tool takes far more time. And my testing tool eventually does get there, after being hanged on FindFirst or FindAll for several minutes. So far I haven't been able to make it work faster. If anyone has any ideas, please share.
P.S. I also tried to set my dialog box as my root, didn't help either
Thursday, March 15, 2012 2:13 PM
I can't really help directly with this question if you're using the managed UI Automation API that's included in the .NET Framework, as I rarely use that API. But one thing I'd suggest is that you may want to consider trying out the native-code UIA API that's included with Windows. As useful as the managed API is, sometimes it can't access all the data that can be accessed by the native-code API. The latest Inspect and AccEvent tools that are included in the Windows SDK use the native-code API, and so you may want to try pointing Inspect to the UI that you're working with and see what results are reported. Inspect won't be doing all the operations you will, (such as FindFirst/All), but it will be walking through the UI tree.
There's some discussion about moving from the managed API to the native-code API at http://social.msdn.microsoft.com/Forums/en-US/windowsaccessibilityandautomation/thread/5b043035-b1eb-4c6c-944c-5ce8df28b1ee.
If you do decide that the native-code API is the right move for you, I have a number of samples up at http://code.msdn.microsoft.com/site/search?f%5B0%5D.Type=User&f%5B0%5D.Value=Guy%20Barker%20MSFT which demo a lot of the interesting features of the API. There's a C++ client app which gathers hyperlinks from a browser at http://code.msdn.microsoft.com/Windows-7-UI-Automation-9131f729, and its C# equivalent at http://code.msdn.microsoft.com/Windows-7-UI-Automation-0625f55e. It can be interesting to step through these samples in the debugger to get an introduction into the powerful things you can do with the API, (such as leveraging the caching functionality to improve performance.)
Thursday, March 15, 2012 10:29 PMThank you. The managed API works, and UISpy does find the control. The only problem I'm having is managing the threads, as they end up in a deadlock. I would like to hear any suggestions or ideas on how to resolve a deadlock with the threads. As when a dialog box is being called from the main thread, and is created as a separate thread - how do I then do the UI Automation calls on that thread efficiently?
Friday, March 16, 2012 2:07 AM
Sorry, I won't be able to help with that as I'm not familiar with whatever rules there may be around threads and managed UIA.
As an aside for others reading this who use the native UIA API, there are some things to be aware of:
1. If you get involved with UIA events, you should add and remove the event handlers on a background MTA thread. And make sure you remove an event handler from the same thread it was added.
2. If you call UIA to interact with your own UI, make the calls on a background MTA thread.
3. Don't add or remove event handlers beneath another event handler. For example, inside a focus changed event handler, don't add a property changed event handler for the element that's got focus. Rather allow the event handler to return and then add or remove whatever event handler you want to.
My first attempt at the sample at http://code.msdn.microsoft.com/Windows-7-UI-Automation-9131f729 didn't follow rule #1 properly, and I found that some UIA calls experienced severe delays sometimes. Once I updated the sample to make use of the MTA threads as I need to, then all the delays went away.