Ir para o conteúdo

Automatizando um Aplicativo Windows

Em alguns casos, podemos automatizar aplicativos do Windows por meio de propriedades de elementos, como uma alternativa à visão computacional.

Esta pode ser uma alternativa útil quando não queremos nos preocupar com problemas de resolução. Podemos simplesmente interagir com a estrutura do aplicativo por meio dos atributos de elementos e janelas.

Este tutorial o guiará pelo processo de criação de uma automação simples que interage com os elementos de um aplicativo do Windows.

Criando um Novo Projeto

O primeiro passo é criar um projeto para automação de desktop, você pode seguir os mesmos passos definidos nas seções anteriores.

Veja como criar um Projeto Bot Desktop.

Aplicativo Alvo e Ferramentas de Espionagem

Para este exemplo simples, usaremos o wordpad padrão do Windows.

Para nos ajudar a inspecionar este aplicativo, vamos usar a ferramenta de espionagem Accessibility Insights for Windows.

Veja mais detalhes sobre o uso de ferramentas de espionagem.

Interagindo com a Aplicação

Conectando

Com o projeto aberto, vamos inserir o primeiro passo no arquivo bot.py, que é estabelecer a conexão com o aplicativo alvo.

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

    # Caminho da aplicação
    app_path = "wordpad.exe"

    # Iniciando o app
    bot.execute(app_path)

    # Conectando-se ao aplicativo usando o seletor 'path'
    bot.connect_to_app(backend=Backend.UIA, path=app_path)
...

Com o aplicativo aberto, podemos usar a ferramenta de espionagem para ver algumas informações sobre os elementos.

Spy tool inspect

Procurando Janelas e Elementos

Com o aplicativo conectado, podemos agora usar a referência da janela principal e coletar o elemento referente ao editor de texto, por exemplo.

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

    # Caminho da aplicação
    app_path = "wordpad.exe"

    # Iniciando o app
    bot.execute(app_path)

    # Conectando-se ao aplicativo usando o seletor 'path'
    bot.connect_to_app(backend=Backend.UIA, path=app_path)

    # Obtendo o contexto da janela principal do wordpad usando o seletor 'title_re', 'class_name' e 'control_type'
    main_window = bot.find_app_window(title_re='Document - WordPad', class_name="WordPadClass",         
                                        control_type="Window")

    # Obtendo a área de edição de texto usando o seletor 'class_name' e 'control_type'
    # Conseguimos visualizar esta propriedade através da ferramenta de espionagem
    edit = bot.find_app_element(from_parent_window=main_window, control_type="Document",
                                    class_name='RICHEDIT50W')
...

Observe que usamos a propriedade class_name e control_type que obtivemos da ferramenta de espionagem. Basicamente, você pode usar qualquer informação que apareça para filtrar um determinado elemento.

Element properties

Dica

Outra maneira de inspecionar os elementos de controle do aplicativo é usar o método print_control_identifiers. Depois de encontrar um elemento e atribuí-o a uma variável, o método print_control_identifiers deve imprimir todos os controles disponíveis referentes a este elemento. Veja mais detalhes sobre isso nesse link.

Performando Ações

Com o elemento encontrado, podemos realizar as operações. Como este elemento é do tipo Document, podemos inserir um conteúdo de texto.

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

    # Caminho da aplicação
    app_path = "wordpad.exe"

    # Iniciando o app
    bot.execute(app_path)

    # Conectando-se ao aplicativo usando o seletor 'path'
    bot.connect_to_app(backend=Backend.UIA, path=app_path)

    # Obtendo o contexto da janela principal do wordpad usando o seletor 'title_re', 'class_name' e 'control_type'
    main_window = bot.find_app_window(title_re='Document - WordPad', class_name="WordPadClass",                 
                                           control_type="Window")

    # Obtendo a área de edição de texto usando o seletor 'class_name' e 'control_type'
    # Conseguimos visualizar esta propriedade através da ferramenta de espionagem
    edit = bot.find_app_element(from_parent_window=main_window, control_type="Document",
                                     class_name='RICHEDIT50W')

    # Inserindo um conteúdo de texto
    edit.type_keys("Hello! Welcome to BotCity!", with_spaces=True)
