Share via


Utilizar la propiedad AutomationID

NotaNota

Esta documentación está dirigida a desarrolladores de .NET Framework que desean usar las clases administradas de UI Automation definidas en el espacio de nombres System.Windows.Automation.Para obtener información actualizada sobre UI Automation, vea Windows Automation API: UI Automation.

Este tema contiene escenarios y ejemplos de código que muestran cómo y cuando se puede usar AutomationIdProperty para buscar un elemento dentro del árbol de UI Automation.

AutomationIdProperty identifica de manera inequívoca un elemento de Automatización de la interfaz de usuario de los elementos de su mismo nivel. Para obtener más información acerca de los identificadores de propiedad relacionados con la identificación de controles, vea Información general acerca de las propiedades de UI Automation.

NotaNota

AutomationIdProperty no garantiza una identidad única en todo el árbol; para ser útil, normalmente necesita información de contenedor y ámbito.Por ejemplo, una aplicación puede contener un control de menú con varios elementos de menú de nivel superior que, a su vez, contiene varios elementos de menú secundarios.Estos elementos de menú secundarios pueden identificarse mediante un esquema genérico como "Elemento1", "Elemento2", etc., lo que permite que existan identificadores de elementos de niveles secundarios que estén duplicados en los elementos del nivel superior.

Escenarios

Se han identificado tres escenarios de aplicación cliente de Automatización de la interfaz de usuario principales que requieren el uso de AutomationIdProperty para obtener resultados precisos y coherentes al buscar elementos.

NotaNota

AutomationIdProperty lo admiten todos los elementos de Automatización de la interfaz de usuario en la vista de control salvo las ventanas de aplicación de nivel superior, los elementos de Automatización de la interfaz de usuario derivados de los controles de Windows Presentation Foundation (WPF) que no tienen un identificador ni un x:Uid y los elementos de Automatización de la interfaz de usuario derivados de los controles de Win32 que no tienen un identificador de control.

Utilizar un AutomationID único y reconocible para buscar un elemento concreto en el árbol de automatización de la interfaz de usuario

  • Utilice una herramienta como UI Spy para informar a AutomationIdProperty sobre un elemento de UI de interés. Este valor se puede copiar y pegar después en una aplicación cliente como un script de prueba para las pruebas automatizadas posteriores. Este método reduce y simplifica el código que es necesario para identificar y buscar un elemento en tiempo de ejecución.
Nota de precauciónPrecaución

En general, se recomienda intentar obtener solamente elementos secundarios directos de RootElement.Una búsqueda de descendientes puede recorrer en iteración centenares o incluso miles de elementos, lo que produciría posiblemente un desbordamiento de pila.Si intenta obtener un elemento concreto en un nivel inferior, debe iniciar la búsqueda desde la ventana de la aplicación o desde un contenedor de un nivel inferior.

'''--------------------------------------------------------------------
''' <summary>
''' Finds all elements in the UI Automation tree that have a specified
''' AutomationID.
''' </summary>
''' <param name="targetApp">
''' The root element from which to start searching.
''' </param>
''' <param name="automationID">
''' The AutomationID value of interest.
''' </param>
''' <returns>
''' The collection of automation elements that have the specified 
''' AutomationID value.
''' </returns>
'''--------------------------------------------------------------------
Private Function FindElementFromAutomationID( _
ByVal targetApp As AutomationElement, _
ByVal automationID As String) As AutomationElementCollection
    Return targetApp.FindAll( _
    TreeScope.Descendants, _
    New PropertyCondition( _
    AutomationElement.AutomationIdProperty, automationID))
End Function 'FindElementFromAutomationID
///--------------------------------------------------------------------
/// <summary>
/// Finds all elements in the UI Automation tree that have a specified
/// AutomationID.
/// </summary>
/// <param name="targetApp">
/// The root element from which to start searching.
/// </param>
/// <param name="automationID">
/// The AutomationID value of interest.
/// </param>
/// <returns>
/// The collection of UI Automation elements that have the specified 
/// AutomationID value.
/// </returns>
///--------------------------------------------------------------------
private AutomationElementCollection FindElementFromAutomationID(AutomationElement targetApp, 
    string automationID)
{
    return targetApp.FindAll(
        TreeScope.Descendants,
        new PropertyCondition(AutomationElement.AutomationIdProperty, automationID));
}

