1
0
forked from BRT/arc

Fix for windows

This commit is contained in:
slava 2026-03-16 18:31:45 +07:00
parent 8ed25698e8
commit 10897164e9
5 changed files with 151 additions and 13 deletions

View File

@ -16,18 +16,27 @@ set(CMAKE_AUTOUIC ON)
add_compile_definitions(QT_MESSAGELOGCONTEXT) add_compile_definitions(QT_MESSAGELOGCONTEXT)
if (WIN32) if (WIN32)
# Определяем архитектуру: проверяем VCPKG triplet, CMAKE переменные и env # Определяем целевую архитектуру.
if (VCPKG_TARGET_TRIPLET MATCHES "arm64" # CMAKE_GENERATOR_PLATFORM (-A flag) самый надёжный способ определения при кросс-компиляции.
# На ARM64 хосте CMAKE_SYSTEM_PROCESSOR может быть "ARM64" даже при сборке под x64,
# поэтому сначала проверяем явные x64-признаки.
if (CMAKE_GENERATOR_PLATFORM STREQUAL "x64"
OR CMAKE_GENERATOR_PLATFORM STREQUAL "Win64"
OR VCPKG_TARGET_TRIPLET MATCHES "x64")
message(STATUS "Detected x64 target architecture")
set(CMAKE_PREFIX_PATH "C:/Qt/6.9.0/msvc2022_64")
list(APPEND CMAKE_PREFIX_PATH "C:/Users/User/.vcpkg-clion/vcpkg/installed/x64-windows")
set(Tesseract_DIR "C:/Users/User/.vcpkg-clion/vcpkg/installed/x64-windows/share/tesseract")
elseif (VCPKG_TARGET_TRIPLET MATCHES "arm64"
OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64"
OR CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64" OR CMAKE_GENERATOR_PLATFORM STREQUAL "ARM64"
OR CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "ARM64"
OR CMAKE_CXX_COMPILER MATCHES "arm64") OR CMAKE_CXX_COMPILER MATCHES "arm64")
message(STATUS "Detected ARM64 target architecture") message(STATUS "Detected ARM64 target architecture")
set(CMAKE_PREFIX_PATH "C:/Qt/6.9.0/msvc2022_arm64") set(CMAKE_PREFIX_PATH "C:/Qt/6.9.0/msvc2022_arm64")
list(APPEND CMAKE_PREFIX_PATH "C:/Users/User/.vcpkg-clion/vcpkg/installed/arm64-windows") list(APPEND CMAKE_PREFIX_PATH "C:/Users/User/.vcpkg-clion/vcpkg/installed/arm64-windows")
set(Tesseract_DIR "C:/Users/User/.vcpkg-clion/vcpkg/installed/arm64-windows/share/tesseract") set(Tesseract_DIR "C:/Users/User/.vcpkg-clion/vcpkg/installed/arm64-windows/share/tesseract")
else () else ()
message(STATUS "Detected x64 target architecture") message(STATUS "Detected x64 target architecture (default)")
set(CMAKE_PREFIX_PATH "C:/Qt/6.9.0/msvc2022_64") set(CMAKE_PREFIX_PATH "C:/Qt/6.9.0/msvc2022_64")
list(APPEND CMAKE_PREFIX_PATH "C:/Users/User/.vcpkg-clion/vcpkg/installed/x64-windows") list(APPEND CMAKE_PREFIX_PATH "C:/Users/User/.vcpkg-clion/vcpkg/installed/x64-windows")
set(Tesseract_DIR "C:/Users/User/.vcpkg-clion/vcpkg/installed/x64-windows/share/tesseract") set(Tesseract_DIR "C:/Users/User/.vcpkg-clion/vcpkg/installed/x64-windows/share/tesseract")

View File

