mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 18:20:43 +00:00
被控端 - 修复 MTU 问题:夹 MSS + 路径 MTU 探测(公网可用率 48% -> 100%) - 复用 HTTP 连接(免掉每次新建 TLS 的 30% 握手失败) - 每分钟回头找局域网,自动切回快 400 倍的路径 - 画面心跳帧:静止时省流量,客户端仍知道流是活的 - 锁屏时给出可操作的提示 手表端 - 内置 GTS Root R4 / GlobalSign Root CA,修 SSLHandshakeException - 连接错误翻译成人话(证书/时间/解析/超时分别提示) - 经中转连上后用服务器报的地址刷新已配对记录 - 新增局域网连接页面、服务器延迟检测 服务器端 - 支持 chunked 请求体(修每 16 秒一次的连接错乱与大面积 502) - 网络调优脚本 net-tune.sh(开机自动应用) - 管理页:批量删除、网络体检、下载区 - 隧道改 HTTP/2 + 双连接 文档 - 许可协议 / 安装前必读 / 安装后须知(作者:小麦子)
386 lines
17 KiB
Python
386 lines
17 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""再加 26 个功能(总数到 131)+ 自启开关 + 退出被控端。
|
||
|
||
新增分组「静默」:开机自启开关、运行状态、退出被控端。
|
||
其余按用途分到「查看」「系统」「网络」「工具」。
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
FEATURES = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote\windows"
|
||
r"\lanremote\features.py")
|
||
|
||
DEFS_ANCHOR = ' add("mute_all", "全部静音", "action", "音量")'
|
||
|
||
DEFS_ADD = ''' add("mute_all", "全部静音", "action", "音量")
|
||
|
||
# ---- 静默运行 ----
|
||
add("autostart", "开机自启(静默)", "toggle", "静默",
|
||
on=self._autostart_on())
|
||
add("autostart_status", "运行状态", "action", "静默")
|
||
add("quit_agent", "退出被控端", "action", "静默")
|
||
add("silent_help", "静默模式说明", "action", "静默")
|
||
|
||
# ---- 查看(续)----
|
||
add("screen_resolution", "显示器分辨率", "action", "查看")
|
||
add("list_printers", "打印机列表", "action", "查看")
|
||
add("list_drives", "驱动器详情", "action", "查看")
|
||
add("audio_devices", "音频设备", "action", "查看")
|
||
add("usb_devices", "USB 设备", "action", "查看")
|
||
add("installed_drivers", "已装驱动", "action", "查看")
|
||
add("windows_detail", "Windows 版本详情", "action", "查看")
|
||
add("recycle_size", "回收站大小", "action", "查看")
|
||
add("temp_size", "临时文件大小", "action", "查看")
|
||
add("certificates", "系统证书", "action", "查看")
|
||
|
||
# ---- 网络(续)----
|
||
add("open_ports", "本机监听端口", "action", "网络")
|
||
add("firewall_status", "防火墙状态", "action", "网络")
|
||
add("dns_servers", "DNS 服务器", "action", "网络")
|
||
add("hosts_file", "查看 hosts", "action", "网络")
|
||
add("wifi_networks", "附近 WiFi", "action", "网络")
|
||
add("bluetooth_devices", "蓝牙设备", "action", "网络")
|
||
|
||
# ---- 系统(续)----
|
||
add("open_services", "打开服务", "action", "系统")
|
||
add("open_task_scheduler", "打开任务计划", "action", "系统")
|
||
add("open_device_manager", "打开设备管理器", "action", "系统")
|
||
add("open_disk_cleanup", "打开磁盘清理", "action", "系统")
|
||
add("open_windows_update", "打开系统更新", "action", "系统")
|
||
add("clear_temp", "清理临时文件", "action", "系统")
|
||
add("env_vars", "环境变量", "action", "系统")'''
|
||
|
||
IMPL_ANCHOR = " # ---------------- 持久化 ----------------"
|
||
|
||
IMPL_ADD = ''' # ==================================================================
|
||
# 静默运行
|
||
# ==================================================================
|
||
|
||
def _autostart_on(self) -> bool:
|
||
try:
|
||
from .autostart import is_enabled
|
||
return is_enabled()
|
||
except Exception: # noqa: BLE001
|
||
return False
|
||
|
||
def _do_autostart(self, params) -> str:
|
||
from .autostart import toggle
|
||
return toggle(self._truthy(params.get("on")))
|
||
|
||
def _do_autostart_status(self, params) -> str:
|
||
from .autostart import status as auto_status
|
||
info = auto_status()
|
||
lines = [
|
||
f"开机自启:{'已开启' if info['enabled'] else '未开启'}",
|
||
f"已配设备:{len(self.store.device_list())} 台",
|
||
f"允许新配对:"
|
||
f"{'是' if self.store.get('allow_new_pairing', True) else '否'}",
|
||
f"监听端口:{self.store.get('port', 8765)}",
|
||
]
|
||
if info["enabled"]:
|
||
lines.append(f"自启命令:{info['command']}")
|
||
return "\\n".join(lines)
|
||
|
||
def _do_quit_agent(self, params) -> str:
|
||
"""退出被控端进程。"""
|
||
import os
|
||
import threading
|
||
|
||
def later():
|
||
time.sleep(0.6) # 先让这条回复发出去
|
||
os._exit(0)
|
||
|
||
threading.Thread(target=later, daemon=True, name="quit").start()
|
||
return "被控端正在退出"
|
||
|
||
def _do_silent_help(self, params) -> str:
|
||
return ("静默模式:没有任何窗口,也没有终端,只在后台监听。\\n"
|
||
"已经配过的手表会自动重连,不用再输配对码。\\n"
|
||
"加新设备要先退出,用带窗口的方式启动,"
|
||
"或运行 LanRemote-Agent.exe --add-device 10")
|
||
|
||
# ==================================================================
|
||
# 查看(续)
|
||
# ==================================================================
|
||
|
||
def _do_screen_resolution(self, params) -> str:
|
||
if not IS_WINDOWS:
|
||
return "仅支持 Windows"
|
||
user32 = ctypes.windll.user32
|
||
user32.SetProcessDPIAware()
|
||
width = user32.GetSystemMetrics(0)
|
||
height = user32.GetSystemMetrics(1)
|
||
monitors = user32.GetSystemMetrics(80)
|
||
return f"主显示器 {width} x {height}\\n显示器数量:{monitors}"
|
||
|
||
def _do_list_printers(self, params) -> str:
|
||
script = ("Get-Printer | ForEach-Object { "
|
||
"\\"$($_.Name) [$($_.Status)]\\" }")
|
||
_code, out = _run(["powershell", "-NoProfile", "-Command", script],
|
||
timeout=25)
|
||
lines = [l for l in out.splitlines() if l.strip()]
|
||
return f"打印机 {len(lines)} 台:\\n" + "\\n".join(lines) if lines else "没有打印机"
|
||
|
||
def _do_list_drives(self, params) -> str:
|
||
script = ("Get-Volume | Where-Object {$_.DriveLetter} | ForEach-Object { "
|
||
"\\"$($_.DriveLetter): $($_.FileSystemLabel) "
|
||
"$([math]::Round($_.SizeRemaining/1GB,1))/"
|
||
"$([math]::Round($_.Size/1GB,1)) GB\\" }")
|
||
_code, out = _run(["powershell", "-NoProfile", "-Command", script],
|
||
timeout=25)
|
||
lines = [l for l in out.splitlines() if l.strip()]
|
||
return "\\n".join(lines) or "读不到驱动器"
|
||
|
||
def _do_audio_devices(self, params) -> str:
|
||
script = ("Get-CimInstance Win32_SoundDevice | ForEach-Object { "
|
||
"\\"$($_.Name) [$($_.Status)]\\" }")
|
||
_code, out = _run(["powershell", "-NoProfile", "-Command", script],
|
||
timeout=25)
|
||
lines = [l for l in out.splitlines() if l.strip()]
|
||
return "\\n".join(lines) or "读不到音频设备"
|
||
|
||
def _do_usb_devices(self, params) -> str:
|
||
script = ("Get-CimInstance Win32_USBControllerDevice | "
|
||
"ForEach-Object { [wmi]$_.Dependent } | "
|
||
"Select-Object -ExpandProperty Name -Unique")
|
||
_code, out = _run(["powershell", "-NoProfile", "-Command", script],
|
||
timeout=30)
|
||
lines = [l for l in out.splitlines() if l.strip()]
|
||
return f"USB 设备 {len(lines)} 个:\\n" + "\\n".join(lines[:30])
|
||
|
||
def _do_installed_drivers(self, params) -> str:
|
||
script = ("Get-CimInstance Win32_PnPSignedDriver | "
|
||
"Where-Object {$_.DeviceName} | "
|
||
"Select-Object -ExpandProperty DeviceName -Unique")
|
||
_code, out = _run(["powershell", "-NoProfile", "-Command", script],
|
||
timeout=35)
|
||
lines = [l for l in out.splitlines() if l.strip()]
|
||
return f"驱动 {len(lines)} 个(前 30):\\n" + "\\n".join(lines[:30])
|
||
|
||
def _do_windows_detail(self, params) -> str:
|
||
script = ("$o=Get-CimInstance Win32_OperatingSystem;"
|
||
"\\"版本: $($o.Caption)\\";"
|
||
"\\"构建: $($o.BuildNumber)\\";"
|
||
"\\"架构: $($o.OSArchitecture)\\";"
|
||
"\\"安装日期: $($o.InstallDate)\\";"
|
||
"\\"最后启动: $($o.LastBootUpTime)\\"")
|
||
_code, out = _run(["powershell", "-NoProfile", "-Command", script],
|
||
timeout=30)
|
||
lines = [l for l in out.splitlines() if l.strip()]
|
||
return "\\n".join(lines) or "读不到"
|
||
|
||
def _do_recycle_size(self, params) -> str:
|
||
script = (
|
||
"$s=(New-Object -ComObject Shell.Application)"
|
||
".NameSpace(10).Items() | "
|
||
"Measure-Object -Property Size -Sum;"
|
||
"\\"$($s.Count) 项,共 "
|
||
"$([math]::Round($s.Sum/1MB,1)) MB\\"")
|
||
_code, out = _run(["powershell", "-NoProfile", "-Command", script],
|
||
timeout=30)
|
||
text = out.strip().splitlines()
|
||
return text[-1] if text else "读不到回收站"
|
||
|
||
def _do_temp_size(self, params) -> str:
|
||
import os as _os
|
||
total = 0
|
||
count = 0
|
||
for root in (_os.environ.get("TEMP", ""), r"C:\\Windows\\Temp"):
|
||
if not root or not Path(root).is_dir():
|
||
continue
|
||
try:
|
||
for item in Path(root).rglob("*"):
|
||
try:
|
||
if item.is_file():
|
||
total += item.stat().st_size
|
||
count += 1
|
||
except OSError:
|
||
continue
|
||
except OSError:
|
||
continue
|
||
return f"临时文件 {count} 个,共 {total / 1048576:.1f} MB"
|
||
|
||
def _do_certificates(self, params) -> str:
|
||
script = ("Get-ChildItem Cert:\\LocalMachine\\Root | "
|
||
"Select-Object -First 25 -ExpandProperty Subject")
|
||
_code, out = _run(["powershell", "-NoProfile", "-Command", script],
|
||
timeout=30)
|
||
lines = [l for l in out.splitlines() if l.strip()]
|
||
return f"受信任根证书(前 25 / 共若干):\\n" + "\\n".join(lines)
|
||
|
||
# ==================================================================
|
||
# 网络(续)
|
||
# ==================================================================
|
||
|
||
def _do_open_ports(self, params) -> str:
|
||
script = ("Get-NetTCPConnection -State Listen | "
|
||
"Where-Object {$_.LocalAddress -eq '0.0.0.0'} | "
|
||
"Select-Object -ExpandProperty LocalPort -Unique | "
|
||
"Sort-Object")
|
||
_code, out = _run(["powershell", "-NoProfile", "-Command", script],
|
||
timeout=25)
|
||
ports = [p.strip() for p in out.splitlines() if p.strip().isdigit()]
|
||
return f"对外监听端口 {len(ports)} 个:\\n" + ", ".join(ports)
|
||
|
||
def _do_firewall_status(self, params) -> str:
|
||
script = ("Get-NetFirewallProfile | ForEach-Object { "
|
||
"\\"$($_.Name): $($_.Enabled)\\" }")
|
||
_code, out = _run(["powershell", "-NoProfile", "-Command", script],
|
||
timeout=25)
|
||
lines = [l for l in out.splitlines() if l.strip()]
|
||
if not lines:
|
||
# NetSecurity 模块坏掉时退化到 netsh
|
||
_code, out = _run(["netsh", "advfirewall", "show", "allprofiles",
|
||
"state"], timeout=25)
|
||
lines = [l.strip() for l in out.splitlines() if "ON" in l or "OFF" in l
|
||
or "开" in l or "关" in l]
|
||
return "\\n".join(lines) or "读不到防火墙状态"
|
||
|
||
def _do_dns_servers(self, params) -> str:
|
||
script = ("Get-DnsClientServerAddress | "
|
||
"Where-Object {$_.ServerAddresses} | ForEach-Object { "
|
||
"\\"$($_.InterfaceAlias): "
|
||
"$($_.ServerAddresses -join ', ')\\" }")
|
||
_code, out = _run(["powershell", "-NoProfile", "-Command", script],
|
||
timeout=25)
|
||
lines = [l for l in out.splitlines() if l.strip()]
|
||
return "\\n".join(lines) or "读不到 DNS"
|
||
|
||
def _do_hosts_file(self, params) -> str:
|
||
path = Path(r"C:\\Windows\\System32\\drivers\\etc\\hosts")
|
||
if not path.is_file():
|
||
return "读不到 hosts"
|
||
try:
|
||
lines = [l.rstrip() for l in path.read_text(
|
||
encoding="utf-8", errors="replace").splitlines()
|
||
if l.strip() and not l.strip().startswith("#")]
|
||
except OSError as exc:
|
||
raise ValueError(f"读不到: {exc}") from exc
|
||
return (f"hosts 里 {len(lines)} 条有效记录:\\n" + "\\n".join(lines[:40])
|
||
if lines else "hosts 里没有自定义记录")
|
||
|
||
def _do_wifi_networks(self, params) -> str:
|
||
_code, out = _run(["netsh", "wlan", "show", "networks"], timeout=25)
|
||
lines = []
|
||
for raw in out.splitlines():
|
||
text = raw.strip()
|
||
if text.startswith("SSID") and "BSSID" not in text:
|
||
lines.append(text)
|
||
return (f"附近 {len(lines)} 个 WiFi:\\n" + "\\n".join(lines[:25])
|
||
if lines else "附近没扫到 WiFi")
|
||
|
||
def _do_bluetooth_devices(self, params) -> str:
|
||
script = ("Get-PnpDevice -Class Bluetooth -Status OK | "
|
||
"Select-Object -ExpandProperty FriendlyName")
|
||
_code, out = _run(["powershell", "-NoProfile", "-Command", script],
|
||
timeout=30)
|
||
lines = [l for l in out.splitlines() if l.strip()]
|
||
return f"蓝牙设备 {len(lines)} 个:\\n" + "\\n".join(lines[:25]) if lines else "没有蓝牙设备"
|
||
|
||
# ==================================================================
|
||
# 系统(续)
|
||
# ==================================================================
|
||
|
||
def _open_msc(self, name: str, label: str) -> str:
|
||
try:
|
||
subprocess.Popen([name], shell=True, creationflags=_NO_WINDOW)
|
||
except Exception as exc: # noqa: BLE001
|
||
raise ValueError(f"打不开{label}: {exc}") from exc
|
||
return f"已打开{label}"
|
||
|
||
def _do_open_services(self, params) -> str:
|
||
return self._open_msc("services.msc", "服务")
|
||
|
||
def _do_open_task_scheduler(self, params) -> str:
|
||
return self._open_msc("taskschd.msc", "任务计划")
|
||
|
||
def _do_open_device_manager(self, params) -> str:
|
||
return self._open_msc("devmgmt.msc", "设备管理器")
|
||
|
||
def _do_open_disk_cleanup(self, params) -> str:
|
||
return self._open_msc("cleanmgr.exe", "磁盘清理")
|
||
|
||
def _do_open_windows_update(self, params) -> str:
|
||
subprocess.Popen(["cmd", "/c", "start", "ms-settings:windowsupdate"],
|
||
creationflags=_NO_WINDOW)
|
||
return "已打开系统更新"
|
||
|
||
def _do_clear_temp(self, params) -> str:
|
||
import os as _os
|
||
removed = 0
|
||
freed = 0
|
||
for root in (_os.environ.get("TEMP", ""), r"C:\\Windows\\Temp"):
|
||
if not root or not Path(root).is_dir():
|
||
continue
|
||
try:
|
||
for item in Path(root).iterdir():
|
||
try:
|
||
if item.is_file():
|
||
size = item.stat().st_size
|
||
item.unlink()
|
||
removed += 1
|
||
freed += size
|
||
elif item.is_dir():
|
||
import shutil as _shutil
|
||
_shutil.rmtree(item, ignore_errors=True)
|
||
removed += 1
|
||
except OSError:
|
||
continue # 正在被占用的跳过
|
||
except OSError:
|
||
continue
|
||
return f"清理了 {removed} 项,释放约 {freed / 1048576:.1f} MB"
|
||
|
||
def _do_env_vars(self, params) -> str:
|
||
names = ["PATH", "TEMP", "USERPROFILE", "COMPUTERNAME", "USERNAME",
|
||
"OS", "PROCESSOR_IDENTIFIER", "SystemRoot"]
|
||
lines = []
|
||
for name in names:
|
||
value = os.environ.get(name, "")
|
||
if name == "PATH":
|
||
value = f"({len(value.split(os.pathsep))} 个路径)"
|
||
lines.append(f"{name} = {value[:80]}")
|
||
return "\\n".join(lines)
|
||
|
||
''' + IMPL_ANCHOR
|
||
|
||
|
||
def main() -> int:
|
||
text = FEATURES.read_text(encoding="utf-8")
|
||
changed = 0
|
||
if '"autostart"' in text:
|
||
print(" defs 已存在,跳过")
|
||
elif DEFS_ANCHOR in text:
|
||
text = text.replace(DEFS_ANCHOR, DEFS_ADD, 1)
|
||
changed += 1
|
||
print(" defs: 已插入静默 + 26 个功能")
|
||
else:
|
||
print(" [失败] defs 锚点没找到")
|
||
|
||
if "_do_autostart" in text:
|
||
print(" 实现已存在,跳过")
|
||
elif IMPL_ANCHOR in text:
|
||
text = text.replace(IMPL_ANCHOR, IMPL_ADD, 1)
|
||
changed += 1
|
||
print(" 实现: 已插入方法")
|
||
else:
|
||
print(" [失败] 实现锚点没找到")
|
||
|
||
if changed:
|
||
FEATURES.write_text(text, encoding="utf-8")
|
||
print(f" 已写入({changed} 处)")
|
||
|
||
import ast
|
||
try:
|
||
ast.parse(FEATURES.read_text(encoding="utf-8"))
|
||
print(" features.py: 语法 OK")
|
||
except SyntaxError as exc:
|
||
print(f" features.py: 语法错误 {exc}")
|
||
return 1
|
||
return 0
|
||
|
||
|
||
if __name__ == "__main__":
|
||
sys.exit(main())
|