2121
2222logger = 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
2539class 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
539556def _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