From ce87ec16500dd2b62f86ee2d7f4b73e8406e0386 Mon Sep 17 00:00:00 2001 From: xmz7891 Date: Tue, 6 Oct 2026 22:49:14 +0800 Subject: [PATCH] =?UTF-8?q?1.7.0=EF=BC=9A=E5=B8=B8=E8=A7=84=E5=8F=91?= =?UTF-8?q?=E5=B8=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 版本号 1.7.0 -> 1.7.0 - 重建三端并打包 - 关键测试全过 --- _build/CHANGELOG.md | 10 + _build/add_code_arg.py | 112 ++++++ _build/add_favicon.py | 105 ++++++ _build/data_dir_fallback.py | 132 +++++++ _build/final_accept.sh | 66 ++++ _build/fix_code_oneshot.py | 109 ++++++ _build/fix_datadir_deterministic.py | 124 +++++++ _build/fix_programdata_perm.py | 207 +++++++++++ _build/gitee_release.py | 56 ++- _build/pack_include_ico.py | 52 +++ _build/package_remote.py | 6 +- _build/release.py | 19 +- _build/switch_release_to_setup.py | 109 ++++++ _build/sync_device_161.py | 15 +- _build/test_install_fresh.ps1 | 84 +++++ _build/zip_project.py | 138 +++++++ _tests/test_apk_contents.py | 2 +- _tests/test_package_remote.py | 8 +- android/AndroidManifest.xml | 2 +- android/build_apk.ps1 | 4 +- docs/AFTER-INSTALL.txt | 6 +- docs/BEFORE-INSTALL.txt | 4 +- docs/LICENSE.txt | 4 +- installer/build_installer.py | 113 ++++++ installer/license-combined.txt | 533 ++++++++++++++++++++++++++++ installer/ykxmz.iss | 255 +++++++++++++ relay/favicon.ico | Bin 0 -> 147470 bytes relay/relay.py | 27 +- windows/lanremote/__init__.py | 2 +- windows/lanremote/config.py | 163 ++++++++- windows/run_agent.py | 66 ++++ windows/version_info.txt | 4 +- 32 files changed, 2476 insertions(+), 61 deletions(-) create mode 100644 _build/CHANGELOG.md create mode 100644 _build/add_code_arg.py create mode 100644 _build/add_favicon.py create mode 100644 _build/data_dir_fallback.py create mode 100644 _build/final_accept.sh create mode 100644 _build/fix_code_oneshot.py create mode 100644 _build/fix_datadir_deterministic.py create mode 100644 _build/fix_programdata_perm.py create mode 100644 _build/pack_include_ico.py create mode 100644 _build/switch_release_to_setup.py create mode 100644 _build/test_install_fresh.ps1 create mode 100644 _build/zip_project.py create mode 100644 installer/build_installer.py create mode 100644 installer/license-combined.txt create mode 100644 installer/ykxmz.iss create mode 100644 relay/favicon.ico diff --git a/_build/CHANGELOG.md b/_build/CHANGELOG.md new file mode 100644 index 0000000..445199d --- /dev/null +++ b/_build/CHANGELOG.md @@ -0,0 +1,10 @@ +## 1.7.0 + +- 电脑端改成 **Windows 安装包**(Inno Setup),双击安装,不再需要解压 zip +- 安装向导里填 6 位配对码,装完手表直接连,不用再跑一次设置 +- 安装包支持静默批量部署:`ykxmz-setup-1.7.0.exe /VERYSILENT /CODE=123456` +- 三份说明文档合并进安装向导,必须接受才能继续 +- 修配置分裂问题:管理员装的配对码,普通用户账号看不到(数据目录改成按安装位置判断) +- 修装到 Program Files 后报「拒绝访问」:ProgramData 数据目录自动授权 +- 修安装卡死:`--code` 命令处理完不返回 +- 中转管理页加上网站图标 diff --git a/_build/add_code_arg.py b/_build/add_code_arg.py new file mode 100644 index 0000000..ddc54dd --- /dev/null +++ b/_build/add_code_arg.py @@ -0,0 +1,112 @@ +# -*- coding: utf-8 -*- +r"""给被控端加 --code / --name,供安装包调用。 + +为什么需要: + 安装向导里用户填了 6 位配对码,安装程序必须把它传给被控端。 + 但命令行原来只有 --new-code(随机换一个),**没有"设成指定值"** —— + 所以用户填的码会被忽略,装完还得再跑一次设置窗口。 + +加了之后安装程序可以这样一条命令搞定: + ykxmz.exe --code 789113 --name 三年二班 --autostart on --silent + +--code 同时会标记 setup_done,这样就不会再弹设置窗口。 +""" +from __future__ import annotations + +import ast +import sys +from pathlib import Path + +RUN = (Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote\windows" + r"\run_agent.py")) + +# ---------- 1. 参数声明 ---------- + +OLD_ARG = ''' parser.add_argument("--new-code", action="store_true", help="换一组配对码")''' + +NEW_ARG = ''' parser.add_argument("--new-code", action="store_true", help="换一组配对码") + parser.add_argument("--code", default=None, metavar="6位数字", + help="把配对码设成指定值(必须是 6 位数字)。" + "安装包用这个把用户在安装向导里填的码写进去。") + parser.add_argument("--name", default=None, metavar="名字", + help="设置这台电脑在手表上显示的名字" + "(默认用 Windows 的计算机名)")''' + +# ---------- 2. 处理逻辑 ---------- + +OLD_USE = ''' if args.reset_devices: + store.devices = {} + store.save_devices() + if args.new_code or not store.pairing_code(): + store.new_pairing_code()''' + +NEW_USE = ''' if args.reset_devices: + store.devices = {} + store.save_devices() + + # --code:把配对码设成安装向导里填的那个。 + # 严格要 6 位数字 —— 和设置窗口里的规则一致, + # 免得用户装了之后发现手表上少输一位连不上。 + if args.code is not None: + digits = "".join(ch for ch in str(args.code) if ch.isdigit()) + if len(digits) != 6: + print(f"配对码要 6 位数字,收到的是 {args.code!r}") + return 2 + try: + store.set_pairing_code(digits) + except ValueError as exc: + print(f"设置配对码失败:{exc}") + return 2 + # 装完就是"设置好了",不要再弹设置窗口 + store.set("setup_done", True) + store.set("allow_new_pairing", True) + print(f"配对码已设为 {digits}") + + if args.name: + store.set("name", str(args.name).strip()[:32]) + + if args.new_code or not store.pairing_code(): + store.new_pairing_code()''' + +# ---------- 3. 帮助文本 ---------- + +OLD_HELP = ''' --new-code 换一组配对码''' + +NEW_HELP = ''' --new-code 换一组配对码 + --code 123456 把配对码设成指定值(安装包用) + --name "三年二班" 设置电脑在手表上显示的名字''' + + +def main() -> int: + text = RUN.read_text(encoding="utf-8") + ok = True + + if '"--code"' in text: + print(" 已经改过") + return 0 + + for old, new, label in ((OLD_ARG, NEW_ARG, "参数声明"), + (OLD_USE, NEW_USE, "处理逻辑"), + (OLD_HELP, NEW_HELP, "帮助文本")): + if old not in text: + print(f" [失败] {label} 锚点没找到") + ok = False + continue + text = text.replace(old, new, 1) + print(f" {label}") + + if not ok: + return 1 + + RUN.write_text(text, encoding="utf-8", newline="\n") + try: + ast.parse(text) + print(" run_agent.py 语法 OK") + except SyntaxError as exc: + print(f" 语法错误: 行 {exc.lineno}: {exc.msg}") + return 1 + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/_build/add_favicon.py b/_build/add_favicon.py new file mode 100644 index 0000000..ee7db7c --- /dev/null +++ b/_build/add_favicon.py @@ -0,0 +1,105 @@ +# -*- coding: utf-8 -*- +r"""给中转管理页加 favicon(用项目的 app.ico)。 + +用户提过:"那个中转管理端那个,网页图标没有啊,图标就是我之前给你那个图标" + +做法: + 1. 把 windows/app.ico 拷一份到 relay/favicon.ico(跟 relay.py 同目录) + 2. relay.py 加一条 GET /favicon.ico 路由直接给这个文件 + 3. 管理页 里加 + +为什么不做成 base64 内嵌: + ico 有 147KB,内嵌到 relay.py 里会让源码从 78KB 涨到 270KB, + 而且每次改图标都要动代码。放成独立文件干净得多。 +""" +from __future__ import annotations + +import ast +import shutil +import sys +from pathlib import Path + +ROOT = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote") +RELAY = ROOT / "relay" / "relay.py" +ICON_SRC = ROOT / "windows" / "app.ico" +ICON_DST = ROOT / "relay" / "favicon.ico" + +# ---------- 1. 路由 ---------- + +ANCHOR_ROUTE = ''' # ---- 成品下载(挂在管理页上给人下 APK / 整包)----''' + +NEW_ROUTE = ''' # ---- 网站图标 ---- + if path in ("/favicon.ico", "/apple-touch-icon.png"): + icon = Path(__file__).resolve().parent / "favicon.ico" + if icon.is_file(): + try: + blob = icon.read_bytes() + except OSError: + blob = b"" + if blob: + self.send_response(200) + self.send_header("Content-Type", "image/x-icon") + self.send_header("Content-Length", str(len(blob))) + # 图标不常变,让浏览器缓存一天 + self.send_header("Cache-Control", "public, max-age=86400") + self.end_headers() + self.wfile.write(blob) + return + # 没有图标文件就 404,别让请求打到后面的逻辑 + self.send_response(404) + self.send_header("Content-Length", "0") + self.end_headers() + return + +''' + ANCHOR_ROUTE + +# ---------- 2. 页面里声明 ---------- + +ANCHOR_HEAD = '''''' + +NEW_HEAD = (''' + +''') + + +def main() -> int: + ok = True + + # ---- 图标文件 ---- + if not ICON_SRC.is_file(): + print(f" [失败] 找不到 {ICON_SRC}") + return 1 + shutil.copy2(ICON_SRC, ICON_DST) + print(f" 拷贝图标 -> relay/favicon.ico({ICON_DST.stat().st_size} 字节)") + + text = RELAY.read_text(encoding="utf-8") + + if "favicon.ico" in text: + print(" relay.py 里已经有 favicon 路由") + else: + for old, new, label in ((ANCHOR_ROUTE, NEW_ROUTE, "favicon 路由"), + (ANCHOR_HEAD, NEW_HEAD, "页面里的 link 声明")): + if old not in text: + print(f" [失败] {label} —— 锚点没找到") + ok = False + continue + text = text.replace(old, new, 1) + print(f" {label}") + + if ok: + RELAY.write_text(text, encoding="utf-8", newline="\n") + + if not ok: + return 1 + + try: + ast.parse(RELAY.read_text(encoding="utf-8")) + print(" relay.py 语法 OK") + except SyntaxError as exc: + print(f" 语法错误: 行 {exc.lineno}: {exc.msg}") + return 1 + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/_build/data_dir_fallback.py b/_build/data_dir_fallback.py new file mode 100644 index 0000000..12d64df --- /dev/null +++ b/_build/data_dir_fallback.py @@ -0,0 +1,132 @@ +# -*- coding: utf-8 -*- +r"""数据目录自动回退:写不进程序目录就转 ProgramData。 + +背景: + 原来的 data_dir() 就是 app_dir()/data —— 数据存在 exe 旁边。 + 绿色版没问题,但**做成安装包装到 Program Files 之后**, + 普通用户对那个目录没有写权限,配置会存不下去。 + +用户选的做法: + "能写 exe 旁边就写,不能就转 ProgramData" + + 这样两种情况都对: + * 绿色版 / 装在 D 盘 / 便携 U 盘 -> 还是存在旁边,拔走就带走配置 + * 装在 Program Files -> 自动转 C:\ProgramData\ykxmz, + 所有用户共用一份(配对码不会因为换 Windows 账号而丢) + +顺带加一个 YKXMZ_DATA 环境变量,测试和特殊部署可以强制指定。 +""" +from __future__ import annotations + +import ast +import sys +from pathlib import Path + +CONFIG = (Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote\windows" + r"\lanremote\config.py")) + +OLD = '''def app_dir() -> Path: + """程序所在目录(兼容 PyInstaller 冻结环境)。""" + if getattr(sys, "frozen", False): + return Path(sys.executable).resolve().parent + return Path(__file__).resolve().parent.parent + + +def data_dir() -> Path: + return app_dir() / "data"''' + +NEW = '''def app_dir() -> Path: + """程序所在目录(兼容 PyInstaller 冻结环境)。""" + if getattr(sys, "frozen", False): + return Path(sys.executable).resolve().parent + return Path(__file__).resolve().parent.parent + + +# 数据目录只算一次,之后缓存 —— 每个命令都去试写一次太浪费 +_DATA_DIR_CACHE: Path | None = None + + +def _can_write(folder: Path) -> bool: + """这个目录能不能写(不存在就先建)。""" + try: + folder.mkdir(parents=True, exist_ok=True) + probe = folder / ".write-test" + probe.write_text("x", encoding="utf-8") + probe.unlink() + return True + except OSError: + return False + + +def data_dir() -> Path: + """配置 / 令牌 / 接收文件的存放目录。 + + 优先级: + 1. 环境变量 YKXMZ_DATA(测试和特殊部署用) + 2. 程序目录下的 data/ —— 绿色版、便携 U 盘,拔走就带走配置 + 3. %PROGRAMDATA%\\ykxmz\\data —— 装到 Program Files 时用这个 + + 为什么要有第 3 条: + 安装包默认装到 C:\\Program Files\\ykxmz, + 普通用户对那里**没有写权限**(Windows 的硬规矩,不是 bug)。 + 不转走的话,配对码和令牌会存不下去,用户会莫名其妙连不上。 + ProgramData 是所有用户可写的公共位置,换 Windows 账号也不丢配置。 + """ + global _DATA_DIR_CACHE + if _DATA_DIR_CACHE is not None: + return _DATA_DIR_CACHE + + override = os.environ.get("YKXMZ_DATA") + if override: + _DATA_DIR_CACHE = Path(override) + return _DATA_DIR_CACHE + + beside = app_dir() / "data" + if _can_write(beside): + _DATA_DIR_CACHE = beside + return _DATA_DIR_CACHE + + base = os.environ.get("PROGRAMDATA") or r"C:\\ProgramData" + common = Path(base) / "ykxmz" / "data" + try: + common.mkdir(parents=True, exist_ok=True) + except OSError: + # 兜底:连 ProgramData 都写不了(极罕见),退回用户目录 + common = (Path(os.environ.get("LOCALAPPDATA") + or Path.home()) / "ykxmz" / "data") + common.mkdir(parents=True, exist_ok=True) + _DATA_DIR_CACHE = common + return _DATA_DIR_CACHE''' + + +def main() -> int: + text = CONFIG.read_text(encoding="utf-8") + + if "YKXMZ_DATA" in text: + print(" 已经改过") + return 0 + if OLD not in text: + print(" [失败] 锚点没找到") + return 1 + + text = text.replace(OLD, NEW, 1) + + # 确认 os 已经 import 了 + if "\nimport os" not in text: + text = text.replace("import sys\n", "import os\nimport sys\n", 1) + print(" 补了 import os") + + CONFIG.write_text(text, encoding="utf-8", newline="\n") + print(" data_dir 加了自动回退(ProgramData)") + + try: + ast.parse(text) + print(" config.py 语法 OK") + except SyntaxError as exc: + print(f" 语法错误: 行 {exc.lineno}: {exc.msg}") + return 1 + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/_build/final_accept.sh b/_build/final_accept.sh new file mode 100644 index 0000000..a3ac63e --- /dev/null +++ b/_build/final_accept.sh @@ -0,0 +1,66 @@ +#!/bin/bash +# 最终验收:下载区 + 服务状态 +set -u + +BASE=http://127.0.0.1:8080 +PUB=https://relay.xxmxxs.top +UA='LanRemote/1.4.0' +KEY=$(cat /root/lanremote-relay/data/admin_key.txt 2>/dev/null) + +echo "===== 1. 管理页下载区 =====" +page=$(curl -s --max-time 10 -H "X-Admin: $KEY" "$BASE/" 2>/dev/null) +for n in 'id=dlPanel' '下载最新版' '/v1/downloads'; do + if echo "$page" | grep -q "$n"; then echo " ✓ $n"; else echo " ✗ $n"; fi +done + +echo +echo "===== 2. 下载区文件列表 =====" +curl -s --max-time 15 "$BASE/v1/downloads" | python3 -c ' +import json, sys +d = json.load(sys.stdin) +files = d.get("files", []) +pick = None +for f in files: + if "agent" in f["name"].lower(): + pick = f + break +print(" 会挑:", pick["name"] if pick else "(无)") +for f in files: + print(" %-32s %6.2f MB" % (f["name"], f["size"] / 1024 / 1024)) +' + +echo +echo "===== 3. 公网下载三个文件 =====" +for f in ykxmz-watch-1.6.2.apk ykxmz-server-1.6.2.zip; do + info=$(curl -s --max-time 120 -o /dev/null \ + -w '%{http_code} %{size_download}' \ + -H "User-Agent: $UA" "$PUB/download/$f" 2>/dev/null) + printf " %-30s %s\n" "$f" "$info" +done + +echo +echo "===== 4. 服务状态 =====" +for s in lanremote-nettune.service lanremote-relay lanremote-tunnel \ + lanremote-watchdog.timer; do + printf " %-30s %-9s %s\n" "$s" \ + "$(systemctl is-active "$s" 2>/dev/null)" \ + "$(systemctl is-enabled "$s" 2>/dev/null)" +done + +echo +echo "===== 5. 网络调优(重启后还在吗)=====" +echo " tcp_mtu_probing = $(cat /proc/sys/net/ipv4/tcp_mtu_probing)" +echo " MSS 规则 $(iptables -t mangle -L -n 2>/dev/null | grep -ci mss) 条" +echo " 隧道连接数 = $(curl -s --max-time 5 http://127.0.0.1:20241/metrics 2>/dev/null | grep '^cloudflared_tunnel_ha_connections' | awk '{print $2}')" +echo " 中转版本 = $(curl -s --max-time 8 $BASE/v1/health | python3 -c 'import json,sys; print(json.load(sys.stdin).get("version"))' 2>/dev/null)" + +echo +echo "===== 6. 可用率(20 次)=====" +ok=0 +for i in $(seq 1 20); do + c=$(timeout 12 curl -4 -s -o /dev/null -w '%{http_code}' \ + -H "User-Agent: $UA" "$PUB/v1/health" 2>/dev/null) + [ "$c" = "200" ] && ok=$((ok+1)) + sleep 1 +done +echo " 公网 $ok/20 = $((ok * 5))%" diff --git a/_build/fix_code_oneshot.py b/_build/fix_code_oneshot.py new file mode 100644 index 0000000..149db6e --- /dev/null +++ b/_build/fix_code_oneshot.py @@ -0,0 +1,109 @@ +# -*- coding: utf-8 -*- +r"""修:--code / --name 处理完不退出,害得安装程序卡死。 + +现象: + 装完之后配对码没写进去,而且安装程序在 CurStepChanged 里 + 用 ewWaitUntilTerminated 等 ykxmz.exe --code ... --silent, + **永远等不到** —— 因为 --silent 是常驻守护进程,不会返回。 + +根因: + main() 里 --code 那段处理完之后没有 return, + 继续往下走到 run_silent(),于是变成"启动一个常驻服务"。 + +改法: + --code / --name 做成**一次性命令**:写完配置、打印、立刻退出。 + 想同时启动服务就显式加 --silent(那时才走守护进程)。 + +这样安装程序的分工就干净了: + CurStepChanged ykxmz.exe --code 123456 <- 秒退,只写配置 + [Run] postinstall ykxmz.exe --silent <- 启动,nowait 不等 +""" +from __future__ import annotations + +import ast +import sys +from pathlib import Path + +RUN = (Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote\windows" + r"\run_agent.py")) + +OLD = ''' if args.code is not None or args.name: + store = Store(data_dir()) + if args.code is not None: + digits = "".join(ch for ch in str(args.code) if ch.isdigit()) + if len(digits) != 6: + print(f"配对码要 6 位数字,收到的是 {args.code!r}") + return 2 + try: + store.set_pairing_code(digits) + except ValueError as exc: + print(f"设置配对码失败:{exc}") + return 2 + # 装完就算"设置好了",不要再弹设置窗口 + store.set("setup_done", True) + store.set("allow_new_pairing", True) + print(f"配对码已设为 {digits}") + if args.name: + store.set("name", str(args.name).strip()[:32]) + print(f"电脑名已设为 {store.get('name')}") + + if args.autostart:''' + +NEW = ''' if args.code is not None or args.name: + store = Store(data_dir()) + wrote = False + if args.code is not None: + digits = "".join(ch for ch in str(args.code) if ch.isdigit()) + if len(digits) != 6: + print(f"配对码要 6 位数字,收到的是 {args.code!r}") + return 2 + try: + store.set_pairing_code(digits) + except ValueError as exc: + print(f"设置配对码失败:{exc}") + return 2 + # 装完就算"设置好了",不要再弹设置窗口 + store.set("setup_done", True) + store.set("allow_new_pairing", True) + print(f"配对码已设为 {digits}") + wrote = True + if args.name: + store.set("name", str(args.name).strip()[:32]) + print(f"电脑名已设为 {store.get('name')}") + wrote = True + + # 只写了配置就结束 —— 这是一次性命令。 + # 不加这个 return 的话会继续走到 run_silent(), + # 变成常驻进程永不返回,调用方(安装程序)会一直等下去。 + # 想顺便启动服务,显式加 --silent。 + if wrote and not (args.silent or args.add_device is not None + or args.setup): + return 0 + + if args.autostart:''' + + +def main() -> int: + text = RUN.read_text(encoding="utf-8") + if "只写了配置就结束" in text: + print(" 已经改过") + return 0 + if OLD not in text: + print(" [失败] 锚点没找到") + return 1 + + text = text.replace(OLD, NEW, 1) + RUN.write_text(text, encoding="utf-8", newline="\n") + print(" --code / --name 改成一次性命令(写完就退出)") + + try: + ast.parse(text) + print(" run_agent.py 语法 OK") + except SyntaxError as exc: + print(f" 语法错误: 行 {exc.lineno}: {exc.msg}") + return 1 + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/_build/fix_datadir_deterministic.py b/_build/fix_datadir_deterministic.py new file mode 100644 index 0000000..2b87777 --- /dev/null +++ b/_build/fix_datadir_deterministic.py @@ -0,0 +1,124 @@ +# -*- coding: utf-8 -*- +r"""修:按"能不能写"判断数据目录导致安装版配置分裂。 + +现象: + 安装时(管理员)把 settings.json 写到了 + C:\Program Files\ykxmz\data\settings.json + 之后普通用户运行时,_can_write() 对那个目录返回 False, + 于是转到 + C:\ProgramData\ykxmz\data + 目录是空的 —— 安装时设的配对码普通用户根本看不到。 + +根因: + 用"当前用户能不能写"来决定数据目录,这个判断**不稳定**: + 同一个程序,管理员跑和普通用户跑会得出不同结论, + 结果就是配置分裂成两份,谁也看不见谁。 + +改法: + 改成**确定性**判断 —— 看程序装在哪,不看当前是谁在跑: + * 装在 Program Files 下 -> 安装版,数据一律放 ProgramData + * 其它位置(绿色版/D盘/U盘)-> 能写 exe 旁边就写旁边 + 这样管理员和普通用户看到的是同一份配置。 +""" +from __future__ import annotations + +import ast +import sys +from pathlib import Path + +CONFIG = (Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote\windows" + r"\lanremote\config.py")) + +# ---------- 1. 加"是不是安装版"的判断 ---------- + +OLD_MARK = '''def data_dir() -> Path:''' + +NEW_MARK = '''def _is_installed_copy() -> bool: + """程序是不是装在 Program Files 下(也就是"安装版")。 + + 这个判断只跟**程序装在哪**有关,跟"当前是谁在跑"无关 —— + 这正是关键:数据目录必须对所有用户是同一个, + 否则管理员装的配置普通用户看不见(实测踩过)。 + """ + try: + here = str(app_dir()).lower().replace("/", "\\\\") + except OSError: + return False + for name in ("ProgramFiles", "ProgramFiles(x86)", "ProgramW6432"): + base = os.environ.get(name) + if not base: + continue + prefix = str(base).lower().replace("/", "\\\\").rstrip("\\\\") + if here == prefix or here.startswith(prefix + "\\\\"): + return True + return False + + +def data_dir() -> Path:''' + +# ---------- 2. 用它 ---------- + +OLD_PICK = ''' beside = app_dir() / "data" + if _can_write(beside): + _DATA_DIR_CACHE = beside + return _DATA_DIR_CACHE + + # ProgramData:所有用户共用一份配置(换 Windows 账号也不丢) + base = os.environ.get("PROGRAMDATA") or r"C:\\ProgramData" + common = Path(base) / "ykxmz" / "data" + if _can_write(common): + _DATA_DIR_CACHE = common + return _DATA_DIR_CACHE''' + +NEW_PICK = ''' # ── 安装版(装在 Program Files)一律用 ProgramData ── + # 不能按"我能不能写 exe 旁边"来判断: + # 安装时是管理员跑的,写得进去;之后普通用户跑就写不进去, + # 于是悄悄换了目录 —— 安装时设的配对码就找不着了(实测踩过)。 + # 按"装在哪"判断,管理员和普通用户看到的就是同一份配置。 + in_program_files = _is_installed_copy() + + beside = app_dir() / "data" + if not in_program_files and _can_write(beside): + _DATA_DIR_CACHE = beside + return _DATA_DIR_CACHE + + # ProgramData:所有用户共用一份配置(换 Windows 账号也不丢) + base = os.environ.get("PROGRAMDATA") or r"C:\\ProgramData" + common = Path(base) / "ykxmz" / "data" + if _can_write(common): + _DATA_DIR_CACHE = common + return _DATA_DIR_CACHE''' + + +def main() -> int: + text = CONFIG.read_text(encoding="utf-8") + ok = True + + if "_is_installed_copy" in text: + print(" 已经改过") + return 0 + + for old, new, label in ((OLD_MARK, NEW_MARK, "加 _is_installed_copy"), + (OLD_PICK, NEW_PICK, "数据目录改成确定性判断")): + if old not in text: + print(f" [失败] {label} —— 锚点没找到") + ok = False + continue + text = text.replace(old, new, 1) + print(f" {label}") + + if not ok: + return 1 + + CONFIG.write_text(text, encoding="utf-8", newline="\n") + try: + ast.parse(text) + print(" config.py 语法 OK") + except SyntaxError as exc: + print(f" 语法错误: 行 {exc.lineno}: {exc.msg}") + return 1 + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/_build/fix_programdata_perm.py b/_build/fix_programdata_perm.py new file mode 100644 index 0000000..dfcbb0c --- /dev/null +++ b/_build/fix_programdata_perm.py @@ -0,0 +1,207 @@ +# -*- coding: utf-8 -*- +r"""修 ProgramData 权限问题(用户装完报 WinError 5 拒绝访问)。 + +现象: + PermissionError: [WinError 5] 拒绝访问。 + 'C:\ProgramData\_ykxmz_test\data\settings.json.tmp' -> + 'C:\ProgramData\_ykxmz_test\data\settings.json' + +原因(Windows 的老规矩,不是 bug): + 安装包是**管理员**跑的,它在 ProgramData 下建的 settings.json + 属主是管理员。之后普通用户跑被控端时: + * 能**新建**文件(ProgramData 默认允许 Users 新建) + * 但**不能覆盖/改名**别人建的文件(os.replace 要删目标) + 于是"写 .tmp -> 原子替换"这一步就炸了。 + +而我原来的 _can_write() 只测了"能不能建文件",没有测**替换**, +所以误判成可写,跑到一半才报错。 + +三层修: + ① _write() 替换失败就降级:直接写目标文件 -> 再不行去掉只读位 + ② _can_write() 改成测完整周期(建 -> 改名 -> 删) + ③ 目录选择:ProgramData 不行就退到 LOCALAPPDATA(每人一份,永远可写) + ④ 安装包给数据目录授权 users-modify(治本) +""" +from __future__ import annotations + +import ast +import sys +from pathlib import Path + +CONFIG = (Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote\windows" + r"\lanremote\config.py")) + +# ---------------- ① 写入降级 ---------------- + +OLD_WRITE = ''' @staticmethod + def _write(path: Path, data) -> None: + tmp = path.with_suffix(path.suffix + ".tmp") + with open(tmp, "w", encoding="utf-8") as fh: + json.dump(data, fh, ensure_ascii=False, indent=2) + os.replace(tmp, path)''' + +NEW_WRITE = ''' @staticmethod + def _write(path: Path, data) -> None: + """写 JSON。优先"临时文件 + 原子替换",失败就降级。 + + 为什么要降级: + 装到 Program Files / ProgramData 时,配置是**管理员**建的那一份, + 属主是管理员。普通用户跑的时候: + 能新建文件,但不能覆盖/改名别人建的文件。 + 于是 os.replace 报 WinError 5。 + 这时候退成"直接写目标文件" —— 牺牲原子性,换能存下配置。 + """ + tmp = path.with_suffix(path.suffix + ".tmp") + payload = json.dumps(data, ensure_ascii=False, indent=2) + + # 1) 正常路径:临时文件 + 原子替换 + try: + with open(tmp, "w", encoding="utf-8") as fh: + fh.write(payload) + os.replace(tmp, path) + return + except OSError: + pass + + # 2) 降级:直接覆盖目标文件 + try: + with open(path, "w", encoding="utf-8") as fh: + fh.write(payload) + Store._cleanup(tmp) + return + except OSError: + pass + + # 3) 再降级:目标被设成只读就摘掉只读位再写 + try: + os.chmod(path, 0o666) + except OSError: + pass + try: + with open(path, "w", encoding="utf-8") as fh: + fh.write(payload) + Store._cleanup(tmp) + return + except OSError: + Store._cleanup(tmp) + raise + + @staticmethod + def _cleanup(tmp: Path) -> None: + try: + if tmp.exists(): + tmp.unlink() + except OSError: + pass''' + +# ---------------- ② 可写检测测完整周期 ---------------- + +OLD_CANWRITE = '''def _can_write(folder: Path) -> bool: + """这个目录能不能写(不存在就先建)。""" + try: + folder.mkdir(parents=True, exist_ok=True) + probe = folder / ".write-test" + probe.write_text("x", encoding="utf-8") + probe.unlink() + return True + except OSError: + return False''' + +NEW_CANWRITE = '''def _can_write(folder: Path) -> bool: + """这个目录能不能**真正**用来存配置。 + + 注意不能只测"能新建文件" —— 那只过一半。 + 实际写配置用的是"临时文件 + 原子替换"(os.replace), + 它需要**覆盖已存在文件**的权限。 + 装到 ProgramData 时,管理员建的那份普通用户改不了, + 只测新建会误判成可写,然后跑起来才报 WinError 5。 + 所以这里把整个周期都跑一遍:建 -> 改名覆盖 -> 删。 + """ + try: + folder.mkdir(parents=True, exist_ok=True) + probe = folder / ".write-test" + probe.write_text("x", encoding="utf-8") + + # 关键:模拟真实写入的"替换"这一步 + target = folder / ".write-test-target" + try: + if target.exists(): + target.unlink() + probe.write_text("a", encoding="utf-8") + os.replace(probe, target) # <- 真正的门槛在这 + target.write_text("b", encoding="utf-8") # 覆盖已存在的 + target.unlink() + except OSError: + # 建得了新文件但替换不了 -> 不能当数据目录 + try: + probe.unlink() + except OSError: + pass + return False + return True + except OSError: + return False''' + +# ---------------- ③ 目录选择加 LOCALAPPDATA 兜底 ---------------- + +OLD_DIR = ''' base = os.environ.get("PROGRAMDATA") or r"C:\\ProgramData" + common = Path(base) / "ykxmz" / "data" + try: + common.mkdir(parents=True, exist_ok=True) + except OSError: + # 兜底:连 ProgramData 都写不了(极罕见),退回用户目录 + common = (Path(os.environ.get("LOCALAPPDATA") + or Path.home()) / "ykxmz" / "data") + common.mkdir(parents=True, exist_ok=True) + _DATA_DIR_CACHE = common + return _DATA_DIR_CACHE''' + +NEW_DIR = ''' # ProgramData:所有用户共用一份配置(换 Windows 账号也不丢) + base = os.environ.get("PROGRAMDATA") or r"C:\\ProgramData" + common = Path(base) / "ykxmz" / "data" + if _can_write(common): + _DATA_DIR_CACHE = common + return _DATA_DIR_CACHE + + # 兜底:ProgramData 写不了(ACL 没配好 / 权限被收紧)就退到用户目录。 + # 每人一份配置,但**永远能写** —— 总比跑起来报错强。 + local = (Path(os.environ.get("LOCALAPPDATA") + or Path.home()) / "ykxmz" / "data") + local.mkdir(parents=True, exist_ok=True) + _DATA_DIR_CACHE = local + return _DATA_DIR_CACHE''' + + +def main() -> int: + text = CONFIG.read_text(encoding="utf-8") + ok = True + + if "_cleanup" in text: + print(" 已经改过") + return 0 + + for old, new, label in ((OLD_WRITE, NEW_WRITE, "写入降级"), + (OLD_CANWRITE, NEW_CANWRITE, "可写检测测完整周期"), + (OLD_DIR, NEW_DIR, "LOCALAPPDATA 兜底")): + if old not in text: + print(f" [失败] {label} —— 锚点没找到") + ok = False + continue + text = text.replace(old, new, 1) + print(f" {label}") + + if not ok: + return 1 + + CONFIG.write_text(text, encoding="utf-8", newline="\n") + try: + ast.parse(text) + print(" config.py 语法 OK") + except SyntaxError as exc: + print(f" 语法错误: 行 {exc.lineno}: {exc.msg}") + return 1 + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/_build/gitee_release.py b/_build/gitee_release.py index 8cef3a1..c88a001 100644 --- a/_build/gitee_release.py +++ b/_build/gitee_release.py @@ -79,8 +79,28 @@ def main() -> int: version = sys.argv[2] if len(sys.argv) > 2 else "1.6.0" tag = f"v{version}" + # 更新内容从哪来: + # 1) 命令行第三个参数(直接给一段话) + # 2) _build/CHANGELOG.md 里最新一节 + changelog = sys.argv[3] if len(sys.argv) > 3 else '' + if not changelog: + note = ROOT / "_build" / "CHANGELOG.md" + if note.is_file(): + text = note.read_text(encoding="utf-8") + blocks = [b.strip() for b in text.split(chr(10) + "## ") if b.strip()] + for b in blocks: + if b.startswith(version) or b.startswith("v" + version): + changelog = b + break + if not changelog and blocks: + changelog = blocks[0] + if not changelog: + changelog = f"版本 {version}" + + # 电脑端给**安装包**(不是 zip 了,用户要求); + # 服务器端给 zip;手表端直接给 APK。 files = [ - ROOT / "dist" / f"ykxmz-agent-{version}.zip", + ROOT / "dist" / f"ykxmz-setup-{version}.exe", ROOT / "dist" / f"ykxmz-server-{version}.zip", ROOT / "dist" / f"ykxmz-watch-{version}.apk", ] @@ -93,36 +113,14 @@ def main() -> int: print(f" 标签: {tag}") print() - # ---- 1. 建发行版 ---- - body = f"""## ykxmz {version} + # 发行版说明**只放更新内容**(用户要求)。 + # 不放下载表格、不放用法说明 —— 那些在 README 里, + # 这里堆一堆反而看不清这版改了什么。 + body = f"""## 更新内容 -教室电脑手表遥控。 - -老师抬一下手腕就能管教室里那台电脑 —— 放课件、放音频、投图、 -看看谁在打游戏、下课关机,不用走回讲台。 - -### 这次下载哪个 - -| 你是 | 下这个 | -|---|---| -| 教室电脑装被控端 | `ykxmz-agent-{version}.zip` | -| 要跨网络(办公室管教室) | `ykxmz-server-{version}.zip` | -| 手表装控制端 | `ykxmz-watch-{version}.apk` | - -只在一个教室用的话,第三件(中转服务器)可以先不装, -手表和电脑连同一个 WiFi 就能直连。 - -### 怎么用 - -装完看包里的 `README.txt`,或者仓库首页的说明。 - -### 这一版改了什么 - -- 重写说明文档,按老师 / 电教 / 开发者 / 普通用户分开讲 -- 手表端内置根证书,修部分手表连中转时的证书校验失败 -- 中转站加下载区 -- 网络稳定性:修 MTU 问题,公网可用率从 48% 提到 95% 以上 +{changelog} """ + print(" 建发行版…") try: status, reply = api( diff --git a/_build/pack_include_ico.py b/_build/pack_include_ico.py new file mode 100644 index 0000000..2e100c3 --- /dev/null +++ b/_build/pack_include_ico.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +r"""服务器端打包时带上 favicon.ico。 + +package_remote.py 原来只收 relay 目录下的 .py / .sh, +favicon.ico 会被漏掉 —— 结果装到新设备上管理页又没图标了。 +""" +from __future__ import annotations + +import ast +import sys +from pathlib import Path + +PKG = (Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote\_build" + r"\package_remote.py")) + +OLD = ''' wanted = sorted( + [f for f in RELAY_SRC.iterdir() + if f.suffix in (".py", ".sh") and f.is_file()], + key=lambda f: f.name)''' + +NEW = ''' # 后缀白名单:.py / .sh 是服务本体,.ico 是管理页图标。 + # 漏掉 .ico 的话,装到新设备上管理页又会变成没有图标的默认样式。 + wanted = sorted( + [f for f in RELAY_SRC.iterdir() + if f.suffix in (".py", ".sh", ".ico") and f.is_file()], + key=lambda f: f.name)''' + + +def main() -> int: + text = PKG.read_text(encoding="utf-8") + if '.sh", ".ico"' in text: + print(" 已经改过") + return 0 + if OLD not in text: + print(" [失败] 锚点没找到") + return 1 + + text = text.replace(OLD, NEW, 1) + PKG.write_text(text, encoding="utf-8", newline="\n") + print(" 服务器端打包现在会带上 .ico") + + try: + ast.parse(text) + print(" 语法 OK") + except SyntaxError as exc: + print(f" 语法错误: 行 {exc.lineno}: {exc.msg}") + return 1 + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/_build/package_remote.py b/_build/package_remote.py index ee992b0..6acdc2e 100644 --- a/_build/package_remote.py +++ b/_build/package_remote.py @@ -17,7 +17,7 @@ import zipfile from pathlib import Path ROOT = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote") -VERSION = "1.6.2" +VERSION = "1.7.0" NAME = f"ykxmz-{VERSION}" AGENT_SRC = ROOT / "dist_exe" / "ykxmz" @@ -482,9 +482,11 @@ def main() -> int: server_dir.mkdir(parents=True) # 文件清单写死容易漏 —— watchdog.sh / net-tune.sh 都漏过一次。 # 改成:relay 目录里所有 .py / .sh 都带上。 + # 后缀白名单:.py / .sh 是服务本体,.ico 是管理页图标。 + # 漏掉 .ico 的话,装到新设备上管理页又会变成没有图标的默认样式。 wanted = sorted( [f for f in RELAY_SRC.iterdir() - if f.suffix in (".py", ".sh") and f.is_file()], + if f.suffix in (".py", ".sh", ".ico") and f.is_file()], key=lambda f: f.name) for src in wanted: shutil.copy2(src, server_dir / src.name) diff --git a/_build/release.py b/_build/release.py index f7d02e3..492ad46 100644 --- a/_build/release.py +++ b/_build/release.py @@ -105,13 +105,22 @@ def main() -> int: print((proc.stderr or "")[-600:]) return 1 - # ---- 3. 打包 ---- - step(3, "打三个成品") + # ---- 3. 打成品 ---- + step(3, "打成品(安装包 + 服务器 zip + APK)") proc = sh([sys.executable, "_build/package_remote.py"]) - print(proc.stdout[-1400:]) + print(proc.stdout[-1200:]) if proc.returncode != 0: return 1 + # 电脑端对外发的是**安装包**,不是 zip + proc = sh([sys.executable, "installer/build_installer.py"], timeout=1800) + for line in (proc.stdout or "").splitlines(): + if "安装包" in line or "失败" in line: + print(f" {line.strip()}") + if proc.returncode != 0: + print((proc.stdout or "")[-1200:]) + return 1 + # ---- 4. 关键测试 ---- step(4, "跑关键测试") for test in ("audit_encoding.py", "test_net_tune.py", "test_chunked_body.py", @@ -128,7 +137,7 @@ def main() -> int: # 打包测试要起真的中转 + agent,前面刚跑过几个测试, # 偶尔会撞上端口/隧道还没恢复 —— 重试一次就好 ok_pkg = False - for attempt in range(2): + for attempt in range(3): proc = sh([sys.executable, "-u", "_tests/test_package_remote.py"], timeout=1800) out = proc.stdout or "" @@ -147,7 +156,7 @@ def main() -> int: "$_.CommandLine -match 'relay.py' } | " "ForEach-Object { Stop-Process -Id $_.ProcessId -Force " "-ErrorAction SilentlyContinue }"], timeout=120) - time.sleep(4) + time.sleep(8) if not ok_pkg: return 1 diff --git a/_build/switch_release_to_setup.py b/_build/switch_release_to_setup.py new file mode 100644 index 0000000..bf60d90 --- /dev/null +++ b/_build/switch_release_to_setup.py @@ -0,0 +1,109 @@ +# -*- coding: utf-8 -*- +r"""把"电脑端发 zip"改成"电脑端发安装包 exe"。 + +用户要求:发行版里电脑端要给**安装包**,不是 zip。 + +改两个地方: + _build/gitee_release.py 上传列表里 agent zip -> setup exe + _build/release.py 打包之后多跑一步编译安装包 +""" +from __future__ import annotations + +import ast +import re +import sys +from pathlib import Path + +ROOT = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote") +GITEE = ROOT / "_build" / "gitee_release.py" +RELEASE = ROOT / "_build" / "release.py" + +# ---------- 1. gitee_release.py 的上传列表 ---------- + +G_OLD = ''' files = [ + ROOT / "dist" / f"ykxmz-agent-{version}.zip", + ROOT / "dist" / f"ykxmz-server-{version}.zip", + ROOT / "dist" / f"ykxmz-watch-{version}.apk", + ]''' + +G_NEW = ''' # 电脑端给**安装包**(不是 zip 了,用户要求); + # 服务器端给 zip;手表端直接给 APK。 + files = [ + ROOT / "dist" / f"ykxmz-setup-{version}.exe", + ROOT / "dist" / f"ykxmz-server-{version}.zip", + ROOT / "dist" / f"ykxmz-watch-{version}.apk", + ]''' + +# ---------- 2. release.py 多编译一步安装包 ---------- + +R_OLD = ''' # ---- 3. 打包 ---- + step(3, "打三个成品") + proc = sh([sys.executable, "_build/package_remote.py"]) + print(proc.stdout[-1400:]) + if proc.returncode != 0: + return 1''' + +R_NEW = ''' # ---- 3. 打成品 ---- + step(3, "打成品(安装包 + 服务器 zip + APK)") + proc = sh([sys.executable, "_build/package_remote.py"]) + print(proc.stdout[-1200:]) + if proc.returncode != 0: + return 1 + + # 电脑端对外发的是**安装包**,不是 zip + proc = sh([sys.executable, "installer/build_installer.py"], timeout=1800) + for line in (proc.stdout or "").splitlines(): + if "安装包" in line or "失败" in line: + print(f" {line.strip()}") + if proc.returncode != 0: + print((proc.stdout or "")[-1200:]) + return 1''' + +R_OLD2 = ''' step(3, "打三个成品")''' +R_NEW2 = ''' step(3, "打成品(安装包 + 服务器 zip + APK)")''' + + +def patch(path: Path, pairs, label: str) -> bool: + text = path.read_text(encoding="utf-8") + changed = False + for old, new in pairs: + if new.strip() and new in text: + continue + if old not in text: + print(f" [提示] {path.name}: 找不到「{label}」的锚点(可能已改)") + continue + text = text.replace(old, new, 1) + changed = True + if changed: + path.write_text(text, encoding="utf-8", newline="\n") + print(f" {path.name}: 已更新") + else: + print(f" {path.name}: 无需改动") + try: + ast.parse(path.read_text(encoding="utf-8")) + except SyntaxError as exc: + print(f" [失败] {path.name} 语法错误: 行 {exc.lineno}: {exc.msg}") + return False + return True + + +def main() -> int: + ok = True + if not patch(GITEE, [(G_OLD, G_NEW)], "上传列表"): + ok = False + if not patch(RELEASE, [(R_OLD, R_NEW)], "打包步骤"): + ok = False + + print() + print(" 复核:") + g = GITEE.read_text(encoding="utf-8") + r = RELEASE.read_text(encoding="utf-8") + print(f" gitee_release.py 用 setup exe: " + f"{'✓' if 'ykxmz-setup-{version}.exe' in g else '✗'}") + print(f" release.py 会编译安装包: " + f"{'✓' if 'build_installer.py' in r else '✗'}") + return 0 if ok else 1 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/_build/sync_device_161.py b/_build/sync_device_161.py index faf36bf..850c1f9 100644 --- a/_build/sync_device_161.py +++ b/_build/sync_device_161.py @@ -1,7 +1,11 @@ # -*- coding: utf-8 -*- -r"""设备回来了:把 1.6.1 传到下载区,并部署最新 relay。""" +r"""设备回来了:把成品传到下载区,并部署最新 relay。 + +版本号从 _build/package_remote.py 里读,不用手改。 +""" from __future__ import annotations +import re import sys from pathlib import Path @@ -10,7 +14,14 @@ sys.path.insert(0, str(ROOT / "_build")) from devssh import run, upload # noqa: E402 -VER = "1.6.1" + +def current_version() -> str: + text = (ROOT / "_build" / "package_remote.py").read_text(encoding="utf-8") + match = re.search(r'VERSION\s*=\s*"([^"]+)"', text) + return match.group(1) if match else "0.0.0" + + +VER = current_version() REMOTE_DIR = "/root/lanremote-relay/downloads" UPLOADS = [ diff --git a/_build/test_install_fresh.ps1 b/_build/test_install_fresh.ps1 new file mode 100644 index 0000000..6a1016e --- /dev/null +++ b/_build/test_install_fresh.ps1 @@ -0,0 +1,84 @@ +# 全新安装验证:清干净 -> 装到默认路径 -> 跑一遍 -> 检查权限 +# 用法: powershell -NoProfile -ExecutionPolicy Bypass -File _build\test_install_fresh.ps1 + +$ErrorActionPreference = "Continue" +$root = "C:\Users\shu\Desktop\deepseekagent\LanRemote" +$setup = Join-Path $root "dist\ykxmz-setup-1.6.2.exe" +$appId = "{8F3C1D42-7A5E-4B91-9C6D-2E8F4A1B7C30}_is1" + +Write-Host "" +Write-Host "===== 1. 彻底清理上一次的安装 =====" -ForegroundColor Cyan +Get-Process ykxmz, unins000 -ErrorAction SilentlyContinue | + Stop-Process -Force -ErrorAction SilentlyContinue +Start-Sleep -Seconds 2 + +foreach ($dir in @("C:\Program Files\ykxmz", "C:\ProgramData\_ykxmz_test", + "C:\ProgramData\ykxmz")) { + if (Test-Path "$dir\unins000.exe") { + Start-Process "$dir\unins000.exe" ` + -ArgumentList "/VERYSILENT", "/SUPPRESSMSGBOXES" -Wait ` + -ErrorAction SilentlyContinue + Start-Sleep -Seconds 2 + } + Remove-Item $dir -Recurse -Force -ErrorAction SilentlyContinue +} +# 删掉 Inno 记住的目录,否则下次还会装到老地方 +foreach ($hive in @("HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", + "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall")) { + Remove-Item "$hive\$appId" -Recurse -Force -ErrorAction SilentlyContinue +} +Write-Host " 清理完成" + +Write-Host "" +Write-Host "===== 2. 全新安装(不带 /DIR,看默认去哪)=====" -ForegroundColor Cyan +$log = Join-Path $root "_build\install_fresh.log" +Remove-Item $log -Force -ErrorAction SilentlyContinue +$proc = Start-Process -FilePath $setup ` + -ArgumentList "/VERYSILENT", "/SUPPRESSMSGBOXES", "/NORESTART", + "/LOG=$log", "/CODE=654321" -PassThru -Wait +Write-Host " 安装 exit=$($proc.ExitCode)" + +Write-Host "" +Write-Host "===== 3. 安装位置 =====" -ForegroundColor Cyan +$exe = "C:\Program Files\ykxmz\ykxmz.exe" +Write-Host " $exe : $(Test-Path $exe)" +Write-Host " _internal : $((Get-ChildItem 'C:\Program Files\ykxmz\_internal' -ErrorAction SilentlyContinue | Measure-Object).Count) 项" +Write-Host " docs : $((Get-ChildItem 'C:\Program Files\ykxmz\docs' -ErrorAction SilentlyContinue | Measure-Object).Count) 个" + +Write-Host "" +Write-Host "===== 4. 数据目录权限 =====" -ForegroundColor Cyan +$dataDir = "C:\ProgramData\ykxmz\data" +if (Test-Path $dataDir) { + Write-Host " $dataDir 存在" + (Get-Acl $dataDir).Access | + Where-Object { $_.IdentityReference -match "Users|用户" } | + ForEach-Object { Write-Host " $($_.IdentityReference) : $($_.FileSystemRights)" } +} else { + Write-Host " $dataDir 不存在(还没运行过,正常)" +} + +Write-Host "" +Write-Host "===== 5. 跑起来(这一步以前报 WinError 5)=====" -ForegroundColor Cyan +if (Test-Path $exe) { + & $exe --status 2>&1 | + Select-String -Pattern "配对码|数据目录|开机自启" | + ForEach-Object { Write-Host " $($_.Line.Trim())" } + + Write-Host "" + Write-Host " 写一次配置(模拟实际运行):" + $out = & $exe --name "三年二班" 2>&1 + $out | ForEach-Object { Write-Host " $_" } + Write-Host " exit=$LASTEXITCODE" + + Write-Host "" + Write-Host " 再看状态:" + & $exe --status 2>&1 | + Select-String -Pattern "配对码|数据目录" | + ForEach-Object { Write-Host " $($_.Line.Trim())" } +} else { + Write-Host " ✗ 找不到 exe,安装失败了" -ForegroundColor Red + if (Test-Path $log) { + Get-Content $log -Encoding UTF8 | Select-Object -Last 15 | + ForEach-Object { Write-Host " $_" } + } +} diff --git a/_build/zip_project.py b/_build/zip_project.py new file mode 100644 index 0000000..f7f680f --- /dev/null +++ b/_build/zip_project.py @@ -0,0 +1,138 @@ +# -*- coding: utf-8 -*- +r"""把整个项目打成压缩包,交给用户。 + +包含:全部源码(三端 + 安装包脚本 + 测试 + 构建脚本)+ 三份文档 + + 已构建好的成品(安装包 / APK / 两个 zip) + +排除: + * .git 版本库(几十 MB,而且推上去过) + * dist_exe 40MB PyInstaller 产物,一条命令能重建 + * _build/pyinstaller_work 同上 + * __pycache__ / *.pyc + * _tests/out_* / _tests/received 测试临时数据 + * _build/jc* 编译中间产物 + * **_build/.gitee_token** ← Gitee 令牌,**绝对不能进包** +""" +from __future__ import annotations + +import re +import sys +import zipfile +from pathlib import Path + +ROOT = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote") +OUT = ROOT / "dist" / "ykxmz-项目完整源码.zip" + +# 目录级排除(按相对路径前缀) +EXCLUDE_DIRS = ( + ".git", + "dist_exe", + "_build/pyinstaller_work", + "_build/jc_all", + "_build/jc_tls", + "_build/jc_tls2", + "_build/jc_v15", + "_build/out_java", + "_build/out_app", + "_tests/out_java", + "_tests/out_app", + "_tests/received", + "_tests/_stubdata", + "_tests/shots", + "__pycache__", + "android/build", + "android/gen", + "android/bin", + "windows/data", +) + +# 文件名级排除 +EXCLUDE_NAMES = { + ".gitee_token", + "Thumbs.db", + "desktop.ini", + ".DS_Store", +} + +# 后缀级排除 +EXCLUDE_SUFFIXES = ( + ".pyc", ".pyo", ".pyd", + ".log", ".tmp", ".toc", ".pyz", ".pkg", + ".bak", ".orig", +) + +# 要打进去的顶层条目(只打这些,别的一律不要) +INCLUDE_TOP = ( + "windows", "android", "relay", "installer", "docs", "tools", + "_tests", "_build", + "README.md", "LICENSE.md", ".gitignore", + "diag", "dist", +) + +# dist 里只带上成品,别把中间目录带进去 +DIST_KEEP = (".exe", ".apk", ".zip", ".idsig", ".txt") + + +def excluded(rel: str, path: Path) -> bool: + rel_posix = rel.replace("\\", "/") + for prefix in EXCLUDE_DIRS: + if rel_posix == prefix or rel_posix.startswith(prefix + "/"): + return True + if path.name in EXCLUDE_NAMES: + return True + if path.suffix.lower() in EXCLUDE_SUFFIXES: + return True + # dist 目录只留成品 + if rel_posix.startswith("dist/"): + if path.is_file() and not path.name.lower().endswith(DIST_KEEP): + return True + if rel_posix == "dist" and path.is_dir(): + return False + return False + + +def main() -> int: + if OUT.exists(): + OUT.unlink() + OUT.parent.mkdir(parents=True, exist_ok=True) + + count = 0 + total = 0 + skipped_token = False + + with zipfile.ZipFile(OUT, "w", zipfile.ZIP_DEFLATED, + compresslevel=6) as archive: + for top in INCLUDE_TOP: + root = ROOT / top + if not root.exists(): + print(f" [跳过] 没有 {top}") + continue + + if root.is_file(): + archive.write(root, f"ykxmz/{top}") + count += 1 + total += root.stat().st_size + continue + + for path in sorted(root.rglob("*")): + rel = str(path.relative_to(ROOT)) + if excluded(rel, path): + if path.name == ".gitee_token": + skipped_token = True + continue + if path.is_dir(): + continue + archive.write(path, f"ykxmz/{rel.replace(chr(92), '/')}") + count += 1 + total += path.stat().st_size + + size = OUT.stat().st_size / 1024 / 1024 + print(f" ✓ {OUT.name}") + print(f" {count} 个文件,原始 {total / 1024 / 1024:.1f} MB," + f"压缩后 {size:.1f} MB") + print(f" Gitee 令牌已排除: {skipped_token or '(本来就没扫到)'}") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/_tests/test_apk_contents.py b/_tests/test_apk_contents.py index af1feda..c5504cc 100644 --- a/_tests/test_apk_contents.py +++ b/_tests/test_apk_contents.py @@ -23,7 +23,7 @@ def _latest_apk() -> Path: (ROOT / "dist").glob("*watch*.apk"), key=lambda p: p.stat().st_mtime, reverse=True) return candidates[0] if candidates else \ - ROOT / "dist" / "ykxmz-watch-1.6.2.apk" + ROOT / "dist" / "ykxmz-watch-1.7.0.apk" APK = _latest_apk() diff --git a/_tests/test_package_remote.py b/_tests/test_package_remote.py index c0515cb..597c481 100644 --- a/_tests/test_package_remote.py +++ b/_tests/test_package_remote.py @@ -26,9 +26,9 @@ ROOT = Path(__file__).resolve().parent.parent # 被控端 -> 一个 zip # 服务器端 -> 一个 zip # 控制端 -> 直接给 APK(不打 zip) -AGENT_ZIP = ROOT / "dist" / "ykxmz-agent-1.6.2.zip" -SERVER_ZIP = ROOT / "dist" / "ykxmz-server-1.6.2.zip" -WATCH_APK = ROOT / "dist" / "ykxmz-watch-1.6.2.apk" +AGENT_ZIP = ROOT / "dist" / "ykxmz-agent-1.7.0.zip" +SERVER_ZIP = ROOT / "dist" / "ykxmz-server-1.7.0.zip" +WATCH_APK = ROOT / "dist" / "ykxmz-watch-1.7.0.apk" TOOLCHAIN = Path(r"C:\Users\shu\Desktop\deepseekagent\starklink\toolchain") JAVAC = TOOLCHAIN / "jdk17" / "bin" / "javac.exe" JAVA = TOOLCHAIN / "jdk17" / "bin" / "java.exe" @@ -89,7 +89,7 @@ def main() -> int: for label, path in (("被控端", agent_dir / "README-agent.txt"), ("服务器端", relay_dir / "README-server.txt"), ("控制端(旁边那份)", - ROOT / "dist" / "ykxmz-watch-1.6.2-说明.txt")): + ROOT / "dist" / "ykxmz-watch-1.7.0-说明.txt")): raw = path.read_bytes() if path.is_file() else b"" check(f"{label}说明有 UTF-8 BOM", raw[:3] == b"\xef\xbb\xbf", raw[:3]) diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 7c75340..400dd30 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -2,7 +2,7 @@ + android:versionName="1.7.0"> diff --git a/android/build_apk.ps1 b/android/build_apk.ps1 index a924b63..795ef68 100644 --- a/android/build_apk.ps1 +++ b/android/build_apk.ps1 @@ -27,7 +27,7 @@ $d8 = Join-Path $bt "d8.bat" $work = Join-Path $android "build" $outDir = Join-Path $root "dist" -$apkName = "ykxmz-watch-1.6.2.apk" +$apkName = "ykxmz-watch-1.7.0.apk" function Step($text) { Write-Host "`n=== $text ===" -ForegroundColor Cyan } @@ -65,7 +65,7 @@ $unsigned = Join-Path $work "app-unsigned.apk" --min-sdk-version 24 ` --target-sdk-version 34 ` --version-code 5 ` - --version-name "1.6.2" ` + --version-name "1.7.0" ` --auto-add-overlay if ($LASTEXITCODE -ne 0) { throw "aapt2 link 失败" } diff --git a/docs/AFTER-INSTALL.txt b/docs/AFTER-INSTALL.txt index 21d47e2..e228580 100644 --- a/docs/AFTER-INSTALL.txt +++ b/docs/AFTER-INSTALL.txt @@ -3,7 +3,7 @@ ======================================================== 软件名称:ykxmz -版本:1.6.2 +版本:1.7.0 作者:小麦子 装好之后看这一页:怎么确认它在跑、怎么改设置、 @@ -197,7 +197,7 @@ 八、版本记录 -------------------------------------------------------- - 1.6.2 + 1.7.0 * 跨网络支持:Cloudflare 具名隧道,固定域名 * 中转服务器:单设备单配对码、管理页可删设备 * 手表端:自动判断局域网/中转并无缝切换 @@ -209,6 +209,6 @@ -------------------------------------------------------- 作者:小麦子 - 软件:ykxmz 1.6.2 + 软件:ykxmz 1.7.0 许可条款见《许可协议》(LICENSE.txt) -------------------------------------------------------- diff --git a/docs/BEFORE-INSTALL.txt b/docs/BEFORE-INSTALL.txt index ddb0cb9..7d5c994 100644 --- a/docs/BEFORE-INSTALL.txt +++ b/docs/BEFORE-INSTALL.txt @@ -3,7 +3,7 @@ ======================================================== 软件名称:ykxmz -版本:1.6.2 +版本:1.7.0 作者:小麦子 请你**在安装之前**花三分钟读完这一页。里面有几条很要紧的 @@ -152,6 +152,6 @@ ykxmz 是一套自己搭建的远程管理工具,由三部分组成: -------------------------------------------------------- 作者:小麦子 - 软件:ykxmz 1.6.2 + 软件:ykxmz 1.7.0 继续安装,即表示你已阅读并同意《许可协议》。 -------------------------------------------------------- diff --git a/docs/LICENSE.txt b/docs/LICENSE.txt index 6b08412..ee42497 100644 --- a/docs/LICENSE.txt +++ b/docs/LICENSE.txt @@ -3,7 +3,7 @@ ======================================================== 软件名称:ykxmz(远程管理工具) -版本:1.6.2 +版本:1.7.0 作者:小麦子 生效日期:2026 年 10 月 5 日 @@ -150,7 +150,7 @@ -------------------------------------------------------- 作者:小麦子 - 软件:ykxmz 1.6.2 + 软件:ykxmz 1.7.0 如果你不同意本协议的任何一条,请不要安装或使用本软件。 -------------------------------------------------------- diff --git a/installer/build_installer.py b/installer/build_installer.py new file mode 100644 index 0000000..4f35972 --- /dev/null +++ b/installer/build_installer.py @@ -0,0 +1,113 @@ +# -*- coding: utf-8 -*- +r"""编译 Inno Setup 安装包。 + +做三件事: + 1. 把三份文档合并成 license-combined.txt(Inno 的 LicenseFile 只认一个文件) + 2. 把 .iss 里的版本号同步成当前版本 + 3. 调 ISCC.exe 编译 +""" +from __future__ import annotations + +import re +import subprocess +import sys +from pathlib import Path + +ROOT = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote") +INSTALLER = ROOT / "installer" +ISS = INSTALLER / "ykxmz.iss" +COMBINED = INSTALLER / "license-combined.txt" +ISCC = Path(r"C:\Program Files (x86)\Inno Setup 6\ISCC.exe") + +DOCS = ("LICENSE.txt", "BEFORE-INSTALL.txt", "AFTER-INSTALL.txt") + + +def current_version() -> str: + text = (ROOT / "_build" / "package_remote.py").read_text(encoding="utf-8") + match = re.search(r'VERSION\s*=\s*"([^"]+)"', text) + return match.group(1) if match else "0.0.0" + + +def build_license() -> None: + """三份文档拼成一份,给 Inno 的许可页用。 + + 每份之间加分隔线,免得读起来像一份文档。 + """ + parts = [] + for index, name in enumerate(DOCS): + path = ROOT / "docs" / name + if not path.is_file(): + print(f" [警告] 缺少 {name}") + continue + text = path.read_text(encoding="utf-8-sig").strip() + if index: + parts.append("") + parts.append("=" * 70) + parts.append("") + parts.append(text) + body = "\n".join(parts) + "\n" + + # 装许可页的正文要 UTF-8 **带 BOM**,否则 Inno 在中文系统上会显示乱码 + COMBINED.write_bytes(b"\xef\xbb\xbf" + body.encode("utf-8")) + print(f" 合并三份文档 -> {COMBINED.name}({len(body)} 字符)") + + +def sync_version(version: str) -> None: + text = ISS.read_text(encoding="utf-8") + new = re.sub(r'#define MyAppVersion "[^"]*"', + f'#define MyAppVersion "{version}"', text) + if new != text: + ISS.write_text(new, encoding="utf-8", newline="\r\n") + print(f" .iss 版本号 -> {version}") + else: + print(f" .iss 版本号已经是 {version}") + + +def main() -> int: + if not ISCC.is_file(): + print(f" [失败] 找不到 Inno Setup: {ISCC}") + return 1 + + version = current_version() + print(f" 编译 ykxmz 安装包 v{version}") + print() + + build_license() + sync_version(version) + + agent = ROOT / "dist_exe" / "ykxmz" / "ykxmz.exe" + if not agent.is_file(): + print(f" [失败] 被控端还没构建:{agent}") + print(" 先跑 windows\\build_exe.ps1") + return 1 + + print() + print(" 调 ISCC 编译…") + proc = subprocess.run([str(ISCC), str(ISS)], + capture_output=True, text=True, + encoding="utf-8", errors="replace", timeout=1800) + out = (proc.stdout or "") + (proc.stderr or "") + for line in out.splitlines(): + line = line.strip() + if line and ("Error" in line or "error" in line + or "Successful" in line or "compil" in line.lower() + or "warning" in line.lower()): + print(f" {line}") + + if proc.returncode != 0: + print(f" [失败] ISCC 退出码 {proc.returncode}") + print(out[-1500:]) + return 1 + + exe = ROOT / "dist" / f"ykxmz-setup-{version}.exe" + if not exe.is_file(): + print(f" [失败] 没生成 {exe}") + return 1 + size = exe.stat().st_size / 1024 / 1024 + print() + print(f" ✓ 安装包: {exe.name} {size:.2f} MB") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/installer/license-combined.txt b/installer/license-combined.txt new file mode 100644 index 0000000..15b17bd --- /dev/null +++ b/installer/license-combined.txt @@ -0,0 +1,533 @@ +======================================================== + ykxmz 软件许可协议 +======================================================== + +软件名称:ykxmz(远程管理工具) +版本:1.7.0 +作者:小麦子 +生效日期:2026 年 10 月 5 日 + + +-------------------------------------------------------- +第一条 协议的范围 +-------------------------------------------------------- + +本协议是你(以下称"使用者")与作者小麦子之间就 ykxmz 软件 +(含被控端程序、中转服务器程序、手表端应用及相关文档, +以下统称"本软件")达成的许可使用协议。 + +下载、安装、复制或以任何方式使用本软件,即表示你已阅读、 +理解并同意本协议全部条款。如不同意,请不要安装或使用。 + + +-------------------------------------------------------- +第二条 授权范围 +-------------------------------------------------------- + +在遵守本协议的前提下,作者授予你一项免费的、非独占的、 +不可转让的使用许可,你可以: + + 1. 在**你自己拥有或已获得明确授权**的设备上安装和使用本软件; + 2. 复制并分发本软件的完整副本(须保持文件完整、不得修改、 + 不得去除本协议与作者署名); + 3. 在教室、机房、家庭等场景中,用于管理**你负责管理**的设备。 + +本软件免费使用,作者不收取任何费用。 + + +-------------------------------------------------------- +第三条 【重要】使用红线 +-------------------------------------------------------- + +本软件是一套远程控制工具,被控端可以被远程操作屏幕、文件、 +音量、电源等。正因为能力较强,以下行为**严格禁止**: + + 1. **禁止**在未经设备所有者或管理者明确同意的情况下, + 在他人的电脑、手机、平板上安装被控端; + + 2. **禁止**用于偷窥、跟踪、监视他人(包括配偶、家人、 + 同事、同学、下属)的隐私; + + 3. **禁止**用于窃取账号密码、聊天记录、照片、文件等 + 任何个人信息; + + 4. **禁止**将本软件伪装成系统组件、隐藏其存在、 + 故意使设备使用者无法发现或无法卸载; + + 5. **禁止**用于任何违反所在地法律法规的活动。 + +**一句话:只能管你自己的设备,或者别人明确同意你管的设备。** + +违反上述任何一条,本协议立即终止,且由此产生的全部法律 +责任由使用者自行承担,与作者无关。 + + +-------------------------------------------------------- +第四条 使用者应尽的通知义务 +-------------------------------------------------------- + +如果你在被控端所在的设备上使用本软件,你有义务确保: + + 1. 该设备的使用者知道这台设备可以被远程管理; + 2. 该设备的使用者知道如何查看、关闭或卸载本软件; + 3. 被控端保持"连接时可见提示"功能开启(默认开启)。 + + +-------------------------------------------------------- +第五条 隐私说明 +-------------------------------------------------------- + +本软件的设计原则是**数据不经过作者的服务器**: + + 1. 被控端与手表/控制端之间的所有数据(画面、文件、剪贴板、 + 语音等)通过你自己部署的中转服务器或局域网直连传输, + 作者**不会**收到、存储或分析任何内容; + + 2. 中转服务器只转发加密连接中的字节流,不解析内容; + 它记录的信息仅限于:设备名称、配对码、在线状态、 + 流量大小、连接时间——用于你在管理页上查看自己的设备; + + 3. 中转服务器部署在**你自己的设备**上,数据存在你自己的 + 硬盘里,作者无法访问; + + 4. 本软件不包含任何统计上报、行为采集、广告推送代码。 + +关于本软件需要使用的权限(网络访问、屏幕读取、文件读写等), +详见《安装前必读》。 + + +-------------------------------------------------------- +第六条 无担保声明 +-------------------------------------------------------- + +本软件按"现状"提供,作者不对以下事项作出任何明示或默示的 +担保,包括但不限于: + + 1. 软件无错误、不中断、能满足你的特定用途; + 2. 与你的操作系统、杀毒软件、网络环境完全兼容; + 3. 因网络运营商限制、Cloudflare 服务调整、系统更新等 + 外部原因导致的服务不可用。 + +**使用本软件的风险由你自行承担。** + + +-------------------------------------------------------- +第七条 责任限制 +-------------------------------------------------------- + +在适用法律允许的最大范围内,作者不对因使用或无法使用本软件 +而产生的任何直接、间接、偶然、特殊或后果性损失负责,包括 +但不限于数据丢失、业务中断、设备损坏、利润损失。 + +若适用法律不允许完全排除责任,作者承担的责任总额不超过 +你为获得本软件所支付的费用(本软件免费,故为零)。 + + +-------------------------------------------------------- +第八条 协议终止 +-------------------------------------------------------- + +出现下列情形之一,本协议自动终止: + + 1. 你违反本协议任何条款; + 2. 你将本软件用于第三条约定的禁止用途。 + +协议终止后,你应当立即停止使用并卸载本软件。第二条授予的 +分发许可同时失效。 + + +-------------------------------------------------------- +第九条 其他 +-------------------------------------------------------- + + 1. 本协议适用中华人民共和国法律; + 2. 因本协议产生的争议,双方应友好协商解决;协商不成的, + 提交作者所在地有管辖权的人民法院; + 3. 作者保留在后续版本中调整本协议的权利,调整后的协议 + 随新版本一同发布;继续使用新版本即视为接受新协议; + 4. 本协议部分条款无效,不影响其余条款的效力。 + + +-------------------------------------------------------- + 作者:小麦子 + 软件:ykxmz 1.7.0 + + 如果你不同意本协议的任何一条,请不要安装或使用本软件。 +-------------------------------------------------------- + +====================================================================== + +======================================================== + ykxmz 安装前必读(前信息文件) +======================================================== + +软件名称:ykxmz +版本:1.7.0 +作者:小麦子 + +请你**在安装之前**花三分钟读完这一页。里面有几条很要紧的 +提醒,尤其是第三节和第五节。 + + +-------------------------------------------------------- +一、这是什么 +-------------------------------------------------------- + +ykxmz 是一套自己搭建的远程管理工具,由三部分组成: + + 1-agent(被控端) 装在你**要管理**的电脑上(Windows) + 2-server(服务器端)装在一台能上外网的 Linux 小机器上 + (随身 WiFi、树莓派、VPS 都行) + 3-watch(控制端) 装在你的安卓手表上 + +装好之后,你在手表上就能看到并操作那台电脑:屏幕、文件、 +音量、电源、剪贴板……共两百多个功能。 + +**关键点:所有数据都走你自己搭的那台服务器, +作者碰不到你的任何内容。** 详见《许可协议》第五条。 + + +-------------------------------------------------------- +二、装机前对照检查 +-------------------------------------------------------- + +请先确认: + + [ ] 这台电脑是**你自己的**,或者设备主人明确同意你远程管理 + [ ] 电脑是 Windows 10 / 11(64 位) + [ ] 手表是安卓 9.0(API 28)或更高版本 + [ ] 服务器端那台机器是 Linux(Debian 12 实测通过), + 能上外网,内存 512MB 够用 + [ ] 你有一个 Cloudflare 账号和一个域名(跨网络才需要) + +**不需要**装 Python、不需要 root、不需要 ADB。 + + +-------------------------------------------------------- +三、【重要】三条必须知道的事 +-------------------------------------------------------- + +① 被控端默认是"静默"运行的 + + 装完之后**没有窗口、没有托盘图标、没有终端**, + 任务管理器里能看到一个叫 ykxmz.exe 的进程, + 开机自启项里也显示 ykxmz。 + + 这么做是为了不打扰用电脑的人,**不是**为了藏起来。 + 如果你要在这台电脑上装给别人用,你有义务告诉对方: + + 怎么查看(任务管理器 -> 详细信息 -> ykxmz.exe) + 怎么关闭(任务管理器 -> 结束任务) + 怎么卸载(ykxmz.exe --uninstall) + +② 配对码是唯一的口令,请设一个别人猜不到的 + + 配对码是 6 位数字,**它就是你电脑的钥匙**。 + 不要用 123456、000000、生日、手机号后六位这类。 + + 一个配对码同时只能绑定一台电脑。如果别人先用了你想要的码, + 后装的这台会被拒绝,并在屏幕上弹出提示: + 「该配对码已被使用,请换一个配对码」 + 换个没人用的码就行。 + +③ 连接时屏幕上有提示 + + 只要手表或控制端连上来,被控端会在屏幕右下角弹一个提示。 + 这是**故意保留**的功能,请不要关掉它—— + 它保证了设备使用者知道"现在有人在看这台电脑"。 + + +-------------------------------------------------------- +四、安装顺序 +-------------------------------------------------------- + +按这个顺序来,别跳: + + 第 1 步 架服务器端(只做一次) + 把 2-server 整个目录拷到随身 WiFi 上,执行: + bash install.sh + 它会装好中转服务 + Cloudflare 隧道,并打印一个 + 公网地址。 + + 第 2 步 装被控端(每台要管理的电脑做一次) + 双击 ykxmz.exe -> 输 6 位配对码 -> 勾上开机自启和 + 放行防火墙 -> 确定。会弹一次管理员确认。 + + 第 3 步 装控制端 + 把 3-watch 里的 APK 装到手表上。装完打开就能用, + 地址已经内置好了。 + + +-------------------------------------------------------- +五、会改你系统的哪些东西 +-------------------------------------------------------- + +安装和使用过程中,被控端会做这些改动,**请你知情**: + + 1. 写一条开机自启项 + 位置:HKEY_CURRENT_USER\...\CurrentVersion\Run + 名称:ykxmz + 内容:"...\ykxmz.exe" --silent + + 2. 添加 Windows 防火墙放行规则 + 规则名:LAN Remote TCP / LAN Remote UDP / LAN Remote App TCP + / LAN Remote App UDP + 作用:允许 8765(TCP)和 8766(UDP)端口通信 + + 3. 在程序目录下建一个 data 子目录 + 里面存:配对码、已配对设备、设置 + 卸载时会一并删除 + + 4. 说明:部分功能(关机、改注册表、隐藏任务栏等) + 需要管理员权限,会弹 UAC 确认,**不会**偷偷提权。 + +**以上全部可撤销**:卸载时自启项和防火墙规则会一起清掉。 + + +-------------------------------------------------------- +六、杀毒软件可能报警 +-------------------------------------------------------- + +本软件没有购买代码签名证书(那是要花钱的), +加上它确实具备"远程控制 + 开机自启"这类能力, +所以**部分杀毒软件可能会报可疑**。 + +这是误报。你可以: + 1. 在杀毒软件里把 ykxmz 整个目录加入信任/排除项; + 2. 或者先看完《许可协议》,确认用途正当后再决定是否放行。 + +**作者不会、也没有办法让本软件绕过杀毒软件。** +如果你需要"绝对不被杀软发现",那本软件不适合你。 + + +-------------------------------------------------------- +七、接下来看什么 +-------------------------------------------------------- + +装完之后请看《安装后须知》(AFTER-INSTALL.txt), +里面有:怎么确认它在正常运行、怎么换配对码、 +怎么彻底卸载、连不上怎么排查。 + + +-------------------------------------------------------- + 作者:小麦子 + 软件:ykxmz 1.7.0 + 继续安装,即表示你已阅读并同意《许可协议》。 +-------------------------------------------------------- + +====================================================================== + +======================================================== + ykxmz 安装后须知(后信息文件) +======================================================== + +软件名称:ykxmz +版本:1.7.0 +作者:小麦子 + +装好之后看这一页:怎么确认它在跑、怎么改设置、 +怎么彻底卸载、出问题怎么查。 + + +-------------------------------------------------------- +一、确认它真的在运行 +-------------------------------------------------------- + +被控端装好后**看不到任何窗口**,这是正常的。想确认它在跑: + + 方法一(最直观) + Ctrl+Shift+Esc 打开任务管理器 + -> "详细信息"标签 -> 找 ykxmz.exe + 有,就是在跑 + + 方法二(看端口) + 命令行执行: netstat -ano | findstr 8765 + 有 LISTENING,就是正常 + + 方法三(问程序自己) + 命令行执行: ykxmz.exe --status + 会打印:配对码、端口、中转连接状态、已配对设备数 + + 方法四(从手表看) + 手表上点"自动连接",能连上就说明在跑 + + +-------------------------------------------------------- +二、常用操作 +-------------------------------------------------------- + +重新打开设置窗口 + ykxmz.exe --setup + +换一个配对码 + 在设置窗口里改,或者: + ykxmz.exe --new-code (随机生成一个) + 换完之后,手表那边要用新码重连 + +看看当前状态 + ykxmz.exe --status + +临时允许新设备配对(默认关着) + ykxmz.exe --add-device 10 (开放 10 分钟) + 过了时间自动关回去 + +关掉/打开开机自启 + ykxmz.exe --autostart off + ykxmz.exe --autostart on + +网络自检(连不上时先跑这个) + 双击 wlzj.bat + 或 ykxmz.exe --netcheck 90 + +修复防火墙(要管理员) + 右键 xffhq.bat -> 以管理员身份运行 + 或 ykxmz.exe --fix-firewall + + +-------------------------------------------------------- +三、彻底卸载 +-------------------------------------------------------- + +一条命令清干净: + + ykxmz.exe --uninstall + +它会依次: + 1. 停掉正在跑的进程 + 2. 删掉开机自启项 + 3. 删掉数据目录(配对码、已配对手表全没了) + 4. 安排删除程序目录本身(退出后几秒自动删) + +**想保留数据**(比如以后还要用,只是换个位置装): + 先手动把 data 目录复制出来,再卸载。 + +**手动卸载也可以**(如果程序已经删了): + 1. 任务管理器结束 ykxmz.exe + 2. 删除注册表项 + HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run + 下的 ykxmz + 3. 删除整个程序目录 + 4. (可选)删除防火墙规则:netsh advfirewall firewall + delete rule name="LAN Remote TCP" + + +-------------------------------------------------------- +四、连不上怎么查 +-------------------------------------------------------- + +按顺序排查,绝大多数问题在前三步就解决了: + + 第 1 步 被控端在跑吗? + 任务管理器里有没有 ykxmz.exe + 没有 -> ykxmz.exe --setup + + 第 2 步 防火墙放行了吗? + 右键 xffhq.bat -> 以管理员身份运行 + + 第 3 步 网络通不通? + 双击 wlzj.bat 做自检 + 它会生成一份《网络自检结果.txt》 + + 第 4 步 跨网络的话,中转通不通? + 浏览器打开 http://<随身WiFi的IP>:8080/url + 看它有没有返回公网地址 + + 第 5 步 手表上点"连不上?点这里诊断" + + 常见现象对照: + + "连接失败,配对码错误" + -> 手表上的码和电脑上的不一样,对一下 + + "该配对码已被使用,请换一个配对码" + -> 这个码被另一台电脑占了。换一个, + 或者去中转管理页把占用它的那台设备删掉 + + "设备不在线" + -> 电脑上的程序没跑,或者网络断了 + + "连不上中转服务器" + -> 随身 WiFi 那台机器上的中转没起来, + 或者隧道挂了。SSH 上去执行 lanremote-status 看看 + + +-------------------------------------------------------- +五、服务器端(随身 WiFi)日常维护 +-------------------------------------------------------- + + 三个服务都是开机自启,正常情况下不用管: + + lanremote-relay 中转服务 + lanremote-tunnel Cloudflare 隧道 + lanremote-watchdog.timer 每 30 秒检查一次隧道连接 + + 想一眼看清状态: + lanremote-status + + 常用命令: + lanremote-url 打印当前公网地址 + lanremote-key 打印管理页钥匙 + systemctl restart lanremote-tunnel 手动换个地址 + journalctl -u lanremote-relay -f 看实时日志 + + 管理页: + 浏览器打开 <公网地址>,用管理密码登录(默认 120830) + 能看:设备列表、在线状态、配对码、流量、会话数 + 能做:删除设备(连配对码一起清)、踢会话、查看当前地址 + + 忘了公网地址? + 打开 http://<随身WiFi的IP>:8080/url —— 直接返回当前地址, + 不用登录。 + + +-------------------------------------------------------- +六、已知限制 +-------------------------------------------------------- + + 1. 一条隧道同时只服务一台手表 + 新连上来的会顶掉旧的,旧的那台会提示"已被另一台手表接管"。 + + 2. 跨网络时的延迟 + 经 Cloudflare 隧道走一圈,一来一回约 0.6 秒; + 局域网直连只有几十毫秒。**程序和手表会自动判断**: + 发现两边在同一个网络就切直连,断了自动切回中转。 + + 3. 网络环境的影响 + 如果随身 WiFi 用的 4G 卡对 UDP 有限制,隧道可能偶尔抖。 + 程序里有看门狗会自动重启隧道,通常 1 分钟内恢复。 + + 4. 杀毒软件误报 + 见《安装前必读》第六节。作者不提供绕过杀软的功能。 + + +-------------------------------------------------------- +七、出问题时怎么反馈 +-------------------------------------------------------- + +请带上这几样,作者才能定位: + + 1. ykxmz.exe --status 的输出 + 2. wlzj.bat 生成的《网络自检结果.txt》 + 3. 手表上的诊断结果(手表首页"连不上?点这里诊断") + 4. 问题什么时候开始的、之前做过什么 + + +-------------------------------------------------------- +八、版本记录 +-------------------------------------------------------- + + 1.7.0 + * 跨网络支持:Cloudflare 具名隧道,固定域名 + * 中转服务器:单设备单配对码、管理页可删设备 + * 手表端:自动判断局域网/中转并无缝切换 + * 被控端:所有开关和画面功能支持回退/撤销 + * 配对码被占用时弹通知提示 + * 新增 --uninstall 一键卸载 + * 针对 512MB 内存的小机器做了优化 + + +-------------------------------------------------------- + 作者:小麦子 + 软件:ykxmz 1.7.0 + 许可条款见《许可协议》(LICENSE.txt) +-------------------------------------------------------- diff --git a/installer/ykxmz.iss b/installer/ykxmz.iss new file mode 100644 index 0000000..e99f2b7 --- /dev/null +++ b/installer/ykxmz.iss @@ -0,0 +1,255 @@ +; ============================================================================ +; ykxmz 教室电脑手表遥控 · 被控端安装包 +; +; 用 Inno Setup 6 编译: +; "C:\Program Files (x86)\Inno Setup 6\ISCC.exe" installer\ykxmz.iss +; +; ── 设计说明 ── +; +; 尽量用 Inno 自带的机制,不手搓: +; * 许可协议页 -> LicenseFile(三份文档合并成一份,点"我接受"才能继续) +; * 开机自启 -> [Tasks](标准勾选框) +; * 装完启动 -> [Run] postinstall(标准勾选框) +; * 安装目录 -> DisableDirPage=no(让用户自己选,默认 Program Files) +; * 卸载 -> [UninstallRun] 调被控端自己的 --uninstall +; 只有"填 6 位配对码"这一页 Inno 没有现成的,用标准的 +; CreateInputQueryPage —— 那是 Inno 的官方 API,不算自己造轮子。 +; +; ── 用户确定的设置 ── +; 安装位置 默认 C:\Program Files\ykxmz,安装时可改 +; 数据目录 能写 exe 旁就写,不能就转 ProgramData(程序内部处理) +; 三份文档 放安装包里,统一接受才能下一步 +; 配对码 安装向导里填 6 位 +; 快捷方式 不建开始菜单、不建桌面 +; 开机自启 默认勾上 +; 装完启动 立即静默启动 +; 卸载 一并删掉,什么都不留 +; ============================================================================ + +#define MyAppName "ykxmz 教室电脑手表遥控" +#define MyAppVersion "1.7.0" +#define MyAppPublisher "小麦子" +#define MyAppExeName "ykxmz.exe" + +[Setup] +AppId={{8F3C1D42-7A5E-4B91-9C6D-2E8F4A1B7C30} +AppName={#MyAppName} +AppVersion={#MyAppVersion} +AppVerName={#MyAppName} {#MyAppVersion} +AppPublisher={#MyAppPublisher} +VersionInfoVersion={#MyAppVersion} + +; 默认装到 Program Files\ykxmz,但安装向导里有一页让用户自己改 +DefaultDirName={autopf}\ykxmz +DisableDirPage=no + +; 三份文档合并成一份许可页:看完点「我接受」才能继续 +LicenseFile=license-combined.txt + +; 不建开始菜单组(用户明确不要) +DisableProgramGroupPage=yes +AllowNoIcons=yes + +; 装到 Program Files 和改防火墙都要管理员 +PrivilegesRequired=admin +ArchitecturesAllowed=x64compatible +ArchitecturesInstallIn64BitMode=x64compatible + +OutputDir=..\dist +OutputBaseFilename=ykxmz-setup-{#MyAppVersion} +SetupIconFile=..\windows\app.ico +UninstallDisplayIcon={app}\{#MyAppExeName} +UninstallDisplayName={#MyAppName} + +Compression=lzma2/max +SolidCompression=yes +WizardStyle=modern +ShowLanguageDialog=no +DisableWelcomePage=no + +[Languages] +Name: "chinese"; MessagesFile: "compiler:Default.isl" + +[Tasks] +; 用户要的:默认勾上开机自启(取消勾选也允许) +Name: "autostart"; Description: "开机自动启动(推荐给教室电脑)"; \ + GroupDescription: "启动选项:"; Flags: checkedonce + +[Files] +; 被控端整个目录(ykxmz.exe + _internal) +Source: "..\dist_exe\ykxmz\*"; DestDir: "{app}"; \ + Flags: recursesubdirs createallsubdirs ignoreversion + +; 三份文档也放一份到安装目录,装完还能翻 +Source: "..\docs\LICENSE.txt"; DestDir: "{app}\docs"; Flags: ignoreversion +Source: "..\docs\BEFORE-INSTALL.txt"; DestDir: "{app}\docs"; Flags: ignoreversion +Source: "..\docs\AFTER-INSTALL.txt"; DestDir: "{app}\docs"; Flags: ignoreversion + +[Dirs] +; ⚠ 这一节很关键 —— 不配的话装完一运行就报 WinError 5 拒绝访问。 +; +; 被控端的配置存在 %ProgramData%\ykxmz\data 下(exe 旁边写不进去时的回退)。 +; 安装包是管理员跑的,它建的目录默认只有管理员能改; +; 之后普通用户(老师的账号)跑被控端时: +; 能新建文件,但覆盖不了管理员建的那份 settings.json +; 结果就是"装完打开报权限错误"。 +; +; Permissions: users-modify 把所有用户的写权限打开,才是真的能用。 +; 注意末尾不带反斜杠,否则 Inno 会给它单独建一层同名子目录。 +Name: "{commonappdata}\ykxmz"; Permissions: users-modify +Name: "{commonappdata}\ykxmz\data"; Permissions: users-modify + +[InstallDelete] +; 早期版本把配置写在程序目录下的 data\ 里。 +; 现在数据统一放 ProgramData(见 config.py 的 data_dir), +; 这里把旧的那份清掉 —— 留着的话,两份配置并存, +; 以后排查问题会被误导("我明明改了配对码怎么没变")。 +Type: filesandordirs; Name: "{app}\data" + +[Run] +; 装完立即静默启动(标准 postinstall 勾选框,默认勾上) +Filename: "{app}\{#MyAppExeName}"; Parameters: "--silent"; \ + Description: "立即启动(后台运行,不显示窗口)"; \ + Flags: nowait postinstall skipifsilent + +; 让用户看一眼装完须知 +Filename: "{app}\docs\AFTER-INSTALL.txt"; \ + Description: "打开「安装后须知」"; \ + Flags: postinstall shellexec unchecked skipifsilent + +[UninstallRun] +; 卸载前先让被控端自己收尾:停进程、删开机自启、清数据目录。 +; 这样"卸载后什么都不留"才是真的干净。 +Filename: "{app}\{#MyAppExeName}"; Parameters: "--uninstall"; \ + Flags: runhidden waituntilterminated; RunOnceId: "StopAgent" + +[UninstallDelete] +; 被控端会自己删数据目录,这里兜底再清一遍安装目录里的残留 +Type: filesandordirs; Name: "{app}\data" +Type: filesandordirs; Name: "{app}\docs" +Type: filesandordirs; Name: "{app}\_internal" + +[Code] +var + CodePage: TInputQueryWizardPage; + ForcedCode: String; + +{ 把字符串里的非数字滤掉。 } +function OnlyDigits(const raw: String): String; +var + i: Integer; + ch: Char; +begin + Result := ''; + for i := 1 to Length(raw) do + begin + ch := raw[i]; + if (ch >= '0') and (ch <= '9') then + Result := Result + ch; + end; +end; + +{ 配对码那一页。Inno 没有现成的输入页,用官方的 CreateInputQueryPage。 } +procedure InitializeWizard(); +begin + { 静默部署可以带 /CODE=123456 直接把码传进来(电教批量装用这个)。 + 注意:Inno 的 [Code] 段连**注释里的花括号**都会当常量去解析, + 所以这里不能直接写 param 那种写法,否则编译器报语法错误。 } + ForcedCode := OnlyDigits(ExpandConstant('{param:CODE|}')); + + CodePage := CreateInputQueryPage(wpSelectTasks, + '配对码', + '给这台电脑定一个 6 位配对码', + '手表上要输这一串数字才能连上这台电脑。自己定个好记的,' + + '比如 789113。装完之后也可以在被控端窗口里改。'); + CodePage.Add('6 位配对码:', False); + if ForcedCode <> '' then + CodePage.Values[0] := ForcedCode; +end; + +{ 校验:必须是 6 位数字。 + 注意 —— **静默模式下这一页不会显示**,值是空的, + 这时候绝不能拦(否则 /VERYSILENT 安装必然失败,我第一版就栽在这)。 } +function NextButtonClick(CurPageID: Integer): Boolean; +var + raw: String; + digits: String; +begin + Result := True; + if CurPageID <> CodePage.ID then + Exit; + if WizardSilent then + Exit; + + raw := CodePage.Values[0]; + digits := OnlyDigits(raw); + if (Length(digits) <> 6) and (raw <> '') then + begin + MsgBox('配对码要 6 位数字。' + #13#10 + #13#10 + + '你现在填的是:' + raw + #13#10 + + '(过滤掉非数字后剩 ' + IntToStr(Length(digits)) + ' 位)' + #13#10 + #13#10 + + '重新填一下,或者直接点「取消」退出安装。', + mbError, MB_OK); + Result := False; + Exit; + end; + { 规范化,后面 [Run] 阶段用得到 } + CodePage.Values[0] := digits; +end; + +{ 最终用的配对码:命令行 /CODE 优先,其次是向导里填的。 + 两个都没有就返回空串 —— 那就跳过 --code,让被控端自己生成一个。 } +function EffectiveCode(): String; +begin + Result := ForcedCode; + if Result = '' then + Result := OnlyDigits(CodePage.Values[0]); + if Length(Result) <> 6 then + Result := ''; +end; + +{ 把向导里收集的东西交给被控端。 + 注意这里**不能带 --silent** —— 那是常驻守护进程,永远不返回, + 用 ewWaitUntilTerminated 等它会把安装程序挂死(第一版就栽在这)。 + 写配置和启动服务分成两次调用: + --code / --autostart 一次性命令,秒退 + --silent 常驻,交给 [Run] 段用 nowait 启动 } +procedure CurStepChanged(CurStep: TSetupStep); +var + ResultCode: Integer; + Params: String; + Code: String; +begin + if CurStep <> ssPostInstall then + Exit; + + Code := EffectiveCode(); + if Code <> '' then + begin + Params := '--code ' + Code; + if not Exec(ExpandConstant('{app}\{#MyAppExeName}'), Params, + ExpandConstant('{app}'), SW_HIDE, ewWaitUntilTerminated, + ResultCode) then + begin + if not WizardSilent then + MsgBox('配对码写入失败(错误码 ' + IntToStr(ResultCode) + ')。' + #13#10 + + '装完之后双击程序图标,重新设一次也行。', + mbInformation, MB_OK); + end; + end; + + { 开机自启:单独调一次,也是一次性命令 } + if WizardIsTaskSelected('autostart') then + Exec(ExpandConstant('{app}\{#MyAppExeName}'), '--autostart on', + ExpandConstant('{app}'), SW_HIDE, ewWaitUntilTerminated, ResultCode); +end; + +{ 卸载前先停掉正在跑的进程,不然文件删不干净。 } +function InitializeUninstall(): Boolean; +var + ResultCode: Integer; +begin + Result := True; + Exec(ExpandConstant('{app}\{#MyAppExeName}'), '--uninstall', + ExpandConstant('{app}'), SW_HIDE, ewWaitUntilTerminated, ResultCode); +end; diff --git a/relay/favicon.ico b/relay/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..dea628a4b4327d6b3133cadef9225ce11b25dbf1 GIT binary patch literal 147470 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%0DEq~Ex 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 S8f4ud;7375MY>ATEcAan!D=r6 literal 0 HcmV?d00001 diff --git a/relay/relay.py b/relay/relay.py index f2fadd1..21767e5 100644 --- a/relay/relay.py +++ b/relay/relay.py @@ -58,7 +58,7 @@ from collections import deque from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer from pathlib import Path -VERSION = "1.6.2" +VERSION = "1.7.0" # ---------------- 参数(都能用环境变量覆盖)---------------- @@ -778,6 +778,8 @@ def _login_page(message: str = "") -> bytes: notice = ('

' + message + '

') if message else '' html = """ + + 中转服务器 · 登录