鼠标提示拼接文本超过 1024 字符时偶发弹出 “Encountered an improper argument.” 错误

Author: ObnubiladOCreated Sep 9, 2026Updated Sep 9, 2026

前置条件

  • 已经在 issue 列表中搜索了相关问题。
  • 已详细阅读了常见问题并在常见问题列表中搜索了相关问题。

您当前使用的TrafficMonitor版本

1.86(x64)

您当前使用的操作系统版本

Windows 11 x64

发生了什么?

TrafficMonitor 会偶发弹出标题为 "TrafficMonitor"、内容为 "Encountered an improper argument." 的错误弹窗(错误图标)。通常在启动后一分钟内出现,也可能稍晚出现,关闭后还可能再次弹出;程序本身不会崩溃,能继续正常运行。

这是 MFC 的 CInvalidArgException。根本原因:TrafficMonitor 每隔一次数据刷新(大约每秒一次)都会重新拼接完整的“鼠标提示”字符串并传给 CToolTipCtrl::UpdateTipText,而 MFC 在该函数中强制限制提示文本不能超过 1024 个字符,超长即抛出异常:

// VS2022 MFC, atlmfc/include/afxcmn.h, 第 22 行:
const size_t MAX_TIP_TEXT_LENGTH = 1024;

// VS2022 MFC, atlmfc/src/mfc/tooltip.cpp, CToolTipCtrl::UpdateTipText:
void CToolTipCtrl::UpdateTipText(LPCTSTR lpszText, CWnd* pWnd, UINT_PTR nIDTool)
{
    ENSURE(::IsWindow(m_hWnd));
    ENSURE_ARG(pWnd != NULL);
    if (lpszText != LPSTR_TEXTCALLBACK)
    {
        ENSURE_ARG(AtlStrLen(lpszText) <= MAX_TIP_TEXT_LENGTH);   // <-- 超长时抛 CInvalidArgException
    }
    ...
}

而 TrafficMonitor 拼接出来的提示文本没有任何长度上限:

  • CTrafficMonitorDlg::GetMouseTipsInfo()TrafficMonitorDlg.cpp:133)拼接主窗口提示文本,并在第 217 行追加所有已加载插件的提示文本拼接结果
  • CTaskBarDlg::GetMouseTipsInfo()TaskBarDlg.cpp:698)对任务栏窗口做同样的事(第 790 行追加插件提示);
  • CTrafficMonitorApp::GetPlauginTooltipInfo()TrafficMonitor.cpp:1209)用 \r\n 把所有插件的 GetTooltipInfo() 拼在一起;
  • CTrafficMonitorDlg::OnMonitorInfoUpdated()TrafficMonitorDlg.cpp:2845)每次刷新都会调用 m_tool_tips.UpdateTipText(tip_info, this)(第 2854 行),任务栏窗口则通过 CTaskBarDlg::UpdateToolTips()TaskBarDlg.cpp:943,第 949 行)调用。

提示文本里包含动态内容(传感器名称/数值、被隐藏项目的行、各插件文本),每次刷新长度都在变化,因此只在偶然超过 1024 时弹窗,表现为时有时无。插件作者无法预知剩余长度预算(取决于内置文本和其他插件的文本长度),所以这个问题应在主程序内部处理。

复现方法

  • 加载一个或多个 GetTooltipInfo() 输出较长的插件,使插件文本与内置提示文本相加超过 1024 字符。单个插件返回约 950 个以上字符即可稳定触发;两个各约 600 字符的插件也可以。
  • 现象:弹窗出现(在报告者机器上约 1 分钟内)。

建议修复

在两个调用点(TrafficMonitorDlg.cpp:2854TaskBarDlg.cpp:949)把拼接好的提示文本截断到上限内再传给 MFC,例如:

constexpr size_t kMaxTipChars = 1024;
if (tip_info.GetLength() > static_cast<int>(kMaxTipChars))
    tip_info = tip_info.Left(kMaxTipChars - 1);   // 或改为在末尾加 L"…"

另外建议:

  • 在插件开发指南中说明 1024 字符的合并预算,提醒插件作者控制提示长度;
  • 也可以考虑对每个插件的提示单独截断(加省略号),而不是只做最终一刀切。

日志输出

(为空 —— 该错误不会写入 error.log,因此看起来与插件无关。)

附加信息

  • 通过进程内 MessageBoxW 钩子验证:弹窗文本正是 "Encountered an improper argument.",标题 "TrafficMonitor",MB_ICONERROR,在 UI 线程上由 mfc140u.dll(MFC 异常报告路径)弹出,即上面 ENSURE_ARG 抛出的 CInvalidArgException
  • 同一台机器上的受控重启试验(每次约 70 秒):
配置 弹窗次数
无额外插件 0 / 8
插件提示约 150 字符 5 / 9
同一插件但提示为空 0 / 5
空提示插件 + 用户正常配置 0 / 4
  • 目前的用户侧临时规避:让受影响的插件返回空提示文本。这样不再弹窗,但没有真正修复问题——任何提示较长的插件或插件组合都可能再次触发。

Source: zhongyang219/TrafficMonitor