...

Info

Veja mais detalhes sobre os métodos disponíveis para cada tipo diferente de elemento nesse link.

Executando o Robô

Apenas o código acima seria suficiente para iniciarmos o Wordpad e inserir um conteúdo de texto.

Estabelecemos uma conexão com o aplicativo e estamos realizando operações no contexto de um elemento específico.

Executando o código, o resultado final ficará assim:

Result

Acessando outros Elementos

Com a mesma abordagem acima, usando as propriedades control_type e title_re, vamos acessar outros elementos do Wordpad.

Acessando Print Preview

Iniciaremos acessando a opção Print Preview.

# Acessando a opção 'Print Preview' do Wordpad através dos seletores `control_type` e `title_re`
print_preview = bot.find_app_element(from_parent_window=main_window, control_type='Button',
                                            title_re='Print preview')
print_preview.click()
...

Em seguida selecionaremos a opção Page Setup

# Acessando a opção 'Page Setup' através dos seletores `control_type` e `title_re`
page_setup = bot.find_app_element(from_parent_window=main_window, control_type='Button',
                                        title_re='Page setup')
page_setup.click()
...

Usando select para escolher uma opção na caixa de seleção

Iremos interagir com o elemento Size, conforme vemos abaixo:

Paper-Setup

Antes de qualquer manipulação, iremos entrar no contexto da janela Page Setup, ela é uma janela dentro do escopo da main_window, mas seus atributos não estão exposto diretamente nela, desta forma, para encontrar os elementos e atributos dos elementos da janela Page Setup, será necessário primeiro, retorna-la.

# Obtendo contexto da janela 'Page Setup' através do seletor 'title_re'
page_setup_window = bot.find_app_element(from_parent_window=main_window, title_re='Page Setup')
...

Agora sim, para selecionar o tamanho do papel, vamos mapear o control_type e title do elemento size, para que possamos selecioná-los através do método select.

Desta vez usaremos outra abordagem para obter a propriedade do elemento, o print_control_identifiers, conforme vemos abaixo:

# Imprimindo os identificadores de controle da janela "Page Setup".
page_setup_window.print_control_identifiers()
...
Executando o código acima, os controles da janela Page Setup serão exibidos em seu terminal.

Control-Identifiers

Podemos visualizar o title e control_type do elemento, e utilizá-los como parâmetros do método find_app_element.

# Encontrando o elemento para selecionar o tamanho da página
size = bot.find_app_element(from_parent_window=main_window, control_type="ComboBox",         
                                title="Size:")
# Selecionando tipo da página
size.select("A5")
...

Usando invoke para escolher um botão de opção

Aqui, usaremos invoke para selecionar o botão de opção Paisagem.

Radio-button

Ainda usando os identificadores de controles.

Control-Identifiers

Vamos pegar o title e control_type do elemento para encontrá-lo abaixo:

# Encontrando o elemento para selecionar o botão de opção "Paisagem"
orientation = bot.find_app_element(from_parent_window=main_window, control_type="RadioButton",          
                                        title="Landscape")
# O método `click` é um alias de `invoke`
orientation.invoke()

# Encontrando elemento para clicar no botão "OK"
btn_ok = bot.find_app_element(from_parent_window=main_window, title="OK")
# Clicando no botão
btn_ok.click()
...

Info

Neste caso, não foi possível utilizar os métodos click e click_input para selecionar o Radio Button, porque eles só têm controle sobre os elementos com propriedade control_type="Button".

Info

invoke usa o chamado InvokePattern, que representa uma ação padrão para o controle. Ao usar Application(backend="uia"), o método click é um alias de invoke, onde a ação InvokePattern traz a janela para o primeiro plano, permitindo interação com o elemento.

Após as ações acima, a configuração da página ficou assim:

Page-setup

Usando type_keys e click para salvar o Wordpad no explorador de arquivos

Para finalizar, acessaremos a opção Save do menu.

# Acessando ícone 'Save' do menu superior através dos seletores 'control_type' e 'title'
save = bot.find_app_element(from_parent_window=main_window, control_type="Button",         
                                title="Save")
save.click()
...

Esta ação abrirá a janela do explorador de arquivos, conforme vemos abaixo:

