param( [string]$AppsDir = "", [string]$AdbPath = "", [string]$ShellPassword = "adb36987" ) $ErrorActionPreference = "Stop" $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path if (-not $AppsDir) { $AppsDir = Join-Path $ScriptDir "apps" } function Find-AdbPath { param( [string]$BaseDir ) $candidates = @( (Join-Path $BaseDir "adb.exe"), (Join-Path $BaseDir "tools\adb.exe"), (Join-Path $BaseDir "..\adb.exe"), (Join-Path $BaseDir "..\tools\adb.exe"), (Join-Path $BaseDir "..\..\tools\adb.exe"), "D:\Code\language-installer\tools\adb.exe", "D:\apk_tools\platform-tools\adb.exe" ) foreach ($candidate in $candidates) { try { $resolved = Resolve-Path -LiteralPath $candidate -ErrorAction Stop if ($resolved) { return $resolved.Path } } catch {} } $pathAdb = Get-Command adb.exe -ErrorAction SilentlyContinue if ($pathAdb) { return $pathAdb.Source } return "" } if (-not $AdbPath) { $AdbPath = Find-AdbPath -BaseDir $ScriptDir } if (-not (Test-Path -LiteralPath $AdbPath)) { throw "adb.exe not found. Put adb.exe next to this script or run with -AdbPath `"D:\path\adb.exe`"" } if (-not (Test-Path -LiteralPath $AppsDir)) { throw "apps directory not found: $AppsDir" } function Quote-ProcessArgument { param( [Parameter(Mandatory = $true)] [string]$Value ) if ($Value -notmatch '[\s"]') { return $Value } return '"' + $Value.Replace('"', '\"') + '"' } function Invoke-Adb { param( [Parameter(Mandatory = $true)] [string[]]$Arguments ) $psi = New-Object System.Diagnostics.ProcessStartInfo $psi.FileName = $AdbPath $psi.Arguments = (($Arguments | ForEach-Object { Quote-ProcessArgument $_ }) -join " ") $psi.RedirectStandardOutput = $true $psi.RedirectStandardError = $true $psi.UseShellExecute = $false $psi.CreateNoWindow = $true $proc = [System.Diagnostics.Process]::Start($psi) $stdout = $proc.StandardOutput.ReadToEnd() $stderr = $proc.StandardError.ReadToEnd() $proc.WaitForExit() return [pscustomobject]@{ Code = $proc.ExitCode Out = ($stdout + $stderr).Trim() } } function Invoke-AdbShellWithPassword { param( [Parameter(Mandatory = $true)] [string]$Command, [int]$TimeoutMs = 60000 ) $psi = New-Object System.Diagnostics.ProcessStartInfo $psi.FileName = $AdbPath $psi.Arguments = "-d shell" $psi.RedirectStandardInput = $true $psi.RedirectStandardOutput = $true $psi.RedirectStandardError = $true $psi.UseShellExecute = $false $psi.CreateNoWindow = $true $proc = New-Object System.Diagnostics.Process $proc.StartInfo = $psi [void]$proc.Start() Start-Sleep -Milliseconds 500 $proc.StandardInput.WriteLine($ShellPassword) Start-Sleep -Milliseconds 300 $proc.StandardInput.WriteLine($Command) $proc.StandardInput.WriteLine("exit") $proc.StandardInput.Close() if (-not $proc.WaitForExit($TimeoutMs)) { try { $proc.Kill() } catch {} return [pscustomobject]@{ Code = -1 Out = "shell command timeout: $Command" } } $stdout = $proc.StandardOutput.ReadToEnd() $stderr = $proc.StandardError.ReadToEnd() return [pscustomobject]@{ Code = $proc.ExitCode Out = ($stdout + $stderr).Trim() } } Write-Host "ADB: $AdbPath" Write-Host "Apps: $AppsDir" $devices = Invoke-Adb -Arguments @("-d", "devices") if ($devices.Code -ne 0 -or $devices.Out -notmatch "`tdevice") { Write-Host "[ERROR] No adb device connected." -ForegroundColor Red if ($devices.Out) { Write-Host $devices.Out } exit 1 } $root = Invoke-Adb -Arguments @("-d", "root") if ($root.Out) { Write-Host $root.Out } Start-Sleep -Seconds 2 $apks = Get-ChildItem -LiteralPath $AppsDir -Filter "*.apk" -File | Sort-Object Name if (-not $apks) { Write-Host "[ERROR] No APK files found in apps directory." -ForegroundColor Red exit 1 } $total = $apks.Count $index = 0 $success = 0 foreach ($apk in $apks) { $index++ $apkName = [System.IO.Path]::GetFileNameWithoutExtension($apk.Name) $targetDir = "/system/app/$apkName" $targetApk = "$targetDir/$($apk.Name)" Write-Host "" Write-Host "[$index/$total] $($apk.Name)" -ForegroundColor Cyan $mkdir = Invoke-AdbShellWithPassword -Command "mkdir -p '$targetDir'" if ($mkdir.Code -ne 0) { Write-Host "[ERROR] mkdir failed: $targetDir" -ForegroundColor Red if ($mkdir.Out) { Write-Host $mkdir.Out } exit 1 } $push = Invoke-Adb -Arguments @("-d", "push", $apk.FullName, $targetApk) if ($push.Code -ne 0) { Write-Host "[ERROR] push failed: $($apk.Name)" -ForegroundColor Red if ($push.Out) { Write-Host $push.Out } exit 1 } if ($push.Out) { Write-Host $push.Out } $chmodDir = Invoke-AdbShellWithPassword -Command "chmod 755 '$targetDir'" if ($chmodDir.Code -ne 0) { Write-Host "[ERROR] chmod 755 failed: $targetDir" -ForegroundColor Red if ($chmodDir.Out) { Write-Host $chmodDir.Out } exit 1 } $chmodApk = Invoke-AdbShellWithPassword -Command "chmod 644 '$targetApk'" if ($chmodApk.Code -ne 0) { Write-Host "[ERROR] chmod 644 failed: $targetApk" -ForegroundColor Red if ($chmodApk.Out) { Write-Host $chmodApk.Out } exit 1 } $success++ Write-Host "[OK] $($apk.Name)" -ForegroundColor Green } Write-Host "" Write-Host "[DONE] Pushed $success/$total APK files." -ForegroundColor Green