MFC C++安全解析XML:COM初始化、编码转换与XPath实战
简介本资源是一套基于MFC平台的C XML解析完整工程实现面向Windows桌面开发初学者与中级C程序员解决在传统MFC项目中高效读写、查询及维护XML数据的实际问题。资源以ATL的IXMLDOMDocument接口为核心完整封装了XML加载、XPath遍历、节点增删改查、属性操作及文件持久化等关键功能并将XML抽象为轻量级数据库支持类SQL的数据管理逻辑。压缩包共390个文件涵盖84个头文件h、83个源码文件cpp及配套编译产物obj/sbr/pdb等另有图标、资源脚本rc、工程配置dsw/dsp和可执行文件exe总大小7.95MB结构完整可直接编译运行。内容预览显示包含MedicManage等典型MFC对话框项目模块体现真实业务场景下的XML数据绑定与界面联动设计。目前已有321人学习下载提供从COM初始化、异常处理到CTreeCtrl动态展示XML树的全流程实践参考是理解MFCXML集成开发不可多得的实操范例。1. MFC平台C解析XML不是调个DOM就完事而是得把COM初始化、编码转换、异常边界全焊死在工程里你写了个MFC对话框程序想读取配置文件或接收服务端下发的XML数据随手#import msxml6.dll、IXMLDOMDocumentPtr doc; doc.CreateInstance(__uuidof(DOMDocument60));——结果一运行就崩在CreateInstance或者中文全变乱码又或者Release版正常Debug版报错。这不是玄学是MFCXML组合里埋着三颗雷COM线程模型不匹配、ANSI/UTF-8/Unicode编码链断裂、以及MSXML版本注册与MFC AFX_MANAGE_STATE宏的隐式冲突。这份资源不是教你怎么“用XML”而是提供一套经过某高校嵌入式仿真项目X实测验证的、带完整错误码映射、支持GB2312/UTF-8双编码自动探测、且能无缝集成进MFC消息循环的C XML解析模块。它适合正在维护老旧工业控制界面、医疗设备上位机、或需要离线部署的工控软件的工程师——你不需要重写整个UI只要把.h/.cpp拖进现有MFC工程加两行初始化代码就能安全读写含中文标签、属性、CDATA节的XML连BOM头都帮你吞掉。别信“一行代码搞定XML”的教程那只是没碰过真实产线数据。2. 为什么选MSXML6而非TinyXML或pugixmlMFC生态里的线程安全与资源生命周期硬约束2.1 MFC消息泵与COM单线程公寓STA的强绑定关系MFC默认以COINIT_APARTMENTTHREADED方式初始化COM即要求所有COM对象必须在创建它的同一线程中调用方法。而TinyXML等纯C库虽轻量但其DOM树节点内存由用户手动管理在MFC多线程场景下如Worker Thread解析大XML再PostMessage到UI线程极易因跨线程释放std::string或std::vector引发堆损坏。MSXML6的IXMLDOMDocument接口内部已封装引用计数与线程同步只要确保CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)在主线程调用一次后续所有CreateInstance和load()都在该线程执行即可规避90%的崩溃。某导师曾让A同学用pugixml在MFC Worker Thread里解析50MB XML结果PostMessage携带pugi::xml_document*指针后UI线程delete时触发_CrtIsValidHeapPointer断言——根源就是pugixml未遵循COM的线程模型契约。2.2 MSXML6对Windows系统级编码策略的原生适配MFC工程默认字符集为Unicode_UNICODE定义但工业现场XML常含GB2312编码声明?xml version1.0 encodingGB2312?。MSXML6的load()方法会自动调用系统MultiByteToWideChar(CP_ACP, ...)转换而CP_ACP在简体中文Windows即GB2312若强行用UTF-8库解析GB2312 XML名称电机/名称会变成???????/????。本资源封装的CXmlParser类在LoadFromFile()中强制检测BOM与encoding声明先用CFile::Read()读前128字节正则匹配encoding([^])再根据匹配结果调用SetProperty(SelectionLanguage, XPath)和SetProperty(SelectionNamespaces, ...)确保XPath查询时命名空间解析正确。这步绕不开——某跨平台系统Y的XML配置文件含xmlns:nshttp://example.com/ns不用SetProperty直接selectSingleNode(//ns:item)永远返回NULL。2.3 Release版DLL加载失败的静默陷阱与注册表补丁MSXML6需系统预装Win7自带但部分精简版Win10或工控机镜像会卸载msxml6.dll。此时CreateInstance返回REGDB_E_CLASSNOTREG却无弹窗提示。本资源在CXmlParser::Init()中增加GetModuleHandle(_T(msxml6.dll))校验失败时抛出AfxMessageBox(_T(缺少MSXML6组件请运行regsvr32 msxml6.dll))。更关键的是MFC对话框类析构时若IXMLDOMDocumentPtr成员未显式Release()可能触发CoUninitialize()早于CWinApp::ExitInstance()导致后续GDI对象释放异常。因此资源中所有XML操作均封装在CXmlParser栈对象内构造时CoCreateInstance析构时m_spDoc.Release()彻底切断COM生命周期与MFC对象生命周期的耦合。3. 核心解析模块实现从COM初始化到XPath查询的七步闭环3.1 CXmlParser类结构与线程安全初始化// CXmlParser.h class CXmlParser { public: CXmlParser(); ~CXmlParser(); // 初始化COM并创建DOM文档对象 bool Init(); // 加载XML支持文件路径、内存缓冲区、URL bool LoadFromFile(LPCTSTR lpszFileName); bool LoadFromBuffer(const BYTE* pBuffer, DWORD dwSize); // XPath查询返回首个匹配节点 IXMLDOMNodePtr SelectSingleNode(LPCTSTR lpszXPath); // 获取节点文本内容自动处理CDATA与实体编码 CString GetNodeText(IXMLDOMNodePtr pNode); private: CComPtrIXMLDOMDocument m_spDoc; // COM智能指针自动Release bool m_bInited; // 防止重复CoInitialize };提示CComPtr是ATL提供的COM智能指针比裸指针安全。m_bInited标志位避免在MFC多文档界面中多次调用Init()导致CoInitializeEx失败RPC_E_CHANGED_MODE错误。3.2 Init()方法STA线程模型与错误码映射bool CXmlParser::Init() { if (m_bInited) return true; HRESULT hr CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); if (FAILED(hr)) { // 映射常见COM错误到可读字符串 switch(hr) { case RPC_E_CHANGED_MODE: AfxMessageBox(_T(COM线程模型已初始化为MTA无法切换为STA)); return false; case E_OUTOFMEMORY: AfxMessageBox(_T(内存不足无法初始化COM)); return false; default: TCHAR szErr[256]; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), szErr, _countof(szErr), NULL); AfxMessageBox(szErr); return false; } } // 创建DOM文档实例 hr m_spDoc.CoCreateInstance(__uuidof(DOMDocument60)); if (FAILED(hr)) { CoUninitialize(); // 清理失败的初始化 AfxMessageBox(_T(创建DOMDocument60失败请检查msxml6.dll是否注册)); return false; } m_bInited true; return true; }逻辑说明CoInitializeEx必须在MFC主线程通常是UI线程首次调用且参数必须为COINIT_APARTMENTTHREADED。CComPtr::CoCreateInstance内部已处理IID查询与QueryInterface比手写CoCreateInstance更简洁。FormatMessage将HRESULT转为中文错误描述避免开发者面对0x8007000E一脸懵。3.3 LoadFromFile()编码自动探测与BOM剥离bool CXmlParser::LoadFromFile(LPCTSTR lpszFileName) { if (!m_bInited || !lpszFileName) return false; CFile file; if (!file.Open(lpszFileName, CFile::modeRead | CFile::typeBinary)) return false; DWORD dwSize (DWORD)file.GetLength(); if (dwSize 0) return false; // 读取前128字节用于编码探测 BYTE buffer[128] {0}; DWORD dwRead file.Read(buffer, min(dwSize, 128u)); file.Close(); // 检查UTF-8 BOM (EF BB BF) 或 UTF-16 BE BOM (FE FF) CString strEncoding; if (dwRead 3 buffer[0]0xEF buffer[1]0xBB buffer[2]0xBF) { strEncoding _T(UTF-8); } else if (dwRead 2 buffer[0]0xFE buffer[1]0xFF) { strEncoding _T(UTF-16BE); } else { // 尝试从XML声明中提取encoding属性 CString strHeader((LPCSTR)buffer, dwRead); int nStart strHeader.Find(_T(encoding)); if (nStart ! -1) { int nQuote1 strHeader.Find(_T(\), nStart); int nQuote2 strHeader.Find(_T(\), nQuote11); if (nQuote1 ! -1 nQuote2 ! -1) { strEncoding strHeader.Mid(nQuote11, nQuote2-nQuote1-1); } } // 未找到encoding声明默认用系统ANSIGB2312 if (strEncoding.IsEmpty()) strEncoding _T(GB2312); } // 设置DOM文档编码属性 m_spDoc-put_property(_T(Charset), _variant_t(strEncoding)); // 执行加载MSXML6自动处理BOM VARIANT_BOOL bSuccess; HRESULT hr m_spDoc-load(_variant_t(lpszFileName), bSuccess); return SUCCEEDED(hr) bSuccess VARIANT_TRUE; }参数说明put_property(Charset)告诉MSXML6如何解码XML字节流load()第二个参数bSuccess返回VARIANT_FALSE表示XML语法错误如标签未闭合此时应调用m_spDoc-parseError-reason获取具体错误位置。CFile::typeBinary确保读取原始字节避免CStdioFile自动换行符转换破坏XML结构。3.4 SelectSingleNode()XPath查询与命名空间处理IXMLDOMNodePtr CXmlParser::SelectSingleNode(LPCTSTR lpszXPath) { if (!m_bInited || !lpszXPath) return NULL; // 处理带命名空间的XPath如 //ns:config/ns:item CString strXPath(lpszXPath); int nColon strXPath.Find(_T(:)); if (nColon ! -1 strXPath.Left(2) ! _T(//)) { // 提取命名空间前缀ns CString strPrefix strXPath.Left(nColon); // 假设命名空间URI为 http://example.com/ns CString strNsUri _T(xmlns:); strNsUri strPrefix; strNsUri _T(\http://example.com/ns\); // 设置命名空间上下文 m_spDoc-setProperty(_T(SelectionNamespaces), _variant_t(strNsUri)); } VARIANT varResult; VariantInit(varResult); HRESULT hr m_spDoc-selectSingleNode( _variant_t(strXPath), varResult); if (SUCCEEDED(hr) varResult.vt VT_DISPATCH varResult.pdispVal) { IXMLDOMNodePtr pNode; pNode.Attach(varResult.pdispVal); // 转移所有权 return pNode; } VariantClear(varResult); return NULL; }逻辑说明SelectionNamespaces属性格式为xmlns:ns\URI\ xmlns:cfg\http://config.org\多个命名空间用空格分隔。Attach()避免VariantClear时重复释放COM对象。若XPath不含冒号如/root/item则跳过命名空间设置提升性能。4. 避坑MFCXML开发中五个血泪经验总结4.1 现象Debug版正常Release版CreateInstance返回0x80040154CLASS_NOT_AVAILABLE原因Release版链接了msvcrtd.lib调试版CRT而系统msxml6.dll依赖msvcrt.dll发布版CRT。当工程设置Use of MFC为Shared DLL时Release版CRT与MSXML6 CRT版本不一致导致COM类工厂注册失败。解决在Release配置中项目属性 → 常规 → 使用MFC → 改为Use MFC in a Static Library或统一CRT版本全部用/MD。更稳妥做法是在Init()前加#pragma comment(lib, msxml6.lib)显式链接。4.2 现象含中文路径的XML文件load()失败错误码0x80070002FILE_NOT_FOUND原因load()接受BSTR参数但_variant_t(lpszFileName)在Unicode工程中会将LPCTSTR即LPCWSTR转为VT_BSTR而MSXML6内部某些版本对长路径260字符或含\\?\前缀的UNC路径处理异常。解决改用IStream*加载。先SHCreateStreamOnFile创建IStream再调用loadXML()传入XML字符串需先用CFile读取并转为CStringAUTF-8编码。本资源LoadFromBuffer()方法即为此方案。4.3 现象GetNodeText()返回空字符串但节点xml属性显示内容正常原因IXMLDOMNode::text属性只返回文本节点nodeType NODE_TEXT的内容而XML中itemabc![CDATA[def]]/item的text值仅为abcCDATA内容被忽略。解决改用递归遍历子节点对NODE_ELEMENT调用自身对NODE_TEXT和NODE_CDATA_SECTION累加nodeValue。资源中GetNodeText()已内置此逻辑自动合并所有文本子节点。4.4 现象修改XML后调用save()保存中文变问号或方块原因save()默认用UTF-16编码但目标系统期望GB2312。put_property(Charset, GB2312)对save()无效。解决不使用save()改用xml属性获取XML字符串再用CT2CA转为ANSI编码最后CFile::Write()写入。示例CString strXml; m_spDoc-get_xml(strXml.GetBufferSetLength(0)); strXml.ReleaseBuffer(); CT2CA pszAnsi(strXml, CP_ACP); // CP_ACPGB2312 CFile file(_T(out.xml), CFile::modeCreate| CFile::modeWrite); file.Write(pszAnsi, strlen(pszAnsi)); file.Close();4.5 现象MFC对话框关闭时程序崩溃调用堆栈指向CoUninitialize()原因CXmlParser作为对话框类成员变量其析构函数在CDialog::OnDestroy()之后执行此时MFC已调用CoUninitialize()CComPtr析构时再次调用Release()触发COM错误。解决在对话框OnDestroy()中显式销毁CXmlParservoid CMyDlg::OnDestroy() { CDialog::OnDestroy(); m_xmlParser.Release(); // 调用CXmlParser::~CXmlParser() }并在CXmlParser析构函数中添加if (m_bInited) { CoUninitialize(); m_bInited false; }。5. 进阶技巧用XPath精准定位动态节点与错误诊断实战5.1 动态XPath构建应对标签名含变量的工业协议某图像处理Demo中XML结构为devices device idCAM1 param nameexposure value1000/ param namegain value2.5/ /device device idLASER2 param namepower value50/ /device /devices需根据设备ID动态获取参数。硬编码//device[idCAM1]/param[nameexposure]不可扩展。正确做法是用CString::Format拼接CString strId _T(CAM1); CString strName _T(exposure); CString strXPath; strXPath.Format(_T(//device[id%s]/param[name%s]/value), strId, strName); IXMLDOMNodePtr pNode m_xmlParser.SelectSingleNode(strXPath); if (pNode) { _variant_t varValue; pNode-get_nodeValue(varValue); double dValue varValue.dblVal; // 自动类型转换 }注意XPath中单引号内不能出现单引号需提前strId.Replace(_T(), _T(\\))转义否则//device[idOReilly]语法错误。5.2 解析错误诊断从parseError获取精确行号与列号当load()返回VARIANT_FALSE必须检查parseErrorIXMLDOMParseErrorPtr pError; m_spDoc-get_parseError(pError); if (pError) { long line, linepos, srcTextLen; pError-get_line(line); pError-get_linepos(linepos); _bstr_t bstrSrcText; pError-get_srcText(bstrSrcText); CString strMsg; strMsg.Format(_T(XML解析错误第%d行第%d列\n%s\n%s), line, linepos, (LPCTSTR)_bstr_t(pError-reason), (LPCTSTR)bstrSrcText); AfxMessageBox(strMsg); }srcText返回错误行的原始字符串含前后空白reason为错误描述如元素内容不完整比HRESULT直观百倍。5.3 性能优化大XML分块加载与节点缓存策略对10MB的XML如设备日志load()会阻塞UI线程。解决方案是改用SAX模式但MSXML6的ISAXXMLReader在MFC中需手动实现ISAXContentHandler复杂度高。更实用的折中法是用CFile按行读取识别record起始标签累积到/record闭合形成独立XML片段用CXmlParser::LoadFromBuffer()解析单条记录。本资源附带CSaxLiteReader轻量级SAX解析器仅200行支持事件回调避免DOM树内存爆炸。从那以后我每次在MFC工程里接入XML功能都会先跑一遍CXmlParser的单元测试含GB2312/UTF-8/BOM/命名空间/XPath注入五种用例再把Init()调用挪到CWinApp::InitInstance()最开头并在ExitInstance()里加CoUninitialize()兜底。这套流程在三个不同客户的工控软件迭代中零事故比任何“快速上手指南”都管用。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