Save-As

Assim, definiremos um nome para o arquivo, neste caso será tutorial.txt, e clicaremos no botão salvar, através do método click.

# Encontrando elemento para digitar o nome do arquivo
file_name = bot.find_app_element(from_parent_window=main_window, class_name="Edit", 
                                    title="File name:")
# Digitando o nome do arquivo
file_name.type_keys("tutorial.txt")

# Encontrando elemento para clicar no botão salvar
btn_save = bot.find_app_element(from_parent_window=main_window, class_name="Button", 
                                    title="Save")
# Clicando no botão salvar
btn_save.click()
...

Código Completo

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

    # Caminho da aplicação
    app_path = "wordpad.exe"

    # Iniciando o app
    bot.execute(app_path)

    # Conectando-se ao aplicativo usando o seletor 'path'
    bot.connect_to_app(backend=Backend.UIA, path=app_path)

    # Obtendo o contexto da janela principal do wordpad usando o seletor 'title_re', 'class_name' e 'control_type'
    main_window = bot.find_app_window(title_re='Document - WordPad', class_name="WordPadClass",
                                         control_type="Window")

    # Obtendo a área de edição de texto usando o seletor 'class_name' e 'control_type'
    # Conseguimos visualizar esta propriedade através da ferramenta de espionagem
    edit = bot.find_app_element(from_parent_window=main_window, control_type="Document",
                                    class_name='RICHEDIT50W')

    # Inserindo um conteúdo de texto
    edit.type_keys("Hello! Welcome to BotCity!", with_spaces=True)

    # Acessando a opção 'Print Preview' do Wordpad através dos seletores `control_type` e   `title_re`
    print_preview = bot.find_app_element(from_parent_window=main_window, control_type='Button',
                                             title_re='Print preview')
    print_preview.click()

    # Acessando a opção 'Page Setup' através dos seletores `control_type` e `title_re`
    page_setup = bot.find_app_element(from_parent_window=main_window,
                                         control_type='Button', title_re='Page setup')
    page_setup.click()

    # Obtendo contexto da janela 'Page Setup' através do seletor 'title_re'
    page_setup_window = bot.find_app_element(from_parent_window=main_window,
                                                 title_re='Page Setup')

    # Imprimindo os identificadores de controle da janela "Page Setup".
    page_setup_window.print_control_identifiers()

    # Encontrando o elemento para selecionar o tamanho da página
    size = bot.find_app_element(from_parent_window=main_window, class_name="ComboBox", 
                                    title="Size:")
    # Selecionando tipo da página
    size.select("A5")

    # Encontrando o elemento para selecionar o botão de opção "Paisagem"
    orientation = bot.find_app_element(from_parent_window=main_window,  control_type="RadioButton", 
                                            title="Landscape")
    # O método `click` é um alias de `invoke`
    orientation.invoke()

    # Encontrando elemento para clicar no botão "OK"
    btn_ok = bot.find_app_element(from_parent_window=main_window, title="OK")
    # Clicando no botão
    btn_ok.click()

    # Acessando ícone 'Save' do menu superior através dos seletores 'control_type' e 'title'
    save = bot.find_app_element(from_parent_window=main_window, control_type="Button",         
                                    title="Save")
    save.click()

    # Encontrando elemento para digitar o nome do arquivo
    name_file = bot.find_app_element(from_parent_window=main_window, class_name="Edit", 
                                        title="File name:")
    # Digitando o nome do arquivo
    name_file.type_keys("tutorial.txt")

    # Encontrando elemento para clicar no botão salvar
    btn_save = bot.find_app_element(from_parent_window=main_window, class_name="Button", 
                                        title="Save")
    # Clicando no botão salvar
    btn_save.click()
...

Importante

Alguns aplicativos podem ser mais difíceis de inspecionar e encontrar informações sobre os elementos.

Use as ferramentas de espionagem como referência para determinar se esta é a melhor alternativa para sua automação.

Conclusão

Neste tutorial você aprendeu:

  • Como usar uma ferramenta de espionagem para inspecionar um aplicativo do Windows.

  • Como se conectar a um aplicativo e visualizar seus atributos e propriedades.

  • Como interagir com um elemento encontrado.