diff --git a/src/wechat_decrypt_tool/img_helper.py b/src/wechat_decrypt_tool/img_helper.py index 2e59413..b893721 100644 --- a/src/wechat_decrypt_tool/img_helper.py +++ b/src/wechat_decrypt_tool/img_helper.py @@ -6,19 +6,21 @@ from .logging_config import get_logger logger = get_logger(__name__) + class ImgHelper: def __init__(self): self._lib: Optional[ctypes.CDLL] = None self._enabled = False self._lock = __import__("threading").Lock() - def _resolve_dll_path(self) -> Path: + @staticmethod + def _resolve_dll_path() -> Path: # 1. Default (source code layout) base = Path(__file__).resolve().parent path = base / "native" / "img_helper.dll" if path.exists(): return path - + # 2. Frozen (bundled exe) import sys if getattr(sys, "frozen", False): @@ -27,22 +29,22 @@ class ImgHelper: for p in [exe_dir / "native" / "img_helper.dll", exe_dir / "img_helper.dll"]: if p.exists(): return p - + # 3. Current working directory for p in [Path.cwd() / "native" / "img_helper.dll", Path.cwd() / "img_helper.dll"]: if p.exists(): return p - - return path # Fallback to default for error message + + return path # Fallback to default for error message def _load_lib(self): if self._lib is not None: return self._lib - + dll_path = self._resolve_dll_path() if not dll_path.exists(): raise FileNotFoundError(f"Missing img_helper.dll at: {dll_path}") - + try: # On Windows, ensure the DLL's directory is in the search path for dependencies if hasattr(os, 'add_dll_directory'): @@ -50,18 +52,18 @@ class ImgHelper: os.add_dll_directory(str(dll_path.parent)) except Exception: pass - + lib = ctypes.CDLL(str(dll_path)) - + lib.InitImgHelper.argtypes = [ctypes.c_uint32] lib.InitImgHelper.restype = ctypes.c_bool - + lib.UninstallImgHelper.argtypes = [] lib.UninstallImgHelper.restype = None - + lib.GetImgHelperError.argtypes = [] lib.GetImgHelperError.restype = ctypes.c_char_p - + self._lib = lib return lib except Exception as e: @@ -76,7 +78,7 @@ class ImgHelper: # If already enabled, we uninstall first to be safe as per DLL docs suggestion # about being designed to hook one process at a time. lib.UninstallImgHelper() - + if lib.InitImgHelper(pid): self._enabled = True logger.info(f"ImgHelper hook applied to PID {pid}") @@ -108,4 +110,5 @@ class ImgHelper: def is_enabled(self) -> bool: return self._enabled + IMG_HELPER = ImgHelper() diff --git a/src/wechat_decrypt_tool/routers/system.py b/src/wechat_decrypt_tool/routers/system.py index 10aca8e..0a06e16 100644 --- a/src/wechat_decrypt_tool/routers/system.py +++ b/src/wechat_decrypt_tool/routers/system.py @@ -53,16 +53,16 @@ async def toggle_img_helper(req: ImgHelperToggleRequest): if not req.enabled: IMG_HELPER.disable() return {"status": "success", "enabled": False} - + # Attempt to enable status_res = await check_wechat_status() wx_status = status_res.get("wx_status", {}) if not wx_status.get("is_running") or not wx_status.get("pid"): raise HTTPException(status_code=400, detail="未检测到微信正在运行,请先打开微信再尝试!") - + pid = wx_status["pid"] ok, err = IMG_HELPER.enable(pid) if not ok: raise HTTPException(status_code=500, detail=f"开启失败: {err}") - - return {"status": "success", "enabled": True} \ No newline at end of file + + return {"status": "success", "enabled": True} diff --git a/src/wechat_decrypt_tool/routers/wechat_detection.py b/src/wechat_decrypt_tool/routers/wechat_detection.py index f64fc37..fc15bad 100644 --- a/src/wechat_decrypt_tool/routers/wechat_detection.py +++ b/src/wechat_decrypt_tool/routers/wechat_detection.py @@ -90,8 +90,11 @@ async def detect_current_account(data_root_path: Optional[str] = None): @router.get("/api/wechat/status", summary="检查微信运行状态") async def check_wechat_status(): """ - 检查系统中是否有 Weixin.exe 或 WeChat.exe 进程在运行 - 返回: status=0 成功, wx_status={is_running: bool, pid: int, ...} + 检查系统微信主进程状态 + 逻辑: + 1. 匹配进程名 Weixin.exe 或 WeChat.exe + 2. 校验命令行必须包含 exe 名称(排除崩溃后的残留/无效进程) + 3. 在有效进程中选择命令行最短的一个作为主进程 """ process_name_targets = ["Weixin.exe", "WeChat.exe"] @@ -103,21 +106,37 @@ async def check_wechat_status(): } try: - for proc in psutil.process_iter(['pid', 'name', 'exe', 'memory_info']): + candidates = [] + + for proc in psutil.process_iter(['pid', 'name', 'exe', 'memory_info', 'cmdline']): try: - if proc.info['name'] and proc.info['name'] in process_name_targets: - wx_status["is_running"] = True - wx_status["pid"] = proc.info['pid'] - wx_status["exe_path"] = proc.info['exe'] + p_name = proc.info.get('name') + if p_name and p_name in process_name_targets: + # 获取命令行并合并为字符串 + cmdline_list = proc.info.get('cmdline') or [] + cmdline_str = " ".join(cmdline_list).lower() - mem = proc.info['memory_info'] - if mem: - wx_status["memory_usage_mb"] = round(mem.rss / (1024 * 1024), 2) - - break + if any(target.lower() in cmdline_str for target in process_name_targets): + candidates.append({ + "pid": proc.info['pid'], + "exe_path": proc.info['exe'], + "cmd_len": len(cmdline_str), + "memory_info": proc.info['memory_info'] + }) except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): continue + if candidates: + main_proc = min(candidates, key=lambda x: x['cmd_len']) + + wx_status["is_running"] = True + wx_status["pid"] = main_proc["pid"] + wx_status["exe_path"] = main_proc["exe_path"] + + mem = main_proc["memory_info"] + if mem: + wx_status["memory_usage_mb"] = round(mem.rss / (1024 * 1024), 2) + return { "status": 0, "errmsg": "ok", @@ -125,9 +144,8 @@ async def check_wechat_status(): } except Exception as e: - # 即使出错也返回 JSON,但 status 非 0 return { "status": -1, - "errmsg": f"检查进程失败: {str(e)}", + "errmsg": f"检查微信主进程失败: {str(e)}", "wx_status": wx_status - } + } \ No newline at end of file