Saltar a contenido

Automatización de una aplicación de Windows

En algunos casos, podemos automatizar aplicaciones de Windows a través de las propiedades de los elementos, como alternativa a la visión por computadora.

Esto puede ser una alternativa útil cuando no queremos preocuparnos por problemas de resolución. Simplemente podemos interactuar con la estructura de la aplicación a través de los atributos de los elementos y las ventanas.

Este tutorial te guiará a través del proceso de crear una automatización simple que interactúa con los elementos de una aplicación de Windows.

Crear un nuevo proyecto

El primer paso es crear un proyecto para una automatización de desktop, puedes seguir los mismos pasos definidos en la sección anterior.

Consulta cómo crear un proyecto de Bot desktop.

Aplicación objetivo y herramientas de inspección

Para este ejemplo simple, vamos a utilizar el estándar de Windows wordpad.

Para ayudarnos a inspeccionar esta aplicación, vamos a utilizar la herramienta de inspección Accessibility Insights for Windows.

Consulta más detalles sobre el uso de herramientas de inspección.

Interactuar con la aplicación

Conexión

Con el proyecto abierto, vamos a insertar el primer paso en el archivo bot.py, que es establecer la conexión con la aplicación objetivo.

from botcity.core import DesktopBot, Backend
...
def main():
    bot = DesktopBot()

    # Application path
    app_path = "wordpad.exe"

    # Launching the app
    bot.execute(app_path)

    # Connecting to the application using 'path' selector
    bot.connect_to_app(backend=Backend.UIA, path=app_path)
...

Con la aplicación abierta, podemos usar la herramienta de inspección para ver información sobre los elementos.

Herramienta de inspección

Encontrar ventanas y elementos

Con la aplicación conectada, ahora podemos usar la referencia de la ventana principal y recopilar el elemento que se refiere al editor de texto, por ejemplo.

from botcity.core import DesktopBot, Backend
...
def main():
    bot = DesktopBot()

    # Ruta de aplicación
    app_path = "wordpad.exe"

    # Lanzamiento de la aplicación
    bot.execute(app_path)

    # Conectarse a la aplicación utilizando el selector de 'path'
bot.connect_to_app(backend=Backend.UIA, path=app_path)

    # Obtener el contexto de la ventana principal del Wordpad usando el selector 'title_re', 'class_name' y 'control_type'
    main_window = bot.find_app_window(title_re='Document - WordPad', class_name="WordPadClass",
                                            control_type="Window")

    # Obtener el área de texto de edición utilizando el selector 'class_name' y 'control_type'
    # Pudimos ver esta propiedad a través de la herramienta espionaje
    edit = bot.find_app_element(from_parent_window=main_window, control_type="Document",
                                    class_name='RICHEDIT50W')
...

Observa que utilizamos la propiedad class_name y control_type que obtuvimos de la herramienta de inspección. Básicamente, puedes utilizar cualquier información que aparezca para filtrar un determinado elemento.

Propiedades del elemento

Tip

Otra forma de inspeccionar los elementos de control de la aplicación es utilizar el método print_control_identifiers. Después de abrir el cuadro de diálogo y asignarlo a una variable, el método print_control_identifiers debería imprimir todos los controles disponibles. Consulta más detalles sobre esto aquí.

Realizar acciones

Con el elemento encontrado, podemos realizar las operaciones. Como este elemento es de tipo Document, podemos insertar un contenido de texto.

from botcity.core import DesktopBot, Backend
...
def main():
    bot = DesktopBot()

    # Ruta de aplicación
    app_path = "wordpad.exe"

    # Lanzamiento de la aplicación
    bot.execute(app_path)

    # Conectarse a la aplicación utilizando el selector de 'path'
    bot.connect_to_app(backend=Backend.UIA, path=app_path)

    # Obtener el contexto de la ventana principal del Wordpad usando el selector 'title_re', 'class_name' y 'control_type'
    main_window = bot.find_app_window(title_re='Document - WordPad', class_name="WordPadClass",
                                             control_type="Window")

    # Obtener el área de texto de edición utilizando el selector 'class_name' y 'control_type'
    # Pudimos ver esta propiedad a través de la herramienta espionaje
    edit = bot.find_app_element(from_parent_window=main_window, control_type="Document",
                                    class_name='RICHEDIT50W')

    # Escribiendo contenido de texto
    edit.type_keys("Hello! Welcome to BotCity!", with_spaces=True)