@ -3,29 +3,60 @@
#include <qDebug> #include <qDebug>
#include <QString> #include <QString>
#include <QCoreApplication> #include <QCoreApplication>
#include <QFileInfo>
AdbUtils::AdbUtils(QObject *parent) : QObject(parent) { AdbUtils::AdbUtils(QObject *parent) : QObject(parent) {
} }
QString AdbUtils::adbPath() { QString AdbUtils::adbPath() {
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
return QCoreApplication::applicationDirPath() + "/tools/adb/windows/adb.exe"; QString path = QCoreApplication::applicationDirPath() + "/tools/adb/windows/adb.exe";
#else #else
return QCoreApplication::applicationDirPath() + "/tools/adb/macos/adb"; QString path = QCoreApplication::applicationDirPath() + "/tools/adb/macos/adb";
#endif #endif
static bool checked = false;
if (!checked) {
checked = true;
QFileInfo fi(path);
if (!fi.exists()) {
qWarning() << "[AdbUtils] adb not found at:" << path;
} else if (!fi.isExecutable()) {
qWarning() << "[AdbUtils] adb is not executable:" << path;
} else {
qDebug() << "[AdbUtils] adb path:" << path;
}
}
return path;
}
QString AdbUtils::adbDir() {
return QFileInfo(adbPath()).absolutePath();
} }
bool AdbUtils::startProcess(const QString &program, const QStringList &args, bool AdbUtils::startProcess(const QString &program, const QStringList &args,
QString *stdOut, QString *stdErr) { QString *stdOut, QString *stdErr) {
QProcess process; QProcess process;
process.setWorkingDirectory(adbDir());
process.start(program, args); process.start(program, args);
if (!process.waitForFinished() || if (!process.waitForStarted(5000)) {
qWarning() << "[AdbUtils] Failed to start process:" << program << args
<< "error:" << process.errorString();
if (stdErr) {
*stdErr = process.errorString();
}
return false;
}
if (!process.waitForFinished(30000) ||
process.exitStatus() != QProcess::NormalExit || process.exitStatus() != QProcess::NormalExit ||
process.exitCode() != 0) { process.exitCode() != 0) {
if (stdErr) { if (stdErr) {
*stdErr = QString::fromUtf8(process.readAllStandardError()); *stdErr = QString::fromUtf8(process.readAllStandardError());
} }
qWarning() << "[AdbUtils] Process failed:" << program << args
<< "exitCode:" << process.exitCode()
<< "stderr:" << (stdErr ? *stdErr : QString::fromUtf8(process.readAllStandardError()));
return false; return false;
} }
@ -45,9 +76,36 @@ bool AdbUtils::startProcess(const QString &program, const QStringList &args,
* @return [(id, status), ...] * @return [(id, status), ...]
*/ */
QList<QPair<QString, QString> > AdbUtils::getListDevices() { QList<QPair<QString, QString> > AdbUtils::getListDevices() {
const QString adb = adbPath();
const QString dir = adbDir();
// Убиваем чужой adb-сервер (возможно другой версии) и запускаем свой,
// чтобы избежать конфликта версий (например, scrcpy adb 35 vs bundled adb 36)
static bool serverRestarted = false;
if (!serverRestarted) {
serverRestarted = true;
QProcess kill;
kill.setWorkingDirectory(dir);
kill.start(adb, {"kill-server"});
kill.waitForFinished(5000);
qDebug() << "[AdbUtils] Killed existing adb server";
QProcess start;
start.setWorkingDirectory(dir);
start.start(adb, {"start-server"});
start.waitForFinished(10000);
qDebug() << "[AdbUtils] Started own adb server";
}
QProcess process; QProcess process;
process.start(adbPath(), {"devices"}); process.setWorkingDirectory(dir);
process.waitForFinished(); process.start(adb, {"devices"});
if (!process.waitForStarted(5000)) {
qWarning() << "[AdbUtils] Failed to start adb devices:" << process.errorString();
return {};
}
process.waitForFinished(10000);
const QString output = process.readAllStandardOutput(); const QString output = process.readAllStandardOutput();
QList<QPair<QString, QString> > devices; QList<QPair<QString, QString> > devices;
@ -76,10 +134,15 @@ QList<QPair<QString, QString> > AdbUtils::getListDevices() {
QString AdbUtils::tryToGetRunningAppPid(const QString &deviceId, const QString &packageName) { QString AdbUtils::tryToGetRunningAppPid(const QString &deviceId, const QString &packageName) {
QProcess process; QProcess process;
process.setWorkingDirectory(adbDir());
process.start(adbPath(), { process.start(adbPath(), {
"-s", deviceId, "-s", deviceId,
"shell", "pidof", packageName "shell", "pidof", packageName
}); });
if (!process.waitForStarted(5000)) {
qWarning() << "[AdbUtils] Failed to start adb pidof:" << process.errorString();
return {};
}
process.waitForFinished(); process.waitForFinished();
QString pid = process.readAllStandardOutput(); QString pid = process.readAllStandardOutput();
return pid.replace("\n", ""); return pid.replace("\n", "");
@ -87,6 +150,7 @@ QString AdbUtils::tryToGetRunningAppPid(const QString &deviceId, const QString &
bool AdbUtils::tryToStartApplication(const QString &deviceId, const QString &packageName) { bool AdbUtils::tryToStartApplication(const QString &deviceId, const QString &packageName) {
QProcess process; QProcess process;
process.setWorkingDirectory(adbDir());
process.start(adbPath(), { process.start(adbPath(), {
"-s", deviceId, "-s", deviceId,
"shell", "monkey", "shell", "monkey",
@ -94,6 +158,10 @@ bool AdbUtils::tryToStartApplication(const QString &deviceId, const QString &pac
"-c", "android.intent.category.LAUNCHER", "-c", "android.intent.category.LAUNCHER",
"1" "1"
}); });
if (!process.waitForStarted(5000)) {
qWarning() << "[AdbUtils] Failed to start adb monkey:" << process.errorString();
return false;
}
process.waitForFinished(); process.waitForFinished();
const QString output = process.readAllStandardOutput(); const QString output = process.readAllStandardOutput();
@ -110,11 +178,16 @@ bool AdbUtils::tryToStartApplication(const QString &deviceId, const QString &pac
bool AdbUtils::tryToKillApplication(const QString &deviceId, const QString &packageName) { bool AdbUtils::tryToKillApplication(const QString &deviceId, const QString &packageName) {
QProcess process; QProcess process;
process.setWorkingDirectory(adbDir());
process.start(adbPath(), { process.start(adbPath(), {
"-s", deviceId, "-s", deviceId,
"shell", "am", "shell", "am",
"force-stop", packageName "force-stop", packageName
}); });
if (!process.waitForStarted(5000)) {
qWarning() << "[AdbUtils] Failed to start adb force-stop:" << process.errorString();
return false;
}
process.waitForFinished(); process.waitForFinished();
return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0; return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0;
} }
@ -186,7 +259,13 @@ bool AdbUtils::takeScreenshot(const QString &deviceId, const QString &name) {
QByteArray AdbUtils::captureScreenshotBytes(const QString &deviceId) { QByteArray AdbUtils::captureScreenshotBytes(const QString &deviceId) {
QProcess process; QProcess process;
process.setWorkingDirectory(adbDir());
process.start(adbPath(), {"-s", deviceId, "exec-out", "screencap", "-p"}); process.start(adbPath(), {"-s", deviceId, "exec-out", "screencap", "-p"});
if (!process.waitForStarted(5000)) {
qWarning() << "[AdbUtils] captureScreenshotBytes failed to start for" << deviceId
<< "error:" << process.errorString();
return {};
}
if (!process.waitForFinished(10000) || process.exitCode() != 0) { if (!process.waitForFinished(10000) || process.exitCode() != 0) {
qWarning() << "[AdbUtils] captureScreenshotBytes failed for" << deviceId; qWarning() << "[AdbUtils] captureScreenshotBytes failed for" << deviceId;
return {}; return {};
@ -217,11 +296,16 @@ bool AdbUtils::takeXmlDump(const QString &deviceId, const QString &name) {
bool AdbUtils::makeTap(const QString &deviceId, const int x, const int y) { bool AdbUtils::makeTap(const QString &deviceId, const int x, const int y) {
QProcess process; QProcess process;
process.setWorkingDirectory(adbDir());
process.start(adbPath(), { process.start(adbPath(), {
"-s", deviceId, "-s", deviceId,
"shell", "input", "shell", "input",
"tap", QString::number(x), QString::number(y) "tap", QString::number(x), QString::number(y)
}); });
if (!process.waitForStarted(5000)) {
qWarning() << "[AdbUtils] Failed to start adb tap:" << process.errorString();
return false;
}
process.waitForFinished(); process.waitForFinished();
return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0; return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0;
} }
@ -247,12 +331,17 @@ bool AdbUtils::enableAdbIMEKeyboard(const QString &deviceId) {
bool AdbUtils::inputAdbIMEText(const QString &deviceId, const QString &text) { bool AdbUtils::inputAdbIMEText(const QString &deviceId, const QString &text) {
QProcess process; QProcess process;
process.setWorkingDirectory(adbDir());
process.start(adbPath(), { process.start(adbPath(), {
"-s", deviceId, "-s", deviceId,
"shell", "am", "broadcast", "shell", "am", "broadcast",
"-a", "ADB_INPUT_TEXT", "-a", "ADB_INPUT_TEXT",
"--es", "msg", text "--es", "msg", text
}); });
if (!process.waitForStarted(5000)) {
qWarning() << "[AdbUtils] Failed to start adb broadcast:" << process.errorString();
return false;
}
process.waitForFinished(); process.waitForFinished();
qDebug() << "[AdbUtils] inputAdbIMEText result:" << process.exitCode() qDebug() << "[AdbUtils] inputAdbIMEText result:" << process.exitCode()
<< "output:" << process.readAllStandardOutput().trimmed() << "output:" << process.readAllStandardOutput().trimmed()
@ -262,14 +351,20 @@ bool AdbUtils::inputAdbIMEText(const QString &deviceId, const QString &text) {
bool AdbUtils::disableAdbIMEKeyboard(const QString &deviceId) { bool AdbUtils::disableAdbIMEKeyboard(const QString &deviceId) {
QProcess process; QProcess process;
process.setWorkingDirectory(adbDir());
process.start(adbPath(), {"-s", deviceId, "shell", "ime", "disable", process.start(adbPath(), {"-s", deviceId, "shell", "ime", "disable",
"com.android.adbkeyboard/.AdbIME"}); "com.android.adbkeyboard/.AdbIME"});
if (!process.waitForStarted(5000)) {
qWarning() << "[AdbUtils] Failed to start adb ime disable:" << process.errorString();
return false;
}
process.waitForFinished(); process.waitForFinished();
return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0; return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0;
} }
bool AdbUtils::makeSwipe(const QString &deviceId, const int x1, const int y1, const int x2, const int y2) { bool AdbUtils::makeSwipe(const QString &deviceId, const int x1, const int y1, const int x2, const int y2) {
QProcess process; QProcess process;
process.setWorkingDirectory(adbDir());
process.start( process.start(
adbPath(), adbPath(),
{ {
@ -280,50 +375,74 @@ bool AdbUtils::makeSwipe(const QString &deviceId, const int x1, const int y1, co
QString::number(x2), QString::number(y2) QString::number(x2), QString::number(y2)
} }
); );
if (!process.waitForStarted(5000)) {
qWarning() << "[AdbUtils] Failed to start adb swipe:" << process.errorString();
return false;
}
process.waitForFinished(); process.waitForFinished();
return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0; return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0;
} }
bool AdbUtils::inputText(const QString &deviceId, const QString &text) { bool AdbUtils::inputText(const QString &deviceId, const QString &text) {
QProcess process; QProcess process;
process.setWorkingDirectory(adbDir());
process.start(adbPath(), { process.start(adbPath(), {
"-s", deviceId, "-s", deviceId,
"shell", "input", "shell", "input",
"text", text "text", text
}); });
if (!process.waitForStarted(5000)) {
qWarning() << "[AdbUtils] Failed to start adb input text:" << process.errorString();
return false;
}
process.waitForFinished(); process.waitForFinished();
return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0; return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0;
} }
bool AdbUtils::hideKeyboard(const QString &deviceId) { bool AdbUtils::hideKeyboard(const QString &deviceId) {
QProcess process; QProcess process;
process.setWorkingDirectory(adbDir());
process.start(adbPath(), { process.start(adbPath(), {
"-s", deviceId, "-s", deviceId,
"shell", "input", "shell", "input",
"keyevent", "111" "keyevent", "111"
}); });
if (!process.waitForStarted(5000)) {
qWarning() << "[AdbUtils] Failed to start adb keyevent:" << process.errorString();
return false;
}
process.waitForFinished(); process.waitForFinished();
return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0; return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0;
} }
bool AdbUtils::goBack(const QString &deviceId) { bool AdbUtils::goBack(const QString &deviceId) {
QProcess process; QProcess process;
process.setWorkingDirectory(adbDir());
process.start(adbPath(), { process.start(adbPath(), {
"-s", deviceId, "-s", deviceId,
"shell", "input", "shell", "input",
"keyevent", "4" "keyevent", "4"
}); });
if (!process.waitForStarted(5000)) {
qWarning() << "[AdbUtils] Failed to start adb keyevent:" << process.errorString();
return false;
}
process.waitForFinished(); process.waitForFinished();
return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0; return process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0;
} }
QSet<QString> AdbUtils::getListApps(const QString &deviceId) { QSet<QString> AdbUtils::getListApps(const QString &deviceId) {
QProcess process; QProcess process;
process.setWorkingDirectory(adbDir());
process.start(adbPath(), { process.start(adbPath(), {
"-s", deviceId, "-s", deviceId,
"shell", "pm list", "shell", "pm list",
"packages", "-3" "packages", "-3"
}); });
if (!process.waitForStarted(5000)) {
qWarning() << "[AdbUtils] Failed to start adb pm list:" << process.errorString();
return {};
}
process.waitForFinished(); process.waitForFinished();
const QString output = process.readAllStandardOutput(); const QString output = process.readAllStandardOutput();

View File

@ -47,6 +47,7 @@ public:
static QSet<QString> getListApps(const QString &deviceId); static QSet<QString> getListApps(const QString &deviceId);
private: private:
static QString adbDir();
static bool startProcess(const QString &program, const QStringList &args, static bool startProcess(const QString &program, const QStringList &args,
QString *stdOut = nullptr, QString *stdErr = nullptr); QString *stdOut = nullptr, QString *stdErr = nullptr);
}; };

Binary file not shown.

View File

@ -3,6 +3,7 @@
#include <QSettings> #include <QSettings>
#include <QProcess> #include <QProcess>
#include <QFile> #include <QFile>
#include <QFileInfo>
#include <QBuffer> #include <QBuffer>
#include <qeventloop.h> #include <qeventloop.h>
#include <QThread> #include <QThread>
@ -350,10 +351,11 @@ QByteArray convertPngToJpeg(const QByteArray &pngData, const int quality = 90) {
QByteArray DeviceScreener::takeScreenshot(const QString &deviceId) { QByteArray DeviceScreener::takeScreenshot(const QString &deviceId) {
QProcess process; QProcess process;
process.setWorkingDirectory(QFileInfo(AdbUtils::adbPath()).absolutePath());
QStringList arguments; QStringList arguments;
arguments << "-s" << deviceId << "exec-out" << "screencap" << "-p"; arguments << "-s" << deviceId << "exec-out" << "screencap" << "-p";
process.start("adb", arguments); process.start(AdbUtils::adbPath(), arguments);
if (!process.waitForFinished(5000)) { if (!process.waitForFinished(5000)) {
qWarning() << "ADB скриншот не завершился для" << deviceId; qWarning() << "ADB скриншот не завершился для" << deviceId;
@ -372,8 +374,14 @@ QByteArray DeviceScreener::takeScreenshot(const QString &deviceId) {
QList<QPair<QString, QString> > DeviceScreener::readAdbDevices() { QList<QPair<QString, QString> > DeviceScreener::readAdbDevices() {
QProcess process; QProcess process;
process.start("adb", QStringList() << "devices"); process.setWorkingDirectory(QFileInfo(AdbUtils::adbPath()).absolutePath());
process.waitForFinished(); process.start(AdbUtils::adbPath(), QStringList() << "devices");
if (!process.waitForStarted(5000)) {
qWarning() << "[DeviceScreener] Failed to start adb devices:" << process.errorString();
return {};
}
process.waitForFinished(10000);
const QString output = process.readAllStandardOutput(); const QString output = process.readAllStandardOutput();
QList<QPair<QString, QString> > devices; QList<QPair<QString, QString> > devices;
@ -412,7 +420,8 @@ DeviceInfo DeviceScreener::readDeviceInfo(const QString &deviceId, const bool is
auto runAdbCommand = [&](const QStringList &args) -> QString { auto runAdbCommand = [&](const QStringList &args) -> QString {
QProcess process; QProcess process;
process.start("adb", QStringList{"-s", deviceId} + args); process.setWorkingDirectory(QFileInfo(AdbUtils::adbPath()).absolutePath());
process.start(AdbUtils::adbPath(), QStringList{"-s", deviceId} + args);
process.waitForFinished(); process.waitForFinished();
return QString::fromUtf8(process.readAllStandardOutput()).trimmed(); return QString::fromUtf8(process.readAllStandardOutput()).trimmed();
}; };