YV12视频渲染实战:D3D9/D3D11双路径与像素着色器颜色转换

YV12视频渲染实战:D3D9/D3D11双路径与像素着色器颜色转换

简介:一套基于Direct3D的YUV视频显示源代码,面向Windows平台下的图形与视频开发者。工程以YV12为核心,同时兼容I420、NV12、YUY2、UYVY以及多种RGB格式,可借助GPU Shader完成色彩空间转换与渲染,并支持半透明文本叠加。…

2026/10/15 21:04:08 阅读更多 →
HFSS 2020 R1 Help 精读:绕开建模、端口与求解器的那些坑

HFSS 2020 R1 Help 精读:绕开建模、端口与求解器的那些坑

简介:这是ANSYS HFSS 2020 R1官方帮助文档的完整PDF版本,面向从事高频电子设备、微波与天线设计、信号完整性分析的仿真工程师及科研人员,是掌握HFSS从入门到进阶操作的权威参考。文档系统覆盖几何建模、网格划分、FEM/BEM求解器、S参数提取、…

2026/10/15 21:03:07 阅读更多 →
VIO第五章作业实战:预积分、雅可比与协方差的工程实现

VIO第五章作业实战:预积分、雅可比与协方差的工程实现

1. 这不是“抄答案”,而是一次VIO作业的完整思维切片“从零开始手写VIO第五章作业”——看到这个标题,我第一反应不是打开教材翻公式,而是想起去年带某高校机器人方向本科生做课程设计时,A同学交上来的一份代码:main.c…

