"""阶段 C2:安全注入 + WakeProvider 进程内暖树尝试。""" from __future__ import annotations import json import os import subprocess import time from pathlib import Path from typing import Any, Optional from .errors import DesktopWakeError, ERR_WAKE_FAILED from .probe import probe from .profiles import load_profile from .wake import native_helper_path from .window import find_hwnd_for_profile, require_windows def wake_c2( profile: str = "wecom", *, hwnd: Optional[int] = None, ) -> dict[str, Any]: """跑 desktop-wake --mode n2-wake,再 probe。 成功暖树:返回里 ``warm=true``(与 probe 一致)。 """ require_windows() prof = load_profile(profile) h = find_hwnd_for_profile(prof, hwnd=hwnd) before = probe(prof, hwnd=h) helper = native_helper_path(prof.native_helper or "desktop-wake.exe") if helper is None: raise DesktopWakeError(ERR_WAKE_FAILED, "desktop-wake.exe 缺失,请先 build.ps1") cmd = [str(helper), prof.id, "0x" + format(int(h), "x"), "--mode", "n2-wake"] try: proc = subprocess.run(cmd, capture_output=True, text=True, timeout=60, check=False) except subprocess.TimeoutExpired as exc: raise DesktopWakeError(ERR_WAKE_FAILED, "n2-wake timeout") from exc out = (proc.stdout or "").strip() native: dict[str, Any] = {"rc": proc.returncode, "stderr": (proc.stderr or "")[:300]} if out: try: native.update(json.loads(out.splitlines()[-1].strip())) except json.JSONDecodeError: native["raw"] = out[:500] # 进程内 UIA 客户端保持存活后,给外层树一点沉降时间 time.sleep(1.0) after = probe(prof, hwnd=h) tdir = Path(os.environ.get("TEMP") or os.environ.get("TMP") or ".") provider = tdir / "jiangchang_desktop_wake_provider.txt" return { "hwnd": h, "profile_id": prof.id, "cmd": cmd, "native": native, "probe_before": before.to_dict(), "probe_after": after.to_dict(), "warm": after.warm, "ui_responsive": bool(native.get("ui_responsive", True)), "provider_text": provider.read_text(encoding="utf-8", errors="replace") if provider.is_file() else "", }