...

Info

Consulta más detalles sobre los métodos disponibles para cada tipo diferente de elemento en este enlace.

Ejecutar el Bot

Solo el código anterior sería suficiente para iniciar Wordpad e insertar un contenido de texto.

Hemos establecido una conexión con la aplicación y estamos realizando operaciones en el contexto de un elemento específico.

Al ejecutar el código, el resultado final se verá así:

Resultado

Acceder a otros elementos

Con el mismo enfoque que se mencionó anteriormente, utilizando las propiedades control_type y title_re, vamos a acceder a otros elementos de Wordpad.

Acceder a Print Preview

Comenzaremos accediendo a la opción Print Preview.

# Acceso a la opción 'Print Preview' de WordPad a través de los selectores `Control_type` y 'title_re`
print_preview = bot.find_app_element(from_parent_window=main_window, control_type='Button',
                                         title_re='Print preview')
print_preview.click()
...

Entonces seleccionaremos la opción Page Setup

# Acceso a la opción 'Page Setup' a través de selectores `Control_type` y` title_re`
page_setup = bot.find_app_element(from_parent_window=main_window, control_type='Button',
                                     title_re='Page setup')
page_setup.click()
...

Usar select para elegir una opción en la caja de selección

Vamos a interactuar con el elemento Size, como se muestra a continuación:

Configuración de papel

Antes de cualquier manipulación, ingresaremos al contexto de la ventana Page Setup, es una ventana dentro del alcance de main_window, pero sus atributos no están expuestos directamente a ella, de esta manera, para encontrar los elementos y atributos del Elementos de la ventana Page Setup, será necesario primero, devuélvalo.

# Obtener el contexto de la ventana 'Configuración de página' a través del selector 'Title_re'
page_setup_window = bot.find_app_element(from_parent_window=main_window, title_re='Page Setup')
...

Ahora sim, para seleccionar el tamaño del papel, vamos a mapear el control_type y title del elemento size, para poder seleccionarlos mediante el método select.

Esta vez vamos a utilizar otro enfoque para obtener la propiedad del elemento, el método print_control_identifiers, como se muestra a continuación:

# Imprimiendo los identificadores de control de la ventana "Page Setup".
page_setup_window.print_control_identifiers()
...

Al ejecutar el código anterior, los controles de la ventana Page Setup se generarán en tu terminal.

Identificadores de control

Donde podemos ver el title y control_type del elemento, que se utilizarán a continuación como parámetros del método find_app_element.

# Encontrar elemento para seleccionar el tamaño de la página
size = bot.find_app_element(from_parent_window=main_window, control_type="ComboBox",
                                title="Size:")
# Selección de tipo de página
size.select("A5")
...

Usar invoke para elegir un botón de opción

Aquí, vamos a usar invoke para seleccionar el botón de opción Landscape.

Botón de opción

Aún utilizando los identificadores de control.

Identificadores de control

Vamos a obtener el title y control_type del elemento Landscape para encontrarlo a continuación:

# Encontrar elemento para seleccionar el botón de radio "Landscape"
orientation = bot.find_app_element(from_parent_window=main_window, control_type="RadioButton",
                                        title="Landscape")
# El método `Click` es un alias de `Invoke`
orientation.invoke()

# Encontrar elemento para hacer clic en el botón "OK"
btn_ok = bot.find_app_element(from_parent_window=main_window, title="OK")
# Haga clic en el botón
btn_ok.click()
...

Info

En este caso, no fue posible utilizar los métodos click y click_input para seleccionar el botón de opción, ya que solo tienen control sobre elementos con la propiedad control_type="Button".

Info

invoke utiliza el llamado InvokePattern que representa una acción predeterminada para el control. Al utilizar Application(backend="uia"), el método click es un alias de invoke, donde la acción InvokePattern lleva la ventana al primer plano, permitiendo la interacción con el elemento.

Después de las acciones anteriores, la configuración de la página se verá así:

Configuración de página

Usar type_keys y click para guardar el Wordpad en el explorador de archivos.

Finalmente, accederemos a la opción Save de la opción Menú.

# Acceso al icono 'Guardar' del menú superior a través de los selectores 'Control_Type' y 'Title'
save = bot.find_app_element(from_parent_window=main_window, control_type="Button",
                                title="Save")
save.click()
...

Esta acción abrirá la ventana del explorador de archivos, como se muestra a continuación:

