Upload files to "/"
This commit is contained in:
248
Run-Automation_Updater.ps1
Normal file
248
Run-Automation_Updater.ps1
Normal file
@@ -0,0 +1,248 @@
|
||||
# --- INÍCIO DO MOTOR DE AUTOMAÇÃO (VERSÃO FINAL COM "GUARDIÃO ANR") ---
|
||||
|
||||
param(
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$IpAddress
|
||||
)
|
||||
|
||||
# --- Funções Auxiliares ---
|
||||
function Get-ScreenData($adbTarget) {
|
||||
for ($attempt = 1; $attempt -le 3; $attempt++) {
|
||||
try {
|
||||
Write-Host "Capturando hierarquia da UI (Tentativa $attempt)..."
|
||||
Start-Sleep -Milliseconds 250
|
||||
$dumpOutput = adb $adbTarget shell uiautomator dump
|
||||
if ($LASTEXITCODE -ne 0 -or $dumpOutput -like "*ERROR*") {
|
||||
Write-Warning "Comando 'uiautomator dump' falhou. Tentando novamente..."
|
||||
Start-Sleep -Seconds 1; continue
|
||||
}
|
||||
if ($dumpOutput -match 'dumped to: (/[\w/.-]+\.xml)') {
|
||||
$dumpPath = $Matches[1].Trim()
|
||||
} else {
|
||||
Write-Warning "Não foi possível encontrar o caminho do dump XML. Tentando novamente..."
|
||||
Start-Sleep -Seconds 1; continue
|
||||
}
|
||||
if (Test-Path ".\window_dump.xml") { Remove-Item ".\window_dump.xml" }
|
||||
adb $adbTarget pull $dumpPath window_dump.xml > $null
|
||||
if ((Test-Path ".\window_dump.xml") -and (Get-Item ".\window_dump.xml").Length -gt 0) {
|
||||
$xmlContent = Get-Content -Raw -Path ".\window_dump.xml" -Encoding UTF8
|
||||
return [PSCustomObject]@{
|
||||
Xml = [xml]$xmlContent
|
||||
Hash = (Get-FileHash -Algorithm MD5 -InputStream ([System.IO.MemoryStream]::new([System.Text.Encoding]::UTF8.GetBytes($xmlContent)))).Hash
|
||||
}
|
||||
}
|
||||
} catch { Write-Warning "Exceção na tentativa $attempt. $_"; Start-Sleep -Seconds 1 }
|
||||
}
|
||||
Write-Error "Falha crítica ao capturar a UI após 3 tentativas."
|
||||
return $null
|
||||
}
|
||||
|
||||
function Wait-For-ScreenChange($adbTarget, $initialHash, [ref]$newXmlData) {
|
||||
$timeoutSeconds = 10
|
||||
Write-Host "Aguardando alteração na tela (timeout de $timeoutSeconds segundos)..."
|
||||
$stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
|
||||
while ($stopwatch.Elapsed.TotalSeconds -lt $timeoutSeconds) {
|
||||
$currentScreenData = Get-ScreenData -adbTarget $adbTarget
|
||||
if ($currentScreenData -and $currentScreenData.Hash -ne $initialHash) {
|
||||
$stopwatch.Stop(); Write-Host "Tela alterada! Prosseguindo..."; $newXmlData.Value = $currentScreenData; return $true
|
||||
}
|
||||
Start-Sleep -Seconds 1
|
||||
}
|
||||
$stopwatch.Stop(); Write-Error "TIMEOUT: A tela não mudou após $timeoutSeconds segundos."; return $false
|
||||
}
|
||||
|
||||
function Find-Element($xml, $keyword) {
|
||||
if (-not $xml -is [System.Xml.XmlDocument] -or -not $keyword) { return $null }
|
||||
$sanitizedKeyword = $keyword.Replace("'", "''").ToLower()
|
||||
$query = "//node[contains(translate(@text, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), '$sanitizedKeyword') or contains(translate(@content-desc, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), '$sanitizedKeyword')]"
|
||||
return $xml.SelectSingleNode($query)
|
||||
}
|
||||
|
||||
function Test-ElementExists($xml, $keyword) {
|
||||
return (Find-Element -xml $xml -keyword $keyword) -ne $null
|
||||
}
|
||||
|
||||
function Invoke-TapAction($adbTarget, $xml, $keyword) {
|
||||
$element = Find-Element -xml $xml -keyword $keyword
|
||||
if (-not $element) { Write-Warning "Elemento '$keyword' para tocar não foi encontrado."; return $false }
|
||||
$bounds = $element.bounds
|
||||
if ($bounds -notmatch '\[(\d+),(\d+)\]\[(\d+),(\d+)\]') { Write-Warning "Formato de 'bounds' inválido: $bounds"; return $false }
|
||||
$xMid = ([int]$Matches[1] + [int]$Matches[3]) / 2
|
||||
$yMid = ([int]$Matches[2] + [int]$Matches[4]) / 2
|
||||
Write-Host "Ação: Tocando em '$($element.text)'..."
|
||||
adb $adbTarget shell input tap "$xMid $yMid"
|
||||
return $true
|
||||
}
|
||||
|
||||
function Invoke-TypeAction($adbTarget, $textToType) {
|
||||
$formattedText = $textToType.Replace(' ', '%s')
|
||||
Write-Host "Ação: Digitando o texto '$textToType'..."
|
||||
adb $adbTarget shell input text "'$formattedText'"
|
||||
return $true
|
||||
}
|
||||
|
||||
function Invoke-KeyEventAction($adbTarget, $keyEventName) {
|
||||
$keyEventMap = @{ "key_back" = 4; "key_home" = 3; "key_dpad_up" = 19; "key_dpad_down" = 20; "key_dpad_left" = 21; "key_dpad_right" = 22; "key_dpad_center" = 23; "key_volume_up" = 24; "key_volume_down" = 25; "key_power" = 26; "key_del" = 67; "key_enter" = 66; "key_escape" = 111; "key_menu" = 82; "key_app_switch" = 187; "key_space" = 62 }
|
||||
if ($keyEventMap.ContainsKey($keyEventName)) {
|
||||
$keyCode = $keyEventMap[$keyEventName]
|
||||
Write-Host "Ação: Enviando evento de tecla '$keyEventName' (código $keyCode)..."
|
||||
adb $adbTarget shell input keyevent $keyCode
|
||||
return $true
|
||||
} else { Write-Warning "Evento de tecla '$keyEventName' desconhecido."; return $false }
|
||||
}
|
||||
|
||||
function Evaluate-Conditions($xml, $conditionBlock) {
|
||||
if (-not $conditionBlock.Condicoes) { return $false }
|
||||
$operator = $conditionBlock.Operador
|
||||
$allConditions = $conditionBlock.Condicoes
|
||||
if ($operator -eq 'OR') {
|
||||
foreach ($condition in $allConditions) { if (Test-ElementExists $xml $condition) { return $true } }
|
||||
return $false
|
||||
} else {
|
||||
foreach ($condition in $allConditions) { if (-not (Test-ElementExists $xml $condition)) { return $false } }
|
||||
return $true
|
||||
}
|
||||
}
|
||||
|
||||
# >>> NOVA FUNÇÃO "GUARDIÃO" PARA LIDAR COM ERROS DO SISTEMA <<<
|
||||
function Handle-SystemDialogs($adbTarget, [ref]$screenData) {
|
||||
$xml = $screenData.Value.Xml
|
||||
# Verifica se o diálogo "não está a responder" (ANR) está na tela
|
||||
if (Test-ElementExists -xml $xml -keyword "não está a responder") {
|
||||
Write-Warning "Detectado diálogo 'IU não está a responder'. Tentando tocar em 'Aguardar'."
|
||||
$initialHash = $screenData.Value.Hash
|
||||
|
||||
$tappedWait = Invoke-TapAction -adbTarget $adbTarget -xml $xml -keyword "Aguardar"
|
||||
|
||||
if ($tappedWait) {
|
||||
# Espera o diálogo desaparecer
|
||||
$dialogDismissed = Wait-For-ScreenChange -adbTarget $adbTarget -initialHash $initialHash -newXmlData ([ref]$screenData)
|
||||
if (-not $dialogDismissed) {
|
||||
Write-Error "Tocou em 'Aguardar', mas o diálogo não desapareceu."
|
||||
}
|
||||
return $true # Indica que um diálogo foi tratado e o passo deve ser repetido
|
||||
} else {
|
||||
Write-Warning "Diálogo ANR detectado, mas o botão 'Aguardar' não foi encontrado."
|
||||
return $false
|
||||
}
|
||||
}
|
||||
return $false # Nenhum diálogo do sistema encontrado
|
||||
}
|
||||
|
||||
|
||||
# --- Lógica Principal do Motor ---
|
||||
adb kill-server
|
||||
adb connect 10.0.211.121
|
||||
adb devices
|
||||
Start-Sleep -Milliseconds 30000
|
||||
Write-Host "Carregando receita do arquivo 'receita1.json'..."
|
||||
try { $receita = Get-Content -Raw -Path ".\receita1.json" -Encoding UTF8 | ConvertFrom-Json } catch { Write-Error "Não foi possível encontrar ou ler o arquivo 'receita.json'."; exit }
|
||||
|
||||
|
||||
$passoAtualNome = ($receita.PSObject.Properties | Where-Object { $_.Name -eq 'Inicio' }).Name
|
||||
if (-not $passoAtualNome) { Write-Error "Ponto de partida 'Inicio' não encontrado na receita.json."; exit }
|
||||
|
||||
$maxPassos = 100; $passoCount = 0; $fatalError = $false
|
||||
$loopCounters = @{}
|
||||
$callStack = [System.Collections.Stack]::new()
|
||||
|
||||
while ($passoAtualNome -and $passoAtualNome -ne "Fim" -and $passoAtualNome -ne "FimComErro" -and $passoCount -lt $maxPassos -and (-not $fatalError)) {
|
||||
$passoCount++
|
||||
$passoAtual = $receita.($passoAtualNome)
|
||||
if (-not $passoAtual) { Write-Error "O passo '$passoAtualNome' não foi encontrado."; $fatalError = $true; continue }
|
||||
|
||||
Write-Host "---"; Write-Host "Passo ($passoCount/$maxPassos): $($passoAtual.Descricao) ($passoAtualNome)"
|
||||
|
||||
|
||||
$dialogHandled = $false
|
||||
do {
|
||||
$telaAtualData = Get-ScreenData $adbTarget
|
||||
if (-not $telaAtualData) { Write-Error "Não foi possível obter a hierarquia da UI."; $fatalError = $true; break }
|
||||
|
||||
# O "Guardião" é chamado aqui. Ele atualiza $telaAtualData se lidar com um diálogo.
|
||||
$dialogHandled = Handle-SystemDialogs -adbTarget $adbTarget -screenData ([ref]$telaAtualData)
|
||||
|
||||
} while ($dialogHandled -and (-not $fatalError)) # Continua no loop enquanto diálogos de erro estiverem sendo tratados
|
||||
|
||||
if ($fatalError) { continue } # Se a captura da UI falhou, pula para o fim
|
||||
|
||||
if ($passoAtual.Acao -and $passoAtual.Acao.Tipo) {
|
||||
$hashAntesDaAcao = $telaAtualData.Hash
|
||||
$acaoBemSucedida = $false
|
||||
|
||||
switch ($passoAtual.Acao.Tipo) {
|
||||
"Tocar" { $acaoBemSucedida = Invoke-TapAction -adbTarget $adbTarget -xml $telaAtualData.Xml -keyword $passoAtual.Acao.ElementoComTexto }
|
||||
"Digitar" { $acaoBemSucedida = Invoke-TypeAction -adbTarget $adbTarget -textToType $passoAtual.Acao.Texto }
|
||||
"KeyEvent" { $acaoBemSucedida = Invoke-KeyEventAction -adbTarget $adbTarget -keyEventName $passoAtual.Acao.Evento }
|
||||
"Loop" {
|
||||
if (-not $loopCounters.ContainsKey($passoAtualNome)) {
|
||||
if ($passoAtual.Acao.LoopType -eq 'For') { $loopCounters[$passoAtualNome] = [int]$passoAtual.Acao.Count }
|
||||
}
|
||||
$acaoBemSucedida = $true
|
||||
}
|
||||
}
|
||||
|
||||
if ($acaoBemSucedida -and $passoAtual.Acao.EsperaMudanca -ne $false -and $passoAtual.Acao.Tipo -ne 'Loop') {
|
||||
$telaMudou = Wait-For-ScreenChange -adbTarget $adbTarget -initialHash $hashAntesDaAcao -newXmlData ([ref]$telaAtualData)
|
||||
if (-not $telaMudou) { $fatalError = $true; continue }
|
||||
}
|
||||
}
|
||||
|
||||
$xmlDaTela = $telaAtualData.Xml
|
||||
$proximoPassoDefinido = $false
|
||||
|
||||
if ($passoAtual.Acao.Tipo -eq 'Loop') {
|
||||
$loopInfo = $passoAtual.Acao
|
||||
if ($loopInfo.LoopType -eq 'For') {
|
||||
if ($loopCounters[$passoAtualNome] -gt 0) {
|
||||
Write-Host "Loop 'For': Repetições restantes $($loopCounters[$passoAtualNome]). Entrando no corpo do loop."
|
||||
$loopCounters[$passoAtualNome]--
|
||||
$callStack.Push($passoAtualNome)
|
||||
$passoAtualNome = $loopInfo.LoopBodyPasso
|
||||
} else {
|
||||
Write-Host "Loop 'For' concluído. Saindo do loop."
|
||||
$loopCounters.Remove($passoAtualNome)
|
||||
$passoAtualNome = $passoAtual.PassoPadrao
|
||||
}
|
||||
} elseif ($loopInfo.LoopType -eq 'DoWhile') {
|
||||
if (-not (Test-ElementExists $xmlDaTela $loopInfo.ConditionElement)) {
|
||||
Write-Host "Loop 'DoWhile': Condição de parada não encontrada. Entrando no corpo do loop."
|
||||
$callStack.Push($passoAtualNome)
|
||||
$passoAtualNome = $loopInfo.LoopBodyPasso
|
||||
} else {
|
||||
Write-Host "Loop 'DoWhile': Condição de parada encontrada. Saindo do loop."
|
||||
$passoAtualNome = $passoAtual.PassoPadrao
|
||||
}
|
||||
}
|
||||
$proximoPassoDefinido = $true
|
||||
}
|
||||
|
||||
if ((-not $proximoPassoDefinido) -and $passoAtual.Transicoes) {
|
||||
foreach ($transicao in $passoAtual.Transicoes) {
|
||||
if (Evaluate-Conditions $xmlDaTela $transicao) {
|
||||
Write-Host "Condição IF satisfeita. Indo para o passo '$($transicao.ProximoPasso)'."
|
||||
$passoAtualNome = $transicao.ProximoPasso; $proximoPassoDefinido = $true; break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (-not $proximoPassoDefinido) {
|
||||
if (($passoAtual.PassoPadrao -eq $null) -and ($passoAtual.ProximoPassoFinal -eq $null) -and ($callStack.Count -gt 0)) {
|
||||
Write-Host "Fim do corpo do loop. Retornando para reavaliação do loop."
|
||||
$passoAtualNome = $callStack.Pop()
|
||||
} else {
|
||||
if ($passoAtual.ProximoPassoFinal) {
|
||||
$passoAtualNome = $passoAtual.ProximoPassoFinal
|
||||
} else {
|
||||
$passoAtualNome = $passoAtual.PassoPadrao
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# --- Fim da Execução ---
|
||||
Write-Host "---"
|
||||
if ($passoAtualNome -eq "Fim") { Write-Host "Automação concluída com sucesso!" }
|
||||
else { Write-Error "Automação finalizada. Estado final: $passoAtualNome" }
|
||||
|
||||
Remove-Item window_dump.xml -ErrorAction SilentlyContinue
|
||||
248
Run-Automation_Whatsapp.ps1
Normal file
248
Run-Automation_Whatsapp.ps1
Normal file
@@ -0,0 +1,248 @@
|
||||
# --- INÍCIO DO MOTOR DE AUTOMAÇÃO (VERSÃO FINAL COM "GUARDIÃO ANR") ---
|
||||
|
||||
param(
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$IpAddress
|
||||
)
|
||||
|
||||
# --- Funções Auxiliares ---
|
||||
function Get-ScreenData($adbTarget) {
|
||||
for ($attempt = 1; $attempt -le 3; $attempt++) {
|
||||
try {
|
||||
Write-Host "Capturando hierarquia da UI (Tentativa $attempt)..."
|
||||
Start-Sleep -Milliseconds 250
|
||||
$dumpOutput = adb $adbTarget shell uiautomator dump
|
||||
if ($LASTEXITCODE -ne 0 -or $dumpOutput -like "*ERROR*") {
|
||||
Write-Warning "Comando 'uiautomator dump' falhou. Tentando novamente..."
|
||||
Start-Sleep -Seconds 1; continue
|
||||
}
|
||||
if ($dumpOutput -match 'dumped to: (/[\w/.-]+\.xml)') {
|
||||
$dumpPath = $Matches[1].Trim()
|
||||
} else {
|
||||
Write-Warning "Não foi possível encontrar o caminho do dump XML. Tentando novamente..."
|
||||
Start-Sleep -Seconds 1; continue
|
||||
}
|
||||
if (Test-Path ".\window_dump.xml") { Remove-Item ".\window_dump.xml" }
|
||||
adb $adbTarget pull $dumpPath window_dump.xml > $null
|
||||
if ((Test-Path ".\window_dump.xml") -and (Get-Item ".\window_dump.xml").Length -gt 0) {
|
||||
$xmlContent = Get-Content -Raw -Path ".\window_dump.xml" -Encoding UTF8
|
||||
return [PSCustomObject]@{
|
||||
Xml = [xml]$xmlContent
|
||||
Hash = (Get-FileHash -Algorithm MD5 -InputStream ([System.IO.MemoryStream]::new([System.Text.Encoding]::UTF8.GetBytes($xmlContent)))).Hash
|
||||
}
|
||||
}
|
||||
} catch { Write-Warning "Exceção na tentativa $attempt. $_"; Start-Sleep -Seconds 1 }
|
||||
}
|
||||
Write-Error "Falha crítica ao capturar a UI após 3 tentativas."
|
||||
return $null
|
||||
}
|
||||
|
||||
function Wait-For-ScreenChange($adbTarget, $initialHash, [ref]$newXmlData) {
|
||||
$timeoutSeconds = 10
|
||||
Write-Host "Aguardando alteração na tela (timeout de $timeoutSeconds segundos)..."
|
||||
$stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
|
||||
while ($stopwatch.Elapsed.TotalSeconds -lt $timeoutSeconds) {
|
||||
$currentScreenData = Get-ScreenData -adbTarget $adbTarget
|
||||
if ($currentScreenData -and $currentScreenData.Hash -ne $initialHash) {
|
||||
$stopwatch.Stop(); Write-Host "Tela alterada! Prosseguindo..."; $newXmlData.Value = $currentScreenData; return $true
|
||||
}
|
||||
Start-Sleep -Seconds 1
|
||||
}
|
||||
$stopwatch.Stop(); Write-Error "TIMEOUT: A tela não mudou após $timeoutSeconds segundos."; return $false
|
||||
}
|
||||
|
||||
function Find-Element($xml, $keyword) {
|
||||
if (-not $xml -is [System.Xml.XmlDocument] -or -not $keyword) { return $null }
|
||||
$sanitizedKeyword = $keyword.Replace("'", "''").ToLower()
|
||||
$query = "//node[contains(translate(@text, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), '$sanitizedKeyword') or contains(translate(@content-desc, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), '$sanitizedKeyword')]"
|
||||
return $xml.SelectSingleNode($query)
|
||||
}
|
||||
|
||||
function Test-ElementExists($xml, $keyword) {
|
||||
return (Find-Element -xml $xml -keyword $keyword) -ne $null
|
||||
}
|
||||
|
||||
function Invoke-TapAction($adbTarget, $xml, $keyword) {
|
||||
$element = Find-Element -xml $xml -keyword $keyword
|
||||
if (-not $element) { Write-Warning "Elemento '$keyword' para tocar não foi encontrado."; return $false }
|
||||
$bounds = $element.bounds
|
||||
if ($bounds -notmatch '\[(\d+),(\d+)\]\[(\d+),(\d+)\]') { Write-Warning "Formato de 'bounds' inválido: $bounds"; return $false }
|
||||
$xMid = ([int]$Matches[1] + [int]$Matches[3]) / 2
|
||||
$yMid = ([int]$Matches[2] + [int]$Matches[4]) / 2
|
||||
Write-Host "Ação: Tocando em '$($element.text)'..."
|
||||
adb $adbTarget shell input tap "$xMid $yMid"
|
||||
return $true
|
||||
}
|
||||
|
||||
function Invoke-TypeAction($adbTarget, $textToType) {
|
||||
$formattedText = $textToType.Replace(' ', '%s')
|
||||
Write-Host "Ação: Digitando o texto '$textToType'..."
|
||||
adb $adbTarget shell input text "'$formattedText'"
|
||||
return $true
|
||||
}
|
||||
|
||||
function Invoke-KeyEventAction($adbTarget, $keyEventName) {
|
||||
$keyEventMap = @{ "key_back" = 4; "key_home" = 3; "key_dpad_up" = 19; "key_dpad_down" = 20; "key_dpad_left" = 21; "key_dpad_right" = 22; "key_dpad_center" = 23; "key_volume_up" = 24; "key_volume_down" = 25; "key_power" = 26; "key_del" = 67; "key_enter" = 66; "key_escape" = 111; "key_menu" = 82; "key_app_switch" = 187; "key_space" = 62 }
|
||||
if ($keyEventMap.ContainsKey($keyEventName)) {
|
||||
$keyCode = $keyEventMap[$keyEventName]
|
||||
Write-Host "Ação: Enviando evento de tecla '$keyEventName' (código $keyCode)..."
|
||||
adb $adbTarget shell input keyevent $keyCode
|
||||
return $true
|
||||
} else { Write-Warning "Evento de tecla '$keyEventName' desconhecido."; return $false }
|
||||
}
|
||||
|
||||
function Evaluate-Conditions($xml, $conditionBlock) {
|
||||
if (-not $conditionBlock.Condicoes) { return $false }
|
||||
$operator = $conditionBlock.Operador
|
||||
$allConditions = $conditionBlock.Condicoes
|
||||
if ($operator -eq 'OR') {
|
||||
foreach ($condition in $allConditions) { if (Test-ElementExists $xml $condition) { return $true } }
|
||||
return $false
|
||||
} else {
|
||||
foreach ($condition in $allConditions) { if (-not (Test-ElementExists $xml $condition)) { return $false } }
|
||||
return $true
|
||||
}
|
||||
}
|
||||
|
||||
# >>> NOVA FUNÇÃO "GUARDIÃO" PARA LIDAR COM ERROS DO SISTEMA <<<
|
||||
function Handle-SystemDialogs($adbTarget, [ref]$screenData) {
|
||||
$xml = $screenData.Value.Xml
|
||||
# Verifica se o diálogo "não está a responder" (ANR) está na tela
|
||||
if (Test-ElementExists -xml $xml -keyword "não está a responder") {
|
||||
Write-Warning "Detectado diálogo 'IU não está a responder'. Tentando tocar em 'Aguardar'."
|
||||
$initialHash = $screenData.Value.Hash
|
||||
|
||||
$tappedWait = Invoke-TapAction -adbTarget $adbTarget -xml $xml -keyword "Aguardar"
|
||||
|
||||
if ($tappedWait) {
|
||||
# Espera o diálogo desaparecer
|
||||
$dialogDismissed = Wait-For-ScreenChange -adbTarget $adbTarget -initialHash $initialHash -newXmlData ([ref]$screenData)
|
||||
if (-not $dialogDismissed) {
|
||||
Write-Error "Tocou em 'Aguardar', mas o diálogo não desapareceu."
|
||||
}
|
||||
return $true # Indica que um diálogo foi tratado e o passo deve ser repetido
|
||||
} else {
|
||||
Write-Warning "Diálogo ANR detectado, mas o botão 'Aguardar' não foi encontrado."
|
||||
return $false
|
||||
}
|
||||
}
|
||||
return $false # Nenhum diálogo do sistema encontrado
|
||||
}
|
||||
|
||||
|
||||
# --- Lógica Principal do Motor ---
|
||||
adb kill-server
|
||||
adb connect 10.0.211.121
|
||||
adb devices
|
||||
Start-Sleep -Milliseconds 30000
|
||||
Write-Host "Carregando receita do arquivo 'receita2.json'..."
|
||||
try { $receita = Get-Content -Raw -Path ".\receita2.json" -Encoding UTF8 | ConvertFrom-Json } catch { Write-Error "Não foi possível encontrar ou ler o arquivo 'receita.json'."; exit }
|
||||
|
||||
|
||||
$passoAtualNome = ($receita.PSObject.Properties | Where-Object { $_.Name -eq 'Inicio' }).Name
|
||||
if (-not $passoAtualNome) { Write-Error "Ponto de partida 'Inicio' não encontrado na receita.json."; exit }
|
||||
|
||||
$maxPassos = 100; $passoCount = 0; $fatalError = $false
|
||||
$loopCounters = @{}
|
||||
$callStack = [System.Collections.Stack]::new()
|
||||
|
||||
while ($passoAtualNome -and $passoAtualNome -ne "Fim" -and $passoAtualNome -ne "FimComErro" -and $passoCount -lt $maxPassos -and (-not $fatalError)) {
|
||||
$passoCount++
|
||||
$passoAtual = $receita.($passoAtualNome)
|
||||
if (-not $passoAtual) { Write-Error "O passo '$passoAtualNome' não foi encontrado."; $fatalError = $true; continue }
|
||||
|
||||
Write-Host "---"; Write-Host "Passo ($passoCount/$maxPassos): $($passoAtual.Descricao) ($passoAtualNome)"
|
||||
|
||||
# >>> NOVA LÓGICA DE PRÉ-VERIFICAÇÃO <<<
|
||||
$dialogHandled = $false
|
||||
do {
|
||||
$telaAtualData = Get-ScreenData $adbTarget
|
||||
if (-not $telaAtualData) { Write-Error "Não foi possível obter a hierarquia da UI."; $fatalError = $true; break }
|
||||
|
||||
# O "Guardião" é chamado aqui. Ele atualiza $telaAtualData se lidar com um diálogo.
|
||||
$dialogHandled = Handle-SystemDialogs -adbTarget $adbTarget -screenData ([ref]$telaAtualData)
|
||||
|
||||
} while ($dialogHandled -and (-not $fatalError)) # Continua no loop enquanto diálogos de erro estiverem sendo tratados
|
||||
|
||||
if ($fatalError) { continue } # Se a captura da UI falhou, pula para o fim
|
||||
|
||||
if ($passoAtual.Acao -and $passoAtual.Acao.Tipo) {
|
||||
$hashAntesDaAcao = $telaAtualData.Hash
|
||||
$acaoBemSucedida = $false
|
||||
|
||||
switch ($passoAtual.Acao.Tipo) {
|
||||
"Tocar" { $acaoBemSucedida = Invoke-TapAction -adbTarget $adbTarget -xml $telaAtualData.Xml -keyword $passoAtual.Acao.ElementoComTexto }
|
||||
"Digitar" { $acaoBemSucedida = Invoke-TypeAction -adbTarget $adbTarget -textToType $passoAtual.Acao.Texto }
|
||||
"KeyEvent" { $acaoBemSucedida = Invoke-KeyEventAction -adbTarget $adbTarget -keyEventName $passoAtual.Acao.Evento }
|
||||
"Loop" {
|
||||
if (-not $loopCounters.ContainsKey($passoAtualNome)) {
|
||||
if ($passoAtual.Acao.LoopType -eq 'For') { $loopCounters[$passoAtualNome] = [int]$passoAtual.Acao.Count }
|
||||
}
|
||||
$acaoBemSucedida = $true
|
||||
}
|
||||
}
|
||||
|
||||
if ($acaoBemSucedida -and $passoAtual.Acao.EsperaMudanca -ne $false -and $passoAtual.Acao.Tipo -ne 'Loop') {
|
||||
$telaMudou = Wait-For-ScreenChange -adbTarget $adbTarget -initialHash $hashAntesDaAcao -newXmlData ([ref]$telaAtualData)
|
||||
if (-not $telaMudou) { $fatalError = $true; continue }
|
||||
}
|
||||
}
|
||||
|
||||
$xmlDaTela = $telaAtualData.Xml
|
||||
$proximoPassoDefinido = $false
|
||||
|
||||
if ($passoAtual.Acao.Tipo -eq 'Loop') {
|
||||
$loopInfo = $passoAtual.Acao
|
||||
if ($loopInfo.LoopType -eq 'For') {
|
||||
if ($loopCounters[$passoAtualNome] -gt 0) {
|
||||
Write-Host "Loop 'For': Repetições restantes $($loopCounters[$passoAtualNome]). Entrando no corpo do loop."
|
||||
$loopCounters[$passoAtualNome]--
|
||||
$callStack.Push($passoAtualNome)
|
||||
$passoAtualNome = $loopInfo.LoopBodyPasso
|
||||
} else {
|
||||
Write-Host "Loop 'For' concluído. Saindo do loop."
|
||||
$loopCounters.Remove($passoAtualNome)
|
||||
$passoAtualNome = $passoAtual.PassoPadrao
|
||||
}
|
||||
} elseif ($loopInfo.LoopType -eq 'DoWhile') {
|
||||
if (-not (Test-ElementExists $xmlDaTela $loopInfo.ConditionElement)) {
|
||||
Write-Host "Loop 'DoWhile': Condição de parada não encontrada. Entrando no corpo do loop."
|
||||
$callStack.Push($passoAtualNome)
|
||||
$passoAtualNome = $loopInfo.LoopBodyPasso
|
||||
} else {
|
||||
Write-Host "Loop 'DoWhile': Condição de parada encontrada. Saindo do loop."
|
||||
$passoAtualNome = $passoAtual.PassoPadrao
|
||||
}
|
||||
}
|
||||
$proximoPassoDefinido = $true
|
||||
}
|
||||
|
||||
if ((-not $proximoPassoDefinido) -and $passoAtual.Transicoes) {
|
||||
foreach ($transicao in $passoAtual.Transicoes) {
|
||||
if (Evaluate-Conditions $xmlDaTela $transicao) {
|
||||
Write-Host "Condição IF satisfeita. Indo para o passo '$($transicao.ProximoPasso)'."
|
||||
$passoAtualNome = $transicao.ProximoPasso; $proximoPassoDefinido = $true; break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (-not $proximoPassoDefinido) {
|
||||
if (($passoAtual.PassoPadrao -eq $null) -and ($passoAtual.ProximoPassoFinal -eq $null) -and ($callStack.Count -gt 0)) {
|
||||
Write-Host "Fim do corpo do loop. Retornando para reavaliação do loop."
|
||||
$passoAtualNome = $callStack.Pop()
|
||||
} else {
|
||||
if ($passoAtual.ProximoPassoFinal) {
|
||||
$passoAtualNome = $passoAtual.ProximoPassoFinal
|
||||
} else {
|
||||
$passoAtualNome = $passoAtual.PassoPadrao
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# --- Fim da Execução ---
|
||||
Write-Host "---"
|
||||
if ($passoAtualNome -eq "Fim") { Write-Host "Automação concluída com sucesso!" }
|
||||
else { Write-Error "Automação finalizada. Estado final: $passoAtualNome" }
|
||||
|
||||
Remove-Item window_dump.xml -ErrorAction SilentlyContinue
|
||||
87
startLDPlayerByName.ps1
Normal file
87
startLDPlayerByName.ps1
Normal file
@@ -0,0 +1,87 @@
|
||||
#run ldplayer instance
|
||||
|
||||
param (
|
||||
[string]$instanceName
|
||||
)
|
||||
|
||||
$global:LDPlayerPath ="C:\Ldplayer\LDplayer9"
|
||||
$global:instanceNameglobal=$instanceName
|
||||
function logger($logMessage) {
|
||||
[int]$number = (get-content -path "$global:LDPlayerPath\index_count.txt")
|
||||
if($number -gt 21){ $number=0}
|
||||
$instanceList = Get-Content -Path "$global:LDPlayerPath\instanceList.txt"
|
||||
#$instanceNumber = $instanceList[$number]
|
||||
#$instanceData = (cat C:\Ldplayer\LDplayer9\vms\config\leidian${instanceNumber}.config)
|
||||
#$convertedData = $instanceData | ConvertFrom-Json
|
||||
foreach ( $inst in $instanceList) {
|
||||
$instanceData = (cat C:\Ldplayer\LDplayer9\vms\config\leidian${inst}.config)
|
||||
$convertedData = $instanceData | ConvertFrom-Json
|
||||
$name = $convertedData."statusSettings.playerName"
|
||||
if ($global:instanceNameglobal -eq $name){
|
||||
$count = $inst
|
||||
break
|
||||
}
|
||||
}
|
||||
#if(-not $instanceName){$name = $convertedData."statusSettings.playerName"}
|
||||
#$count = $number+1
|
||||
|
||||
$scriptName = Split-Path -Leaf $PSCommandPath
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss.fff"
|
||||
$timestampedLogMessage = $timestamp + " ${global:instanceNameglobal} -instanceID: ${count} -${scriptName} -PID: ${PID}-:" + $logMessage
|
||||
#$timestampedLogMessage
|
||||
$logFilePath = "$global:LDPlayerPath\LDAutoLog.txt"
|
||||
$fs = New-Object System.IO.FileStream($logFilePath, [System.IO.FileMode]::Append, [System.IO.FileAccess]::Write, [System.IO.FileShare]::Read)
|
||||
$sw = New-Object System.IO.StreamWriter($fs)
|
||||
try {
|
||||
$sw.WriteLine($timestampedLogMessage)
|
||||
} finally {
|
||||
$sw.Close()
|
||||
$fs.Close()
|
||||
}
|
||||
}
|
||||
|
||||
#$instanceName
|
||||
$instanceList = Get-Content -Path "$global:LDPlayerPath\instanceList.txt"
|
||||
foreach ( $inst in $instanceList) {
|
||||
$filename = "C:\Ldplayer\LDplayer9\vms\config\leidian${inst}.config"
|
||||
$instanceData = (cat C:\Ldplayer\LDplayer9\vms\config\leidian${inst}.config)
|
||||
$convertedData = $instanceData | ConvertFrom-Json
|
||||
$name = $convertedData."statusSettings.playerName"
|
||||
logger($instanceName)
|
||||
logger($name)
|
||||
if ($instanceName -eq $name){
|
||||
$count = $inst
|
||||
$c=$instanceData
|
||||
if (($newC=$c -replace '"networkSettings.networkAddress": "10.0.211.121",', '"networkSettings.networkAddress": "10.0.211.125",') -ne $c) {
|
||||
$newC | Set-Content $filename
|
||||
logger("changed IP temporarily to 10.0.211.125")
|
||||
logger(cat $filename | Select-String -Patter "10.0.211.125")
|
||||
}
|
||||
$foundInstance = $true
|
||||
break
|
||||
}
|
||||
}
|
||||
if(-not $foundInstance){
|
||||
logger("No LDPlayer instance with name: $instanceName")
|
||||
return $false}
|
||||
|
||||
logger("starting instance $instanceName")
|
||||
#$cnt=0
|
||||
#while($true) {
|
||||
# if(Test-Path "C:\Ldplayer\Ldplayer9\runningName.txt"){
|
||||
# if($cnt%10 -eq 0){logger("Antoher reconnection in progress, waiting...")}
|
||||
# Start-Sleep -Seconds 2
|
||||
# $cnt+=1
|
||||
# continue
|
||||
# } else {
|
||||
$launchCMD = "ldconsole.exe launch --name $instanceName"
|
||||
$launchCMD | Out-File -FilePath "C:\Ldplayer\Ldplayer9\launchName.txt"
|
||||
# return
|
||||
# }
|
||||
#}
|
||||
|
||||
<#
|
||||
$number=$number + 1
|
||||
if($number -eq 23){ $number=0}
|
||||
$number | Out-File -FilePath "c:\ldplayer\ldplayer9\index_count.txt"
|
||||
#>
|
||||
67
start_next_ldplayer.ps1
Normal file
67
start_next_ldplayer.ps1
Normal file
@@ -0,0 +1,67 @@
|
||||
#run ldplayer instance
|
||||
$global:LDPlayerPath ="C:\Ldplayer\LDplayer9"
|
||||
|
||||
function logger($logMessage) {
|
||||
[int]$number = (get-content -path "$global:LDPlayerPath\index_count.txt")
|
||||
if($number -gt 21){
|
||||
$number=0
|
||||
}
|
||||
|
||||
|
||||
$instanceList = Get-Content -Path "$global:LDPlayerPath\instanceList.txt"
|
||||
$instanceNumber = $instanceList[$number-1]
|
||||
$instanceData = (cat C:\Ldplayer\LDplayer9\vms\config\leidian${instanceNumber}.config)
|
||||
$convertedData = $instanceData | ConvertFrom-Json
|
||||
$name = $convertedData."statusSettings.playerName"
|
||||
$count = $number+1
|
||||
|
||||
$scriptName = Split-Path -Leaf $PSCommandPath
|
||||
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss.fff"
|
||||
$timestampedLogMessage = $timestamp + "-$name, ($count/22)-$scriptName-PID: ${PID}-:" + $logMessage
|
||||
$logFilePath = "$global:LDPlayerPath\LDAutoLog.txt"
|
||||
$fs = New-Object System.IO.FileStream($logFilePath, [System.IO.FileMode]::Append, [System.IO.FileAccess]::Write, [System.IO.FileShare]::Read)
|
||||
$sw = New-Object System.IO.StreamWriter($fs)
|
||||
try {
|
||||
$sw.WriteLine($timestampedLogMessage)
|
||||
} finally {
|
||||
$sw.Close()
|
||||
$fs.Close()
|
||||
}
|
||||
}
|
||||
|
||||
[int]$number = (get-content -path "c:\ldplayer\ldplayer9\index_count.txt")
|
||||
if($number -gt 21){
|
||||
|
||||
$number=0
|
||||
|
||||
$number | Out-File -FilePath "C:\Ldplayer\Ldplayer9\index_count.txt"
|
||||
return "Done"
|
||||
}
|
||||
$number
|
||||
$instanceList = Get-Content -Path "$global:LDPlayerPath\instanceList.txt"
|
||||
$instanceList
|
||||
$instanceNumber = $instanceList[$number-1]
|
||||
$instanceNumber
|
||||
if($instanceNumber -eq 21) {$filename = "C:\Ldplayer\LDplayer9\vms\config\leidian21.config"
|
||||
}else{$filename = "C:\Ldplayer\LDplayer9\vms\config\leidian${instanceNumber}.config"
|
||||
}
|
||||
$filename
|
||||
$instanceData = (cat C:\Ldplayer\LDplayer9\vms\config\leidian${instanceNumber}.config)
|
||||
if($instanceData -match '10\.0\.211\.125'){
|
||||
logger("making sure ip is correct")
|
||||
$newData = $instanceData -replace '10\.0\.211\.125', '10\.0\.211\.121'
|
||||
Set-Content -Path $filename -Value $filename -Value $newData -Encoding UTF8
|
||||
} else {logger("IP is already correct")}
|
||||
$convertedData = $instanceData | ConvertFrom-Json
|
||||
$name = $convertedData."statusSettings.playerName"
|
||||
$count = $number+1
|
||||
logger("starting instance $instanceNumber, $name, ($count/21)")
|
||||
$launchCMD = "ldconsole.exe launch --index $instanceNumber"
|
||||
Start-Sleep -milliseconds 1000
|
||||
$launchCMD | Out-File -FilePath "C:\Ldplayer\Ldplayer9\launchNow.txt"
|
||||
|
||||
<#
|
||||
$number=$number + 1
|
||||
if($number -eq 23){ $number=0}
|
||||
$number | Out-File -FilePath "c:\ldplayer\ldplayer9\index_count.txt"
|
||||
#>
|
||||
Reference in New Issue
Block a user