A automação robótica de processos (RPA), assim como os trabalhadores humanos, automatiza tarefas por meio de sistemas de software ou hardware que são executados em uma variedade de aplicações. Softwares ou bots podem aprender fluxos de trabalho com várias etapas e aplicativos, como obter formulários recebidos, enviar mensagens de confirmação, verificar a integridade do formulário, arquivar formulários em pastas e atualizar planilhas com nome do formulário e data de envio. O software RPA foi projetado para aliviar os funcionários do fardo de concluir tarefas simples e repetitivas.
Certifique-se de que o cliente correspondente tenha sido instalado no computador local e que tanto rpa-client
quanto rpa-server
tenham sido iniciados.
O sistema atual suporta os seguintes clientes:
ID do aplicativo | Nome |
---|---|
conversamos | |
nóscom | WeChat Empresarial |
QQ da Tencent | |
tempo | TIM |
conversa fiada | DingTalk |
cotovia | Feishu |
Como as tarefas devem ser executadas por um usuário específico, você precisa garantir que o usuário exista antes de executar a tarefa.
http://<host>:<port>/users
POST
JSON
Body
Propriedade | Tipo | Obrigatório | Descrição |
---|---|---|---|
Usuários | Usuário[] | Obrigatório | Matriz de objetos de usuário. |
└id | Corda | Opcional | ID do usuário. Quando vazio, o servidor gerará automaticamente um ID. |
└appId | Corda | Obrigatório | AppID associado. |
└conta | Corda | Obrigatório | Conta de usuário, usada para combinar clientes. |
└ Apelido | Corda | Opcional | Apelido do usuário, usado para exibição. |
└ nome real | Corda | Opcional | O nome real do usuário é usado para exibição. |
└empresa | Corda | Opcional | O nome da empresa à qual o usuário pertence é utilizado para exibição. |
Observe que
企业微信
não pode obter diretamenteaccount
da pessoa atualmente conectada. Atualmente, o cliente é correspondido por meio da combinação de${realname}_${company}
.
Exemplo de interface:
curl -X POST --location " http://localhost:8080/users "
-H " Content-Type: application/json "
-d " {
" users " : [
{
" id " : " uid " ,
" appId " : " wechat " ,
" account " : " account " ,
" nickname " : " nickname "
}
]
} "
insert into user (id, app_id, account, nickname, realname, company, status, created_time, updated_time)
values ( ' uid ' , ' wechat ' , ' account ' , ' nickname ' , ' realname ' , ' company ' , 1 , now(), null );
http://<host>:<port>/tasks
POST
JSON
Body
Propriedade | Tipo | Obrigatório | Descrição |
---|---|---|---|
tarefas | Tarefa[] | Obrigatório | Matriz de objetos de tarefa. |
└id | Corda | Opcional | ID da tarefa. Quando vazio, o servidor gerará automaticamente um ID. |
└ ID do usuário | Corda | Obrigatório | ID de usuário associado. |
└ tipo | Corda | Obrigatório | Tipo de tarefa, consulte a tabela do dicionário de tipo de tarefa. |
└ prioridade | Inteiro | Opcional | Prioridade da tarefa, quanto menor o valor, maior a prioridade. Quando vazio, a prioridade configurada padrão é usada. |
└dados | Corda | Opcional | Dados da tarefa, no formato de string JSON . |
└ horário | DataHora | Opcional | Tempo de execução da tarefa, por exemplo: 2022-01-01 10:00:00 . Se estiver vazio, será executado imediatamente. |
Exemplo:
curl -X PATCH --location " http://localhost:8080/tasks "
-H " Content-Type: application/json "
-d " {
" tasks " : [
{
" id " : " tid " ,
" userId " : " uid " ,
" type " : " login " ,
" priority " : " 0 " ,
" data " : "" ,
" scheduleTime " : " 2022-01-01 10:00:00 " ,
}
]
} "
insert into task (id, user_id, app_id, type, priority, data, status, created_time, updated_time, schedule_time)
values ( ' tid ' , ' uid ' , ' wechat ' , ' login ' , 0 , null , 0 , now(), null , ' 2022-01-01 10:00:00 ' );
O servidor fornece uma página de teste de tempo de execução que os desenvolvedores podem usar para testar tarefas simples localmente. Abra o navegador e visite http://<host>:<port>/index.html
e selecione o cliente a ser testado.
Nenhum parâmetro é necessário para fazer login no cliente
Nenhum parâmetro é necessário para sair do cliente
Formato do parâmetro:
Propriedade | Tipo | Obrigatório | Descrição |
---|---|---|---|
alvo | Corda | Obrigatório | Enviar objeto. |
mensagens | Mensagem[] | Obrigatório | Matriz de objetos de mensagem. |
└ tipo | Corda | Obrigatório | Tipo de mensagem. |
└ conteúdo | Corda | Obrigatório | Conteúdo da mensagem, conteúdo de texto ou endereço de arquivo. |
Tipo de mensagem:
Código | Nome | Descrição |
---|---|---|
texto | TEXTO | texto |
imagem | IMAGEM | foto |
vídeo | VÍDEO | vídeo |
arquivo | ARQUIVO | documento |
Exemplo de parâmetro:
{
"target" : " friend " ,
"messages" : [
{
"type" : " text " ,
"content" : " message "
},
{
"type" : " image " ,
"content" : " https://rpa.leego.io/image.png "
},
{
"type" : " video " ,
"content" : " https://rpa.leego.io/video.mp4 "
},
{
"type" : " file " ,
"content" : " https://rpa.leego.io/file.zip "
}
]
}
Formato do parâmetro:
Propriedade | Tipo | Obrigatório | Descrição |
---|---|---|---|
alvo | Corda | Obrigatório | Nome do grupo. |
mensagens | Mensagem[] | Obrigatório | Matriz de objetos de mensagem. |
└ tipo | Corda | Obrigatório | Tipo de mensagem. |
└ conteúdo | Corda | Obrigatório | Conteúdo da mensagem, conteúdo de texto ou endereço de arquivo. |
Tipo de mensagem:
Código | Nome | Descrição |
---|---|---|
texto | TEXTO | texto |
imagem | IMAGEM | foto |
vídeo | VÍDEO | vídeo |
arquivo | ARQUIVO | documento |
menção | MENÇÃO | lembrar |
Exemplo de parâmetro:
{
"target" : " group " ,
"messages" : [
{
"type" : " text " ,
"content" : " message "
},
{
"type" : " image " ,
"content" : " https://rpa.leego.io/image.png "
},
{
"type" : " video " ,
"content" : " https://rpa.leego.io/video.mp4 "
},
{
"type" : " file " ,
"content" : " https://rpa.leego.io/file.zip "
},
{
"type" : " mention " ,
"content" : " member "
}
]
}
Nenhum parâmetro é necessário para fazer login no cliente
Nenhum parâmetro é necessário para sair do cliente
Formato do parâmetro:
Propriedade | Tipo | Obrigatório | Descrição |
---|---|---|---|
alvo | Corda | Obrigatório | Enviar objeto. |
mensagens | Mensagem[] | Obrigatório | Matriz de objetos de mensagem. |
└ tipo | Corda | Obrigatório | Tipo de mensagem. |
└ conteúdo | Corda | Obrigatório | Conteúdo da mensagem, conteúdo de texto ou endereço de arquivo. |
Tipo de mensagem:
Código | Nome | Descrição |
---|---|---|
texto | TEXTO | texto |
imagem | IMAGEM | foto |
vídeo | VÍDEO | vídeo |
arquivo | ARQUIVO | documento |
Exemplo de parâmetro:
{
"target" : " friend " ,
"messages" : [
{
"type" : " text " ,
"content" : " message "
},
{
"type" : " image " ,
"content" : " https://rpa.leego.io/image.png "
},
{
"type" : " video " ,
"content" : " https://rpa.leego.io/video.mp4 "
},
{
"type" : " file " ,
"content" : " https://rpa.leego.io/file.zip "
}
]
}
Formato do parâmetro:
Propriedade | Tipo | Obrigatório | Descrição |
---|---|---|---|
alvo | Corda | Obrigatório | Nome do grupo. |
mensagens | Mensagem[] | Obrigatório | Matriz de objetos de mensagem. |
└ tipo | Corda | Obrigatório | Tipo de mensagem. |
└ conteúdo | Corda | Obrigatório | Conteúdo da mensagem, conteúdo de texto ou endereço de arquivo. |
Tipo de mensagem:
Código | Nome | Descrição |
---|---|---|
texto | TEXTO | texto |
imagem | IMAGEM | foto |
vídeo | VÍDEO | vídeo |
arquivo | ARQUIVO | documento |
menção | MENÇÃO | lembrar |
Exemplo de parâmetro:
{
"target" : " group " ,
"messages" : [
{
"type" : " text " ,
"content" : " message "
},
{
"type" : " image " ,
"content" : " https://rpa.leego.io/image.png "
},
{
"type" : " video " ,
"content" : " https://rpa.leego.io/video.mp4 "
},
{
"type" : " file " ,
"content" : " https://rpa.leego.io/file.zip "
},
{
"type" : " mention " ,
"content" : " member "
}
]
}
Formato do parâmetro:
Propriedade | Tipo | Obrigatório | Descrição |
---|---|---|---|
alvo | Corda | Obrigatório | Nome do grupo. |
contatos | Contato[] | Obrigatório | Matriz de objetos de contato. |
└ alvo | Corda | Obrigatório | Número de telemóvel ou endereço de e-mail do utilizador. |
└ razão | Corda | Opcional | Adicione notas de contato. |
Exemplo de parâmetro:
{
"contacts" : [
{ "target" : " phone " },
{ "target" : " email " , "reason" : " reason " }
]
}
Muito avançado para exibição.
Para evitar que o cliente seja iniciado várias vezes, os desenvolvedores geralmente criam objetos mutex. Um bloqueio mutex é um mecanismo usado na programação multithread para proteger recursos compartilhados de serem acessados por vários threads ou processos ao mesmo tempo.
HANDLE CreateMutexA (
[in, optional] LPSECURITY_ATTRIBUTES lpMutexAttributes,
[in] BOOL bInitialOwner,
[in, optional] LPCSTR lpName
);
[in, optional] lpMutexAttributes
Ponteiro para uma estrutura SECURITY_ATTRIBUTES. Se este parâmetro for NULL
, o identificador não poderá ser herdado por processos filhos.
O membro lpSecurityDescriptor
da estrutura especifica o descritor de segurança para o novo mutex. Se lpMutexAttributes
for NULL
, o mutex obterá um descritor de segurança padrão. ACL
no descritor de segurança padrão do mutex vem do token primário ou de representação do criador.
[in] bInitialOwner
Se esse valor for TRUE
e o chamador criar o mutex, o thread de chamada assumirá a propriedade inicial do objeto mutex. Caso contrário, o thread de chamada não assumirá a propriedade do bloqueio mutex. Para determinar se o chamador criou o mutex, consulte a seção Valores de retorno.
[in, optional] lpName
O nome do objeto mutex. O nome está limitado a MAX_PATH
caracteres. As comparações de nomes diferenciam maiúsculas de minúsculas.
Se lpName
corresponder ao nome de um mutex nomeado existente, esta função solicitará acesso MUTEX_ALL_ACCESS
. Neste caso, o parâmetro bInitialOwner
é ignorado porque já está definido pelo processo de criação. Se o parâmetro lpMutexAttributes
não for NULL, ele determinará se o identificador pode ser herdado, mas seus membros do descritor de segurança serão ignorados.
Se lpName
for NULL
, o mutex será criado sem nome.
Se lpName
corresponder ao nome de um evento, semáforo, temporizador de espera, tarefa ou objeto de mapeamento de arquivo existente, a função falhará e a função GetLastError retornará ERROR_INVALID_HANDLE
. Isso ocorre porque esses objetos compartilham o mesmo namespace.
O nome pode ter um prefixo "global" ou "local" para criar explicitamente o objeto no namespace global ou de sessão. O restante do nome pode conter qualquer caractere, exceto a barra invertida (). Para obter mais informações, consulte Namespace do objeto Kernel. Use sessões de Terminal Services para troca rápida de usuário. Os nomes dos objetos do kernel devem seguir as diretrizes descritas para os Serviços de Terminal para que os aplicativos possam oferecer suporte a vários usuários.
O objeto pode ser criado em um namespace privado. Para obter mais informações, consulte Namespaces de objetos.
Se a função for bem-sucedida, o valor de retorno será o identificador (Handle) do objeto mutex recém-criado.
Se a função falhar, o valor de retorno será NULL
. Para obter informações estendidas sobre erros, chame a função GetLastError.
Se o mutex for um mutex nomeado e o objeto existisse antes dessa função ser chamada, o valor de retorno será um identificador para o objeto existente e a função GetLastError retornará ERROR_ALREADY_EXISTS
.
Process Explorer é uma ferramenta fornecida oficialmente pela Microsoft para descobrir informações Handle
e DLL
que um processo foi aberto ou carregado.
Página oficial do Process Explorer: https://docs.microsoft.com/en-us/sysinternals/downloads/process-explorer
Exemplo:
Tomando o WeChat como exemplo, primeiro inicie o WeChat, encontre o processo chamado WeChat.exe
na interface principal do Process Explorer e selecione-o.
Em seguida, encontre Handle
com Type
Mutant
e Name
Sessions1BaseNamedObjects_WeChat_App_Instance_Identity_Mutex_Name
na interface Lower Pane
.
Depois de clicar com o botão direito Close Handle
para fechar o identificador, você poderá iniciar um novo processo.
handles = handler . find_handles ( process_ids = [ 10000 ], handle_names = [ r'Sessions1BaseNamedObjects_WeChat_App_Instance_Identity_Mutex_Name' ])
handler . close_handles ( handles )
Código-fonte de referência: client/handler/handler.py
tscon
Quando você usa a Área de Trabalho Remota para conectar-se a um computador remoto, fechar a Área de Trabalho Remota bloqueia o computador e exibe a tela de login. No modo de bloqueio, o computador não possui GUI
, portanto, qualquer teste GUI
atualmente em execução ou agendado falhará.
Para evitar problemas com testes GUI
, você pode usar o utilitário tscon
para desconectar da área de trabalho remota. tscon
retorna o controle para a sessão local original no computador remoto, ignorando a tela de login. Todos os programas no computador remoto continuam funcionando normalmente, incluindo testes GUI
.
tscon
? tscon
é uma ferramenta fornecida por sistemas Windows que pode ser usada para conectar-se a outra sessão no servidor Host de Sessão de Área de Trabalho Remota.
tscon
? tscon { < sessionID > | < sessionname > } [/dest: < sessionname > ] [/password: < pw > | /password: * ] [/v]
parâmetro | descrever |
---|---|
<sessionID> | Especifica o ID da sessão à qual se conectar. Se o parâmetro opcional /dest:<sessionname> for usado, o nome da sessão atual também poderá ser especificado. |
<sessionname> | Especifique o nome da sessão à qual se conectar. |
/dest: <sessionname> | Especifica o nome da sessão atual. Quando você se conecta a uma nova sessão, esta sessão será desconectada. Você também pode usar esse parâmetro para conectar a sessão de outro usuário a uma sessão diferente. |
/senha: <pw> | Especifique a senha do usuário proprietário da sessão à qual se conectar. Essa senha é necessária quando o usuário conectado não é o proprietário da sessão. |
/senha: * | Solicite a senha do usuário proprietário da sessão à qual você deseja se conectar. |
/v | Exibir informações sobre a operação que está sendo executada. |
/? | Exibir ajuda no prompt de comando. |
Para se desconectar de uma área de trabalho remota, execute o seguinte comando no computador remoto (na janela Conexão de Área de Trabalho Remota) como administrador, por exemplo, na linha de comando:
%windir% S ystem32 t scon.exe RDP-Tcp# # # NNN /dest:console
Onde RDP-Tcp### NNN
é ID
da sessão atual da área de trabalho remota, como RDP-Tcp#5
. Você pode vê-lo na coluna Sessão na guia Usuários do Gerenciador de Tarefas do Windows .
Você verá a mensagem Sua sessão de Serviços de Área de Trabalho Remota terminou e o cliente de Área de Trabalho Remota será fechado. No entanto, todos os programas e testes no computador remoto continuarão funcionando normalmente.
Dica: A coluna da sessão fica oculta por padrão. Para exibi-lo, clique com o botão direito em algum lugar na linha que mostra CPU, Memória, etc. e selecione Sessão no menu de contexto que é aberto.
Você pode usar um arquivo em lote para automatizar o processo de desconexão. No computador remoto, faça o seguinte:
for /f " skip=1 tokens=3 " %%s in ( ' query user %USERNAME% ' ) do (
%windir% S ystem32 t scon.exe %%s /dest:console
)
tscon
mantém o computador remoto desbloqueado, o que reduz a segurança do sistema. Após a conclusão da execução do teste, você pode bloquear a máquina usando o seguinte comando:
Rundll32.exe user32.dll, LockWorkStation
Se o processo rdpclip.exe
estiver em execução no computador remoto e a área de transferência não estiver vazia quando você se desconectar da sessão remota, o processo rdpclip.exe
poderá falhar.
Para evitar esse problema, você pode encerrar o processo rdpclip.exe
antes de desconectar a sessão.
Se precisar expandir a função de automação ou ser compatível com diferentes versões de clientes, você pode adicionar ou editar scripts de tarefas no módulo rpa-client/app.
Os dois métodos a seguir são usados principalmente no projeto:
pywinauto
É um módulo python para automação de GUI do Microsoft Windows. No caso mais simples, permite enviar operações de mouse e teclado para caixas de diálogo e controles do Windows, mas oferece suporte a operações mais complexas, como obter dados de texto.
Teste aéreo
É uma estrutura de teste de automação de UI baseada em reconhecimento de imagem lançada pela NetEase Games. É adequada para jogos e aplicativos. As plataformas suportadas são Windows, Android e iOS.
Certifique-se de que o sistema operacional que você está usando seja Windows 7 e superior e que a versão do Python seja 3.7.0 e superior.
Deve-se observar que a versão atual do airtest depende de pywinauto==0.6.3
, e o projeto atual requer pywinauto==0.6.8
. Adicione o parâmetro --no-deps
ao instalar as dependências ou execute manualmente pip install pywinauto==0.6.8
.
git clone https://github.com/yihleego/robotic-process-automation.git
cd robotic-process-automation/rpa-client
pip install --no-deps -r requirements.txt
O arquivo de configuração do cliente está localizado em rpa-client/config.yml e os desenvolvedores podem modificar a configuração de acordo com os cenários reais.
Propriedade | Descrição | Padrão |
---|---|---|
servidor.host | Host do servidor | host local |
servidor.porta | Porta do servidor | 18888 |
servidor.caminho | Caminho do servidor | /rpa |
servidor.ssl | Se deve ativar SSL | Falso |
tamanho do aplicativo | Número máximo de programas que podem ser executados | 32 |
<appid> . | Caminho do programa personalizado | Obter do registro |
airtest.cvstrategy | Algoritmo de reconhecimento de imagem | [tpl, peneirar, rápido] |
teste aéreo.timeout | Algoritmo de reconhecimento de imagem | 20 segundos |
airtest.timeout-tmp | Algoritmo de reconhecimento de imagem | 3 segundos |
registro.nível | Nível de registro | DEPURAR |
registro.formato | Formato de registro | Formato padrão |
registro.nome do arquivo | Nome do arquivo de registro | ./logs/rpa-client.log |
Basta executar rpa-client/main.py.
Certifique-se de que a versão do Java que você está usando é 17 ou superior. O serviço depende do MySQL e do Redis durante a execução.
git clone https://github.com/yihleego/robotic-process-automation.git
cd robotic-process-automation/rpa-server
mvn clean install
Propriedade | Descrição | Padrão |
---|---|---|
spring.datasource.driver-class-name | Orientado por fonte de dados | com.mysql.cj.jdbc.Driver |
primavera.datasource.url | URL da fonte de dados | jdbc:mysql://localhost:3306/rpa |
spring.datasource.nome de usuário | Nome de usuário da fonte de dados | |
primavera.datasource.senha | Senha da fonte de dados | |
primavera.data.redis.host | Anfitrião Redis | host local |
spring.data.redis.port | Porta Redis | 6379 |
spring.data.redis.senha | Senha Redis | |
spring.data.redis.database | Banco de dados Redis | 0 |
A configuração acima pode ser modificada no arquivo application.properties.
Propriedade | Descrição | Padrão |
---|---|---|
rpa.websocket.port | Porta de serviço WebSocket | 18888 |
rpa.websocket.path | Caminho do serviço WebSocket | /rpa |
rpa.websocket.idle-timeout | Tempo limite de inatividade do serviço WebSocket | 5m |
rpa.converter.date-time-pattern | Formato global de data e hora | aaaa-MM-dd HH:mm:ss |
rpa.converter.date-pattern | formato de data global | aaaa-MM-dd |
rpa.converter.time-pattern | formato de hora global | HH:mm:ss |
rpa.client.cache-key | Formato de chave de cache do cliente | rpa:client: <appid> : <account> |
rpa.client.cache-timeout | Tempo limite do cache do cliente | 5m |
Consulte RpaProperties para obter detalhes.
Antes de iniciar o serviço, execute o seguinte script na instância MySQL
Basta executar RpaApplication.java.
$(".btn").click();
.Para determinar se um aplicativo oferece suporte a UIA, você pode usar o software Inspect fornecido oficialmente pela Microsoft, que pode ser baixado do site oficial ou deste warehouse:
No exemplo, o WeChat usa o modo UiaApp porque é implementado com base no UIA, enquanto o Enterprise WeChat usa o modo AirApp, que é semelhante ao fato de haver apenas um Canvas em uma página da web. , portanto, eles só podem ser posicionados por meio de reconhecimento de imagem.
Baixe pacotes redistribuíveis do Visual C++ para Visual Studio 2013 https://www.microsoft.com/zh-cn/download/confirmation.aspx?id=40784
Consulte: 2#questão
Este projeto é apenas para referência de aprendizagem, por favor não o utilize em ambiente de produção.
Este projeto está sob a licença do MIT. Consulte o arquivo LICENSE para obter detalhes.