Utilice una ruta de acceso persistente para volver a un AutomationElement previamente identificado

  • Las aplicaciones cliente, desde simples scripts de prueba hasta complejas utilidades de registro y reproducción, pueden necesitar tener acceso a elementos de los que no se han creado instancias, como un elemento de menú o un cuadro de diálogo para abrir archivos y, por consiguiente, no existen en el árbol de automatización de la interfaz de usuario. Se pueden crear instancias de estos elementos sólo mediante la reproducción de una secuencia concreta de acciones de user interface (UI) a través del uso de propiedades de UI Automation como AutomationID, patrones de control y agentes de escucha de eventos. Vea Test Script Generator Sample para obtener un ejemplo donde se utiliza la Microsoft UI Automation para generar scripts de prueba basados en la interacción del usuario con la user interface (UI).
        '''--------------------------------------------------------------------
        ''' <summary>
        ''' Creates a UI Automation thread.
        ''' </summary>
        ''' <param name="sender">Object that raised the event.</param>
        ''' <param name="e">Event arguments.</param>
        ''' <remarks>
        ''' UI Automation must be called on a separate thread if the client 
        ''' application itself could become a target for event handling.
        ''' For example, focus tracking is a desktop event that could involve
        ''' the client application.
        ''' </remarks>
        '''--------------------------------------------------------------------
        Private Sub CreateUIAThread(ByVal sender As Object, ByVal e As EventArgs)

            ' Start another thread to do the UI Automation work.
            Dim threadDelegate As New ThreadStart(AddressOf CreateUIAWorker)
            Dim workerThread As New Thread(threadDelegate)
            workerThread.Start()

        End Sub 'CreateUIAThread


        '''--------------------------------------------------------------------
        ''' <summary>
        ''' Delegated method for ThreadStart. Creates a UI Automation worker 
        ''' class that does all UI Automation related work.
        ''' </summary>
        '''--------------------------------------------------------------------
        Public Sub CreateUIAWorker()

            uiautoWorker = New UIAWorker(targetApp)

        End Sub 'CreateUIAWorker

        Private uiautoWorker As UIAWorker



...


'''--------------------------------------------------------------------
''' <summary>
''' Function to playback through a series of recorded events calling
''' a WriteToScript function for each event of interest.
''' </summary>
''' <remarks>
''' A major drawback to using AutomationID for recording user 
''' interactions in a volatile UI is the probability of catastrophic 
''' change in the UI. For example, the 'Processes' dialog where items 
''' in the listbox container can change with no input from the user.
''' This mandates thtat a record and playback application must be 
''' reliant on the tester owning the UI being tested. In other words, 
''' there has to be a contract between the provider and client that 
''' excludes uncontrolled, external applications. The added benefit 
''' is the guarantee that each control in the UI should have an
''' AutomationID assigned to it.
''' 
''' This function relies on a UI Automation worker class to create
''' the System.Collections.Generic.Queue object that stores the 
''' information for the recorded user interactions. This
''' allows post-processing of the recorded items prior to actually
''' writing them to a script. If this is not necessary the interaction 
''' could be written to the script immediately.
''' </remarks>
'''--------------------------------------------------------------------
Private Sub Playback(ByVal targetApp As AutomationElement)

    Dim element As AutomationElement
    Dim storedItem As ElementStore
    For Each storedItem In uiautoWorker.elementQueue
        Dim propertyCondition As New PropertyCondition( _
        AutomationElement.AutomationIdProperty, storedItem.AutomationID)
        ' Confirm the existence of a control.
        ' Depending on the controls and complexity of interaction
        ' this step may not be necessary or may require additional 
        ' functionality. For example, to confirm the existence of a 
        ' child menu item that had been invoked the parent menu item 
        ' would have to be expanded. 
        element = targetApp.FindFirst( _
        TreeScope.Descendants, propertyCondition)
        If element Is Nothing Then
            ' Control not available, unable to continue.
            ' TODO: Handle error condition.
            Return
        End If
        WriteToScript(storedItem.AutomationID, storedItem.EventID)
    Next storedItem

End Sub 'Playback


'''--------------------------------------------------------------------
''' <summary>
''' Generates script code and outputs the code to a text control in 
''' the client.
''' </summary>
''' <param name="automationID">
''' The AutomationID of the current control.
''' </param>
''' <param name="eventID">
''' The event recorded on that control.
''' </param>
'''--------------------------------------------------------------------
Private Sub WriteToScript( _
ByVal automationID As String, ByVal eventID As String)

    ' Script code would be generated and written to an output file
    ' as plain text at this point, but for the
    ' purposes of this example we just write to the console.
    Console.WriteLine(automationID + " - " + eventID)