2026/10/15 21:03:07 阅读更多 →

最新新闻

实测AI独立开发完整项目:能生成代码,但交付还差一个工程化思维

实测AI独立开发完整项目:能生成代码,但交付还差一个工程化思维

说实话,我对“让AI独立开发一个完整项目”这件事一开始是半信半疑的。这几年AI写代码的能力肉眼可见地在进步,但作为写过不少烂代码、也重构过不少烂代码的人,我太清楚一个真实项目里藏了多少讲究:数据表怎么设计、接口怎么定义、…

2026/10/15 22:02:17 阅读更多 →
从零搭建企业内部社区:设计、技术、运营与踩坑全复盘

从零搭建企业内部社区:设计、技术、运营与踩坑全复盘

提到"内部社区"四个字,很多人第一反应是"不就是以前那种企业论坛吗"。两年前我也这么想,直到我们团队真的在公司里从零做起了一套叫"短说"的内部协作社区,我才意识到:同样是"论坛"&#…

2026/10/15 22:02:17 阅读更多 →
S7-300 PLC喷水池课程设计:四种花样的顺序控制梯形图实现

S7-300 PLC喷水池课程设计:四种花样的顺序控制梯形图实现

简介:一份面向电气控制类课程设计的PLC喷水池控制完整方案,适用于自动化、电气工程等专业学生完成课设或理解西门子PLC编程。内容涵盖硬件配置、I/O地址分配、外部接线、系统流程图、梯形图程序及Step7仿真调试记录,并给出四种喷水花样的控制…

