mirror of
https://github.com/LifeArchiveProject/WeChatDataAnalysis.git
synced 2026-06-18 15:54:08 +08:00
fix(detection): 优化获取微信pid的方法,保证获取到的是主进程!!
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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}
|
||||
|
||||
return {"status": "success", "enabled": True}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user