End Sub 'WriteToScript
        ///--------------------------------------------------------------------
        /// <summary>
        /// Creates a UI Automation thread.
        /// </summary>
        /// <param name="sender">Object that raised the event.</param>
        /// <param name="e">Event arguments.</param>
        /// <remarks>
        /// UI Automation must be called on a separate thread if the client 
        /// application itself could become a target for event handling.
        /// For example, focus tracking is a desktop event that could involve
        /// the client application.
        /// </remarks>
        ///--------------------------------------------------------------------
        private void CreateUIAThread(object sender, EventArgs e)
        {
            // Start another thread to do the UI Automation work.
            ThreadStart threadDelegate = new ThreadStart(CreateUIAWorker);
            Thread workerThread = new Thread(threadDelegate);
            workerThread.Start();
        }

        ///--------------------------------------------------------------------
        /// <summary>
        /// Delegated method for ThreadStart. Creates a UI Automation worker 
        /// class that does all UI Automation related work.
        /// </summary>
        ///--------------------------------------------------------------------
        public void CreateUIAWorker()
        {
           uiautoWorker = new FindByAutomationID(targetApp);
        }
        private FindByAutomationID uiautoWorker;



...


///--------------------------------------------------------------------
/// <summary>
/// Function to playback through a series of recorded events calling
/// a WriteToScript function for each event of interest.
/// </summary>
/// <remarks>
/// A major drawback to using AutomationID for recording user 
/// interactions in a volatile UI is the probability of catastrophic 
/// change in the UI. For example, the //Processes// dialog where items 
/// in the listbox container can change with no input from the user.
/// This mandates thtat a record and playback application must be 
/// reliant on the tester owning the UI being tested. In other words, 
/// there has to be a contract between the provider and client that 
/// excludes uncontrolled, external applications. The added benefit 
/// is the guarantee that each control in the UI should have an
/// AutomationID assigned to it.
/// 
/// This function relies on a UI Automation worker class to create
/// the System.Collections.Generic.Queue object that stores the 
/// information for the recorded user interactions. This
/// allows post-processing of the recorded items prior to actually
/// writing them to a script. If this is not necessary the interaction 
/// could be written to the script immediately.
/// </remarks>
///--------------------------------------------------------------------
private void Playback(AutomationElement targetApp)
{
    AutomationElement element; 
    foreach(ElementStore storedItem in uiautoWorker.elementQueue)
    {
        PropertyCondition propertyCondition = 
            new PropertyCondition(
            AutomationElement.AutomationIdProperty, storedItem.AutomationID);
        // Confirm the existence of a control.
        // Depending on the controls and complexity of interaction
        // this step may not be necessary or may require additional 
        // functionality. For example, to confirm the existence of a 
        // child menu item that had been invoked the parent menu item 
        // would have to be expanded. 
        element = targetApp.FindFirst(TreeScope.Descendants, propertyCondition);
        if(element == null)
        {
            // Control not available, unable to continue.
            // TODO: Handle error condition.
            return;
        }
        WriteToScript(storedItem.AutomationID, storedItem.EventID);
    }
}

///--------------------------------------------------------------------
/// <summary>
/// Generates script code and outputs the code to a text control in 
/// the client.
/// </summary>
/// <param name="automationID">
/// The AutomationID of the current control.
/// </param>
/// <param name="eventID">
/// The event recorded on that control.
/// </param>
///--------------------------------------------------------------------
private void WriteToScript(string automationID, string eventID)
{
    // Script code would be generated and written to an output file
    // as plain text at this point, but for the
    // purposes of this example we just write to the console.
    Console.WriteLine(automationID + " - " + eventID);
}

Utilizar una ruta de acceso relativa para volver a un AutomationElement previamente identificado

  • En ciertas circunstancias, dado que AutomationID sólo se garantiza que es único entre elementos del mismo nivel, puede suceder que varios elementos del árbol de automatización de la interfaz de usuario tengan valores de propiedad AutomationID idénticos. En estas situaciones, los elementos se pueden identificar de manera única por su elemento primario y, si es necesario, su elemento primario principal. Por ejemplo, un programador puede proporcionar una barra de menú que incluya varios elementos de menú que a su vez tengan varios elementos de menú secundarios que se identifican mediante valores de AutomationID secuenciales como "Elemento1", "Elemento2", etc. En ese caso, cada elemento de menú podría identificarse de manera única mediante su AutomationID y el AutomationID de su elemento primario y, si es necesario, el de su elemento primario principal.

Vea también

Tareas

Buscar un elemento de UI Automation basándose en una condición de propiedad

Referencia

AutomationIdProperty

Conceptos

Información general sobre el árbol de la UI Automation