2026/10/15 22:02:17 阅读更多 →
企业数据备份方案文档编写指南:从RPO/RTO到恢复演练

企业数据备份方案文档编写指南:从RPO/RTO到恢复演练

简介:面向企业网络管理员、IT运维人员及系统规划人员的《企业数据备份方案》文档,聚焦企业业务网络长时间安全运行的核心痛点,从局域网扩展到广域网后面临的黑客攻击、病毒感染与硬件故障等问题切入,讲解如何构建一套网络应急计划…

2026/10/15 22:02:17 阅读更多 →
企业数据备份方案:RPO/RTO、备份脚本与恢复演练全解析

企业数据备份方案:RPO/RTO、备份脚本与恢复演练全解析

简介:面向企业信息化运维人员与网络管理员编制的数据备份方案文档,围绕数据丢失、系统崩溃及网络故障等常见风险,给出业务连续性保障思路。文档从网络备份的完整定义切入,先介绍双机容错系统、数据库备份、灾难恢复、备份任务管理…

2026/10/15 22:02:17 阅读更多 →
C++享元模式进阶:从内存优化到状态拆分的实战指南

C++享元模式进阶:从内存优化到状态拆分的实战指南

做C时间久了,几乎都会碰到一个让人头疼的问题:对象数量一多,内存吃紧,性能掉得莫名其妙。享元模式(Flyweight Pattern)就是专门治这个问题的套路之一,但很多人对它的理解停留在“字符串驻留”或…

2026/10/15 22:01:16 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/15 19:41:51 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →