Skip to content

Commit 3b90ecf

Browse files
committed
improvement(wcdb): 补充 VC++ 运行库安装指引
- 在 WCDB 初始化、连接和超时错误中附加运行库安装说明 - 提供 Microsoft 官方下载地址,方便排查首次运行失败
1 parent 93e5f03 commit 3b90ecf

1 file changed

Lines changed: 31 additions & 10 deletions

File tree

src/wechat_decrypt_tool/wcdb_realtime.py

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,20 @@
2121

2222
logger = get_logger(__name__)
2323

24+
_VC_REDIST_HELP_URL = "https://learn.microsoft.com/zh-cn/cpp/windows/latest-supported-vc-redist?view=msvc-170"
25+
_VC_REDIST_HELP_TEXT = (
26+
"如果这是首次运行或换电脑后出现,请下载安装最新版 Microsoft Visual C++ Redistributable"
27+
"(建议安装 x64 和 x86 两个版本),安装后重启电脑再运行。"
28+
f"下载地址:{_VC_REDIST_HELP_URL}"
29+
)
30+
31+
32+
def _with_vc_redist_help(message: str) -> str:
33+
text = str(message or "").strip()
34+
if _VC_REDIST_HELP_URL in text:
35+
return text
36+
return f"{text} {_VC_REDIST_HELP_TEXT}" if text else _VC_REDIST_HELP_TEXT
37+
2438

2539
class WCDBRealtimeError(RuntimeError):
2640
pass
@@ -521,7 +535,10 @@ def _sidecar_call(action: str, payload: Optional[dict[str, Any]] = None, *, time
521535
hint = ""
522536
if isinstance(logs, list) and logs:
523537
hint = f" logs={[str(x) for x in logs[:6]]}"
524-
raise WCDBRealtimeError(f"{err} rc={rc}.{hint}")
538+
message = f"{err} rc={rc}.{hint}"
539+
if str(action or "").strip() in {"init", "open_account"}:
540+
message = _with_vc_redist_help(message)
541+
raise WCDBRealtimeError(message)
525542
except WCDBRealtimeError:
526543
raise
527544
except (urllib.error.URLError, TimeoutError, OSError) as exc:
@@ -533,7 +550,7 @@ def _sidecar_call(action: str, payload: Optional[dict[str, Any]] = None, *, time
533550
last_err = exc
534551
break
535552

536-
raise WCDBRealtimeError(f"WCDB sidecar unavailable: {last_err}")
553+
raise WCDBRealtimeError(_with_vc_redist_help(f"WCDB sidecar unavailable: {last_err}"))
537554

538555

539556
def _sidecar_payload(action: str, payload: Optional[dict[str, Any]] = None, *, timeout: float = 30.0) -> str:
@@ -819,7 +836,7 @@ def _ensure_initialized() -> None:
819836
hint = _format_protection_hint()
820837
if logs:
821838
hint += f" logs={logs[:6]}"
822-
raise WCDBRealtimeError(f"wcdb_init failed: {rc}.{hint}")
839+
raise WCDBRealtimeError(_with_vc_redist_help(f"wcdb_init failed: {rc}.{hint}"))
823840
_initialized = True
824841

825842

@@ -944,7 +961,7 @@ def open_account(session_db_path: Path, key_hex: str) -> int:
944961
)
945962
handle = int(result.get("handle") or 0)
946963
if handle <= 0:
947-
raise WCDBRealtimeError("wcdb_open_account failed: invalid sidecar handle.")
964+
raise WCDBRealtimeError(_with_vc_redist_help("wcdb_open_account failed: invalid sidecar handle."))
948965
return handle
949966

950967
lib = _load_wcdb_lib()
@@ -953,7 +970,7 @@ def open_account(session_db_path: Path, key_hex: str) -> int:
953970
if rc != 0 or int(out_handle.value) <= 0:
954971
logs = get_native_logs()
955972
hint = f" logs={logs[:6]}" if logs else ""
956-
raise WCDBRealtimeError(f"wcdb_open_account failed: {rc}.{hint}")
973+
raise WCDBRealtimeError(_with_vc_redist_help(f"wcdb_open_account failed: {rc}.{hint}"))
957974
return int(out_handle.value)
958975

959976

@@ -1822,7 +1839,9 @@ def ensure_connected(
18221839
failed_at = self._failed.get(account)
18231840
if failed_at is not None and (time.monotonic() - failed_at) < self._FAILED_TTL:
18241841
logger.warning("[wcdb] recent failure cache hit account=%s ttl=%ss", account, int(self._FAILED_TTL))
1825-
raise WCDBRealtimeError("WCDB connection recently failed; retry after 60s.")
1842+
raise WCDBRealtimeError(
1843+
_with_vc_redist_help("WCDB connection recently failed; retry after 60s.")
1844+
)
18261845

18271846
deadline = time.monotonic() + timeout
18281847

@@ -1841,10 +1860,10 @@ def ensure_connected(
18411860
# Another thread is connecting; wait a bit and retry.
18421861
remaining = deadline - time.monotonic()
18431862
if remaining <= 0:
1844-
raise WCDBRealtimeError("Timed out waiting for WCDB connection.")
1863+
raise WCDBRealtimeError(_with_vc_redist_help("Timed out waiting for WCDB connection."))
18451864
waiter.wait(timeout=min(remaining, 10.0))
18461865
if time.monotonic() >= deadline:
1847-
raise WCDBRealtimeError("Timed out waiting for WCDB connection.")
1866+
raise WCDBRealtimeError(_with_vc_redist_help("Timed out waiting for WCDB connection."))
18481867

18491868
key = str(key_hex or "").strip()
18501869
if not key:
@@ -1891,7 +1910,9 @@ def _do_open() -> None:
18911910
session_db_path,
18921911
)
18931912
raise WCDBRealtimeError(
1894-
f"open_account timed out after {timeout:.0f}s for {session_db_path}"
1913+
_with_vc_redist_help(
1914+
f"open_account timed out after {timeout:.0f}s for {session_db_path}"
1915+
)
18951916
)
18961917
if _open_err:
18971918
with self._mu:
@@ -1905,7 +1926,7 @@ def _do_open() -> None:
19051926
raise _open_err[0]
19061927
if not _handle_box:
19071928
logger.warning("[wcdb] open_account returned no handle account=%s session_db=%s", account, session_db_path)
1908-
raise WCDBRealtimeError("open_account returned no handle.")
1929+
raise WCDBRealtimeError(_with_vc_redist_help("open_account returned no handle."))
19091930

19101931
handle = _handle_box[0]
19111932
# 对齐 WeFlow:传清理后的 wxid/account 名称给 native WCDB,

0 commit comments

Comments
 (0)