Caching UI Automation Properties and Control Patterns

When using Microsoft UI Automation, clients often need to retrieve multiple properties for multiple automation elements. A client could retrieve individual properties one element at a time by using the property retrieval methods such as IUIAutomationElement::CurrentName or CurrentAccessKey. However, this method is slow and inefficient because it requires a cross-process call for each property being retrieved. To improve performance, clients can use the caching (also called bulk fetching) capabilities of UI Automation. Caching enables a client to retrieve all of the desired properties for all of the desired elements with a single method call. The client can then retrieve the individual properties from the cache as needed, and can get a new snapshot of the cache periodically, generally in response to events that signify changes in the user interface (UI).

The benefits of caching are most noticeable with Microsoft Windows Presentation Foundation (WPF) controls and custom controls that have server-side UI Automation providers. There is less benefit when client-side providers, such as the default providers for Microsoft Win32 controls, are accessed.

The application can request caching when it retrieves a UI Automation element by using a method, such as IUIAutomation::ElementFromPointBuildCache, IUIAutomationTreeWalker::GetFirstChildBuildCache, or IUIAutomationElement::FindFirstBuildCache.

Caching also occurs when you specify a cache request while subscribing to events. The UI Automation element passed to your event handler as the source of an event contains the cached properties and patterns that are specified by the cache request. Any changes made to the cache request after you subscribe to the event have no effect.

This topic contains the following sections.

Cache Requests

Caching involves determining which properties to retrieve and which elements to retrieve them from, and then using this information to create a cache request. Whenever the client obtains an IUIAutomationElement interface for UI item, UI Automation caches the information that is specified in the cache request.

To create a cache request, begin by using the IUIAutomation::CreateCacheRequest method to retrieve an IUIAutomationCacheRequest interface pointer. Next, configure the cache request by using the methods of IUIAutomationCacheRequest.

Specifying Property and Control Patterns to Cache

You can specify properties to cache by calling IUIAutomationCacheRequest::AddProperty. You can specify control patterns to cache by calling IUIAutomationCacheRequest::AddPattern. When a pattern is cached, its properties are not automatically cached; you must specify the properties you want to cache by using IUIAutomationCacheRequest::AddProperty.

You can retrieve a control pattern property (for example, the Value property of the Value control pattern), without having to retrieve the entire control pattern into the cache. You must retrieve the control pattern only if you need to use a control pattern method.

Specifying the Scoping and Filtering of a Caching Request

You can specify the elements whose properties and patterns you want to cache by setting the IUIAutomationCacheRequest::TreeScope property before using the request. The scope is relative to the elements that are retrieved by the method to which the cache request is passed. For example, if you set only TreeScope_Children, and then retrieve a UI Automation element, the properties and patterns of children of that element are cached, but the properties and patterns of the element itself are not cached. To ensure that caching is done for the retrieved element itself, you must include TreeScope_Element in the IUIAutomationCacheRequest::TreeScope property. It is not possible to set the scope to TreeScope_Parent or TreeScope_Ancestors. However, a parent element can be cached when a child element is cached; see Retrieving Cached Children and Parents in this topic.

The extent of caching is also affected by the IUIAutomationCacheRequest::TreeFilter property. By default, caching is performed only for elements that appear in the control view of the UI Automation tree. However, you can change this property to apply caching to all elements, or only to elements that appear in the content view.

Strength of Element References

When you retrieve an automation element, by default you have access to all properties and patterns of that element, including those properties and patterns that were not cached. However, you can specify that the reference to the element refers to cached data only, by setting the IUIAutomationCacheRequest::AutomationElementMode property to AutomationElementMode_None. In this case, you do not have access to any uncached properties and patterns of retrieved elements. This means that you cannot access any current properties such as IUIAutomationElement::CurrentIsEnabled or retrieve a pattern by using IUIAutomationElement::GetCurrentPattern. On cached patterns, you cannot call methods that perform actions on the control, such as IUIAutomationInvokePattern::Invoke.

An example of an application that might not need full references to objects is a screen reader, which might prefetch the name and control type properties of elements in a window without needing the automation element objects themselves.

Retrieving Cached Children and Parents

When you retrieve an automation element and request caching for children of that element through the IUIAutomationCacheRequest::TreeScope property of the request, it is possible to get the child elements by calling IUIAutomationElement::GetCachedChildren on the element you retrieved.

If TreeScope_Element was included in the scope of the cache request, the root element of the request can be retrieved by calling IUIAutomationElement::GetCachedParent on any of the child elements.

Note  You cannot cache parents or ancestors of the root element of the request.

Retrieving a New Snapshot of the Cache

The cache is valid only as long as nothing changes in the UI. Your application is responsible for retrieving a new snapshot of the cache, typically, in response to events.

If you subscribe to an event with a cache request, you obtain an IUIAutomationElement new snapshot of the cache as the source of the event whenever your event handler is called. You can also retrieve a new snapshot of cached information for an element by calling IUIAutomationElement::BuildUpdatedCache. You can pass in the original IUIAutomationCacheRequest to get a new snapshot of all information that was previously cached.

Retrieving a new snapshot of the cache does not modify the properties of any existing IUIAutomationElement references.


The following example functions demonstrate some aspects of caching. The target is a list box. In the first function, items are retrieved from the list, and a control pattern and a single property are cached for each item. By default, the list items are returned with a full reference, so that all current properties are still available.

// Given a list element, caches a control pattern and a property for
// all the list items.
IUIAutomationElementArray* FindAndCacheListItems(IUIAutomationElement* pList)
    if (pList == NULL)
        return NULL;
    IUIAutomationCondition* pCondition = NULL;
    IUIAutomationCacheRequest* pCacheRequest = NULL;
    IUIAutomationElementArray* pFound = NULL;

    HRESULT hr = g_pAutomation->CreateTrueCondition(&pCondition);
    if (FAILED(hr))
        goto cleanup;

    hr = g_pAutomation->CreateCacheRequest(&pCacheRequest);
    if (FAILED(hr))
        goto cleanup;

    hr = pCacheRequest->AddPattern(UIA_SelectionItemPatternId);
    if (FAILED(hr))
        goto cleanup;

    hr = pCacheRequest->AddProperty(UIA_NamePropertyId);
    if (FAILED(hr))
        goto cleanup;

    pList->FindAllBuildCache(TreeScope_Children, pCondition, pCacheRequest, &pFound);
    if (pCondition != NULL)

    if (pCacheRequest != NULL)

    return pFound;

The second example function shows how the pattern and property can be retrieved from the cache.

// Demonstrates retrieval of cached properties from a list item
// obtained in FindAndCacheListItems.
HRESULT GetCachedListItem(IUIAutomationElement* pItem)
    if (pItem == NULL)
        return E_INVALIDARG;

    IUIAutomationSelectionItemPattern* pSelectionItemPattern;
    HRESULT hr = pItem->GetCachedPatternAs(UIA_SelectionItemPatternId, 
        IID_IUIAutomationSelectionItemPattern, (void**)&pSelectionItemPattern);
    if (pSelectionItemPattern != NULL)
        // ... To do: Do something with the pattern.


    // Retrieve a cached property.
    BSTR bstrName;
    hr = pItem->get_CachedName(&bstrName);
    if (SUCCEEDED(hr))
        // ... To do: Do something with the property.

        // Clean up when done with name.
        bstrName = NULL;

    BOOL isControl;

    // The following returns E_INVALIDARG because the property was not cached.
    // hr = pItem->get_CachedIsControlElement(&isControl);

    // The following is valid because we have a full reference to the object, therefore
    // we can get current properties. If the cache request had been made with 
    // AutomationElementMode_None, no current properties would be available from
    // this IUIAutomationElement.
    hr = pItem->get_CurrentIsControlElement(&isControl);
    return hr;

Related Topics

Community Additions