Guardar como

Así, vamos a definir un nombre para el archivo, en este caso será tutorial.txt, y haremos clic en el botón guardar, a través del método click.

# Encontrar elemento para escribir el nombre del archivo
file_name = bot.find_app_element(from_parent_window=main_window, class_name="Edit",
                                    title="File name:")
# Escribiendo el nombre del archivo
file_name.type_keys("tutorial.txt")

# Encontrar elemento para hacer clic en el botón Guardar
btn_save = bot.find_app_element(from_parent_window=main_window, class_name="Button",
                                    title="Save")
# Hacer clic en el botón Guardar
btn_save.click()
...

Código completo

from botcity.core import DesktopBot, Backend
...
def main():
    bot = DesktopBot()

    # Ruta de aplicación
    app_path = "wordpad.exe"

    # Lanzamiento de la aplicación
    bot.execute(app_path)

    # Conectarse a la aplicación utilizando el selector de 'path'
    bot.connect_to_app(backend=Backend.UIA, path=app_path)

    # Obtener el contexto de la ventana principal del Wordpad usando el selector 'title_re', 'class_name' y 'control_type'
    main_window = bot.find_app_window(title_re='Document - WordPad', class_name="WordPadClass",
                                             control_type="Window")

    # Obtener el área de texto de edición utilizando el selector 'class_name' y 'control_type'
    # Pudimos ver esta propiedad a través de la herramienta espionaje
    edit = bot.find_app_element(from_parent_window=main_window, control_type="Document",
                                    class_name='RICHEDIT50W')

    # Escribiendo contenido de texto
    edit.type_keys("Hello! Welcome to BotCity!", with_spaces=True)

    # Acceso a la opción 'Print Preview' de WordPad a través de los selectores `Control_type` y 'title_re`
    print_preview = bot.find_app_element(from_parent_window=main_window, control_type='Button',
                                             title_re='Print preview')
    print_preview.click()

    # Acceso a la opción 'Page Setup' a través de selectores `Control_type` y` title_re`
    page_setup = bot.find_app_element(from_parent_window=main_window, control_type='Button',
                                         title_re='Page setup')
    page_setup.click()

    # Obtener el contexto de la ventana 'Configuración de página' a través del selector 'Title_re'
    page_setup_window = bot.find_app_element(from_parent_window=main_window, title_re='Page Setup')

    # Imprimiendo los identificadores de control de la ventana "Page Setup".
    page_setup_window.print_control_identifiers()

    # Encontrar elemento para seleccionar el tamaño de la página
    size = bot.find_app_element(from_parent_window=main_window, control_type="ComboBox",
                                     title="Size:")
    # Selección de tipo de página
    size.select("A5")

    # Encontrar elemento para seleccionar el botón de radio "Landscape"
    orientation = bot.find_app_element(from_parent_window=main_window,control_type="RadioButton",
                                          title="Landscape")
    # El método `Click` es un alias de `Invoke`
    orientation.invoke()

    # Encontrar elemento para hacer clic en el botón "OK"
    btn_ok = bot.find_app_element(from_parent_window=main_window, title="OK")
    # Haga clic en el botón
    btn_ok.click()

    # Acceso al icono 'Guardar' del menú superior a través de los selectores 'Control_Type' y 'Title'
    save = bot.find_app_element(from_parent_window=main_window, control_type="Button",
                                    title="Save")
    save.click()

    # Encontrar elemento para escribir el nombre del archivo
    file_name = bot.find_app_element(from_parent_window=main_window, class_name="Edit",
                                        title="File name:")
    # Escribiendo el nombre del archivo
    file_name.type_keys("tutorial.txt")

    # Encontrar elemento para hacer clic en el botón Guardar
    btn_save = bot.find_app_element(from_parent_window=main_window, class_name="Button",
                                        title="Save")
    # Hacer clic en el botón Guardar
    btn_save.click()
...

Important

Algunas aplicaciones pueden ser más difíciles de inspeccionar y encontrar información sobre los elementos.

Utiliza las herramientas de inspección como referencia para determinar si esta es la mejor alternativa para tu automatización.

Conclusión

En este tutorial has aprendido:

  • Cómo utilizar una herramienta de inspección para examinar una aplicación de Windows.

  • Cómo conectarse a una aplicación y ver sus atributos y propiedades.

  • Cómo interactuar con un elemento que se ha encontrado.