Handling playback failures in Coded UI Test due to stale UI controls
There have been multiple instances of Coded UI Test customers reporting failure in the performing action on a control within a popup window such as a dialog box or a context menu. The typical symptom will be an error thrown something like –
QTAgent32.exe, AL: Playback Error: Microsoft.VisualStudio.TestTools.UITest.Extension.FailedToPerformActionOnBlockedControlException:
Window ” is blocking the control XYZ. Please move the window ” or make the control XYZ visible and retry the action. Additional Details:
ControlType: ‘MenuItem’ —> System.Runtime.InteropServices.COMException: Exception from HRESULT: 0xF004F003
First of all, note that this is not a search failure, but an action failure. If you observe this error even if the target control is well truly visible on the screen, the first troubleshooting action you need to take is to check if the search has actually hit the correct target element. You can make use of the DrawHighlight method in your test code to validate this. Often debugging this leads to the root cause of an earlier instance of the same window not being disposed off properly. This results in a stale accessible object persisting under the desktop and the search hits this stale object. Since this UI object is in reality not visible and obscured behind other UI objects, the playback fails with the blocked control exception error.
If you have access to the application code, I would suggest first to verify and fix this in the application. If this is not possible at given point of time, you could apply certain workarounds in the Coded UI Test to resolve this issue.
1. Make use the VisibleOnly search configuration for the target control (and its ancestors). If the search hierarchy looks something like TopLevelWindow(TLW) -> A -> B, append the configuration to each of all of these controls. The assumption is that the stale control’s accessible object will typically have its visibility property set to false.
2. Approach  may not hold good in all scenarios (at least I have come across certain scenarios where it does not work). The search may be picking up the cached control. In that case, you may also try out the AlwaysSearch configuration along with the VisibleOnly configuration. I always suggest the Coded UI Test users to use AlwaysSearch with caution since it impacts the performance. So use your judgment to apply this only for specific scenarios.
3. The stale control’s window would typically be as an previous sibling peer of the actual target control’s new window. So we have two windows with identical properties and identical hierarchy underneath it. To force the search to hit the second instance of the window, you can make use of the OrderOfInvocation property for the top level window. This property is essentially used to disambiguate multiple top level windows with identical properties (something similar to the “Instance” property you use for the controls within). In a simple case, if you could try setting something like – YourTopLevelWindow.SearchProperties.Add(WinWindow.PropertyNames.OrderOfInvocation, “2”) to ignore the first invisible window.
One final note on the visual verification using DrawHighlight() –
The stale window’s location could simply overlap the actual new window’s location. So the DrawHighlight() might just give a false visual impression that the search has hit the correct control! So you need to do some trial and error with the workarounds. To validate this, one helpful way is to write your own validation Coded UI Test script that gets additional information about the state of the desktop session. For example, if you suspect that there are multiple windows with identical properties, you can do a
WinWindow matchingWindows = new WinWindow();
UITestControlCollection windowsFound = matchingWindows.FindMatchingControls();
// And verify all the windows returned in the collection.
The approaches I’m described above can be extrapolated to all types of controls (not just top level windows). You can use this to debug scenarios for stale controls within a windowless application.