param ( [Parameter(Mandatory=$true)] [string[]]$action, [Parameter(Mandatory=$false)] [switch]$waitForChange, [Parameter(Mandatory=$false)] [int]$numberOfPresses, [Parameter(Mandatory=$false)] [string]$instanceIP, [Parameter(Mandatory=$false)] [switch]$fakeTap ) if(-not $instanceIP){$instanceIP = "10.0.211.121"} $DEBUG = 0 $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] $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() } } function Get-ScreenshotData($text) { adb connect $instanceIP *>$null $status = & adb devices if ($status -eq "${instanceIP}:5555 offline") { $instanceIP | Out-File -FilePath "C:\Ldplayer\Ldplayer9\restartADB.txt" adb connect $instanceIP *>null } adb -s $instanceIP exec-out screencap -p > $global:LDPlayerPath\screenshot.png *>$null & "C:\Program Files\Tesseract-OCR\tesseract.exe" "$global:LDPlayerPath\screenshot.png" "$global:LDPlayerPath\tesseract" -l eng tsv *>$null $tsvFile = "$global:LDPlayerPath\tesseract.tsv" $wordCoords = Get-Content $tsvFile | ConvertFrom-Csv -Delimiter "`t" $wordCoords | Where-Object ($_.level -eq 5) | Select-Object text, left, top, width, height $Data = $wordCoords | ForEach-Object { $x1 =[int]$_._left $y1 =[int]$_.top $width = [int]$_.width $height = [int]$_.height $z1 = $width/2 $z2 = $height/2 $midX =[math]::Round($x1+$z1) $midY =[math]::Round($y1+$z2) [PSCustomObject]@{ Text = $_.text Coords = "$midX $midY" } } $Element = $Data | Where-Object {$_.Text -and $_.Text.ToLower() -eq $text} $coordsForText=$Element.Coords if($coordsForText[1]){ return $coordsForTest[0]} return $coordsForText } function Find-Element($xml, $keyword) { if (-not $xml -is [System.Xml.XmlDocument] -or -not $keyword) { return $null } $sanitizedKeyword = $keyword.Replace("'", "''").ToLower() if($fakeTap){ Write-Host "faketap" $query = "//node[contains(translate(@text, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), '$sanitizedKeyword') or contains(translate(@content-desc, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), '$sanitizedKeyword')]" } else { $query = "//node[@class='android.widget.Button' and (contains(translate(@text, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), '$sanitizedKeyword') or contains(translate(@content-desc, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), '$sanitizedKeyword'))]" } $element = $xml.SelectSingleNode($query) return $xml.SelectSingleNode($query) } function Wait-For-ScreenChange($initialHash, [ref]$newXmlData) { $timeoutSeconds = 10 logger("Aguardando alteracao 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(); logger("Tela alterada! Prosseguindo..."); $newXmlData.Value = $currentScreenData; return $true } Start-Sleep -Seconds 1 } $stopwatch.Stop(); logger("!!!ERROR: TIMEOUT: A tela nao mudou apos $timeoutSeconds segundos."); return $false } function Invoke-TapAction($adbTarget, $xml, $keyword) { $element = Find-Element -xml $xml -keyword $keyword if (-not $element) { logger("!!WARNING: Elemento '$keyword' para tocar nao foi encontrado."); return $false } $bounds = $element.bounds if ($bounds -notmatch '\[(\d+),(\d+)\]\[(\d+),(\d+)\]') { logger("!!WARNING: Formato de 'bounds' invalido: $bounds"); return $false } $xMid = ([int]$Matches[1] + [int]$Matches[3]) / 2 $yMid = ([int]$Matches[2] + [int]$Matches[4]) / 2 logger("Acao: Tocando em '$element'...") adb -s $instanceIP shell input tap "$xMid $yMid" return $true } function Invoke-TypeAction($adbTarget, $textToType) { $formattedText = $textToType.Replace(' ', '%s') logger("Acao: Digitando o texto '$textToType'...") adb -s $instanceIP shell input text "'$formattedText'" 2>&1 return $true } if($waitForChange) { $xmlContent = (Get-Content -Path $global:LDPlayerPath\screen.xml) $initialHash = (Get-FileHash -Algorithm MD5 -InputStream ([System.IO.MemoryStream]::new([System.Text.Encoding]::UTF8.GetBytes($xmlContent)))).Hash } $actionType = $action.split('\s')[0] $cnt=0 while($true){ if($cnt -gt 50){return $false} $connected = adb connect $instanceIP 2>$null logger("$connected") $isOnline = adb devices 2> $null $pattern = [regex]::Escape($instanceIP) + ':\d+\s+device' if($isOnline -match $pattern){ break }else{ logger("falhou, tenando connectar de novo") & tskill adb Start-Sleep -Milliseconds 1000 $cnt+=1 } } switch ($actionType) { "tap" { & $global:LDPlayerPath\test.ps1 -instanceIP $instanceIP $actionType = $action.split('\s')[0] $keyword = $action.split('\s')[1] $xmlFile = get-content -path "$global:LDPlayerPath\screen.xml" $xml = [xml]$xmlFile logger("$actionType") $element = Find-Element -xml $xml -keyword $keyword if (-not $element) { logger("!!WARNING: Elemento '$keyword' para tocar nao foi encontrado."); return $false} $bounds = $element.bounds if ($bounds -notmatch '\[(\d+),(\d+)\]\[(\d+),(\d+)\]') { logger("!!WARNING: Formato de 'bounds' invalido: $bounds"); return } $xMid = ([int]$Matches[1] + [int]$Matches[3]) / 2 $yMid = ([int]$Matches[2] + [int]$Matches[4]) / 2 logger("Acao: Tocando em '$keyword'...") adb -s $instanceIP shell input tap "$xMid $yMid" 2>&1 } "tap_image" { $actionType = $action.split('\s')[0] $keyword = $action.split('\s')[1] $keyword $coords = Get-ScreenshotData($keyword) if (-not $coords) { logger("!!WARNING: Elemento '$keyword' para tocar nao foi encontrado."); return} if($coords[1]){$newCoords=$coords[1]}else{$newCoords=$coords} logger("Acao: Tocando em '$keyword' $newCoords...") $tapCommand = adb -s $instanceIP shell input tap $newCoords 2>&1 $tapCommand $coords } else {logger("not clickable and since not mentioned, not forcing")} "type" { $textToType = $action[1] logger("$actionType") $formattedText = $textToType logger("Acao: Digitando o texto '$textToType'...") $letters = $formattedText.ToCharArray() foreach($char in $letters) { $charInterval = get-random -minimum .1 -maximum 50 logger("$char") adb -s $instanceIP shell input text "'$char'" *>$null start-sleep -Milliseconds $charInterval } } "key" { $keyEventName = $action[1] if (-not $numberOfPresses) {$numberOfPresses = 1} logger("$actionType") logger("$keyEventName") $KeyEventMapJson = get-content -path "$global:LDPlayerPath\adb_key_events.json" -Raw $keyEventMap = $KeyEventMapJson | ConvertFrom-Json if ($keyEventMap.key_events.($keyEventName)) { $keyCode = $keyEventMap.key_events.$keyEventName for ($i = $numberOfPresses; $i -gt 0; $i--){ logger("Acao: Enviando evento de tecla '$keyEventName' $i/$numberOfPresses (codigo $keyCode)...") adb -s $instanceIP shell input keyevent $keyCode *>$null } } else { logger("!!WARNING: Evento de tecla '$keyEventName' desconhecido."); } } "open" { $appName = $action[1] logger("$actionType") logger("$appName") $csvData = Import-Csv -Path "$global:LDPlayerPath\appReference.csv" $appReference = @{} $csvData | ForEach-Object { $appReference[$_.Key] = $_.Value } if ($appReference[$appName]) { $appCode = $appReference[$appName] logger("Acao: Abrindo app '$appName' (codigo $appCode)...") $adbOUT = & adb -s $instanceIP shell monkey -p $appCode 1 2>&1 logger("$adbOUT") if($adbOUT -like "*No activities found to run*") {return $false} } else { logger("!!WARNING: App '$appCode' desconhecido.")} } }