210 lines
5.6 KiB
PowerShell
210 lines
5.6 KiB
PowerShell
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
|