C++实战:深入Windows打印子系统,彻底卸载打印机驱动
1. 项目概述与核心价值打印机驱动卸载听起来是个简单粗暴的操作无非就是“控制面板-程序和功能-卸载”或者用第三方工具一键清理。但如果你在开发打印管理软件、企业IT运维工具或者需要批量部署、静默卸载驱动时就会发现事情远没那么简单。Windows系统下一个打印机驱动的“痕迹”遍布注册表、系统服务、驱动存储目录、打印后台处理程序等多个角落手动清理几乎不可能彻底而市面上的通用卸载工具往往又不够灵活或深入。这正是“全面掌握打印机驱动卸载”这个项目的核心价值所在。它不是一个简单的使用教程而是一个深入到Windows打印子系统Print Spooler内部用C语言从源码层面解析如何精准、彻底地移除一个打印机驱动及其所有关联资源的实战指南。通过剖析和实现一套完整的驱动卸载逻辑你不仅能解决“卸载不干净导致新驱动安装失败”这个老大难问题更能深刻理解Windows打印架构、驱动安装机制以及如何通过编程与系统底层进行安全交互。这对于C开发者尤其是从事系统工具、桌面管理软件或企业级应用开发的工程师来说是一块极具含金量的技能拼图。2. 驱动卸载的深度原理与Windows打印架构要写代码卸载驱动首先得知道我们要清理的目标是什么以及它们藏在哪里。Windows的打印驱动卸载之所以复杂是因为它不是一个孤立的文件而是一个由多个组件构成的“生态”。2.1 Windows打印驱动组件构成一个完整的打印机驱动通常包含以下几个核心部分卸载时必须逐一处理驱动包文件这是驱动的主体通常是一组.inf、.dll、.dat、.psPostScript或.ppd文件。它们默认存储在C:\Windows\System32\spool\drivers目录下并根据系统架构x86/x64存放在W32X86、x64或IA64子文件夹中。.inf文件是安装脚本记录了所有需要复制的文件和注册表项。注册表配置这是驱动在系统中的“户口本”和“关系网”。主要分布在以下几个注册表路径HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Environments\[环境]\Drivers\[驱动版本]\[驱动名]这里定义了驱动的基本信息、依赖文件、配置数据文件等。HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Monitors打印监视器配置某些驱动会安装自己的监视器。HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Printers已创建打印机的配置。卸载驱动前需要先删除所有使用该驱动的打印机。HKEY_LOCAL_MACHINE\SOFTWARE下对应厂商的键值可能存储了用户设置、许可证信息等。打印处理器某些高级驱动会安装自定义的打印处理器Print Processor其.dll文件存放在C:\Windows\System32\spool\prtprocs\[架构]下并在注册表中HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Printers的PrintProcessor键值中引用。端口监视器对于网络打印机或特殊接口的打印机驱动可能会安装端口监视器Port Monitor相关文件在C:\Windows\System32下配置在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Monitors中。系统服务极少数驱动如某些虚拟打印机可能会注册为系统服务。2.2 官方卸载途径与局限性Windows提供了标准的编程接口来管理打印机和驱动主要是Windows API和WMI。Windows APIwinspool.drv中的函数是主力例如DeletePrinter删除一台打印机。DeletePrinterDriverEx这是关键函数用于删除打印机驱动。它可以指定删除特定环境如Windows x64下的驱动并选择是否删除文件。WMI通过Win32_Printer和Win32_PrinterDriver等类也可以进行管理更适合脚本和远程管理。然而这些标准接口有时会“失灵”。DeletePrinterDriverEx在遇到驱动被其他打印机引用、文件正在被使用、或注册表项残留时可能无法完全清理干净。这就是为什么我们经常需要“强制卸载”——即绕过部分系统保护直接操作底层资源。注意强制卸载风险极高。直接删除系统文件或注册表项可能导致系统不稳定、打印服务崩溃甚至蓝屏。因此我们的代码必须遵循“先软后硬精准定位”的原则优先使用官方API仅在必要时辅以谨慎的底层清理并且每一步都要有充分的错误处理和回滚考虑。3. C实战构建一个健壮的驱动卸载工具理解了原理我们开始用C构建工具。我们将创建一个控制台应用程序核心目标是给定一个驱动名称安全、彻底地将其从系统中移除。3.1 环境准备与项目配置首先确保你的开发环境已就绪。推荐使用Visual Studio 2022并安装“使用C的桌面开发”工作负载。创建新项目选择“控制台应用”模板项目名称如PrinterDriverCleaner。设置字符集打印API多使用宽字符建议将项目属性中的“字符集”设置为“使用Unicode字符集”。添加必要的库在项目属性“链接器-输入-附加依赖项”中添加winspool.lib和advapi32.lib用于注册表操作。3.2 核心模块设计与代码解析我们将工具分为几个逻辑模块下面是关键代码解析。3.2.1 模块一枚举与识别目标驱动在卸载前我们需要先确认驱动是否存在以及有哪些打印机在使用它。#include windows.h #include winspool.h #include iostream #include vector #include string // 函数获取所有已安装的打印机驱动列表 std::vectorDRIVER_INFO_6W EnumeratePrinterDrivers() { std::vectorDRIVER_INFO_6W drivers; DWORD needed 0, returned 0; // 第一次调用获取所需缓冲区大小 if (!EnumPrinterDriversW(nullptr, nullptr, 6, nullptr, 0, needed, returned)) { if (GetLastError() ! ERROR_INSUFFICIENT_BUFFER) { std::wcerr LEnumPrinterDrivers failed. Error: GetLastError() std::endl; return drivers; } } std::vectorBYTE buffer(needed); if (!EnumPrinterDriversW(nullptr, nullptr, 6, buffer.data(), needed, needed, returned)) { std::wcerr LEnumPrinterDrivers failed. Error: GetLastError() std::endl; return drivers; } auto* infoArray reinterpret_castDRIVER_INFO_6W*(buffer.data()); for (DWORD i 0; i returned; i) { drivers.push_back(infoArray[i]); } return drivers; } // 函数根据驱动名查找关联的打印机 std::vectorstd::wstring FindPrintersUsingDriver(const std::wstring driverName) { std::vectorstd::wstring printers; DWORD needed 0, returned 0; // 枚举所有打印机 EnumPrintersW(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, nullptr, 2, nullptr, 0, needed, returned); if (needed 0) return printers; std::vectorBYTE buffer(needed); if (!EnumPrintersW(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, nullptr, 2, buffer.data(), needed, needed, returned)) { return printers; } auto* printerInfo reinterpret_castPRINTER_INFO_2W*(buffer.data()); for (DWORD i 0; i returned; i) { if (printerInfo[i].pDriverName std::wstring(printerInfo[i].pDriverName) driverName) { printers.push_back(printerInfo[i].pPrinterName); } } return printers; }关键点解析使用EnumPrinterDriversW并指定级别6(DRIVER_INFO_6) 可以获取最详细的驱动信息包括驱动路径、依赖文件列表等这对后续的文件清理至关重要。EnumPrintersW级别2(PRINTER_INFO_2) 包含了驱动名称信息用于建立打印机与驱动的关联关系。所有字符串操作都使用宽字符版本W后缀确保兼容性。3.2.2 模块二安全删除关联打印机这是卸载驱动前的强制性步骤。不能直接删除一个正在被使用的驱动。bool DeletePrinterSafely(const std::wstring printerName) { HANDLE hPrinter nullptr; PRINTER_DEFAULTSW defaults {nullptr, nullptr, PRINTER_ALL_ACCESS}; // 打开打印机句柄 if (!OpenPrinterW(const_castLPWSTR(printerName.c_str()), hPrinter, defaults)) { std::wcerr LFailed to open printer: printerName L. Error: GetLastError() std::endl; return false; } // 首先尝试设置打印机状态为“待删除”并等待任务完成 DWORD attributes 0; DWORD needed 0; GetPrinterW(hPrinter, 2, nullptr, 0, needed); // 获取PRINTER_INFO_2所需大小 std::vectorBYTE printerInfoBuffer(needed); PRINTER_INFO_2W* pInfo2 reinterpret_castPRINTER_INFO_2W*(printerInfoBuffer.data()); if (GetPrinterW(hPrinter, 2, printerInfoBuffer.data(), needed, needed)) { pInfo2-Attributes | PRINTER_ATTRIBUTE_PENDING_DELETION; if (!SetPrinterW(hPrinter, 2, printerInfoBuffer.data(), 0)) { std::wcerr LFailed to set printer pending deletion. Error: GetLastError() std::endl; ClosePrinter(hPrinter); return false; } // 简单等待实际生产环境可能需要更复杂的轮询 Sleep(2000); } // 关闭句柄后系统会尝试删除。但为了更可靠我们主动调用DeletePrinter ClosePrinter(hPrinter); // 重新以管理权限打开并删除 defaults.DesiredAccess PRINTER_ALL_ACCESS; // 需要DELETE权限 if (OpenPrinterW(const_castLPWSTR(printerName.c_str()), hPrinter, defaults)) { BOOL result DeletePrinter(hPrinter); ClosePrinter(hPrinter); if (!result) { std::wcerr LDeletePrinter failed for: printerName L. Error: GetLastError() std::endl; // 如果标准删除失败可以尝试强制方法见下文注意事项 return false; } std::wcout LSuccessfully deleted printer: printerName std::endl; return true; } return false; }实操心得直接调用DeletePrinter可能失败尤其是打印机有未完成的任务时。先设置PRINTER_ATTRIBUTE_PENDING_DELETION属性是个好习惯它告诉后台处理程序停止接受新任务并清理队列。OpenPrinter需要足够的权限PRINTER_ALL_ACCESS或至少DELETE权限。程序最好以管理员身份运行。如果打印机顽固无法删除可能需要先停止Spooler服务但这会影响所有打印功能需谨慎并在操作后重启服务。3.2.3 模块三核心驱动卸载与文件清理这是最核心的部分我们将使用DeletePrinterDriverEx并尝试清理残留文件。bool UninstallPrinterDriver(const std::wstring driverName, const std::wstring environment LWindows x64) { std::wcout LAttempting to uninstall driver: driverName L for environment: environment std::endl; // 步骤1: 使用API卸载驱动 // DPD_DELETE_UNUSED_FILES 标志告诉系统尝试删除驱动文件 DWORD result DeletePrinterDriverExW( nullptr, // 本地服务器 const_castLPWSTR(environment.c_str()), const_castLPWSTR(driverName.c_str()), DPD_DELETE_UNUSED_FILES, 0 // 保留位必须为0 ); if (result ! 0) { // 成功 std::wcout LDeletePrinterDriverEx API succeeded. std::endl; } else { DWORD err GetLastError(); std::wcerr LDeletePrinterDriverEx failed. Error code: err std::endl; // 处理常见错误 if (err ERROR_UNKNOWN_PRINTER_DRIVER) { std::wcout LDriver not found via API, may already be partially removed. Proceeding to manual cleanup check. std::endl; // 继续执行手动清理检查 } else if (err ERROR_ACCESS_DENIED) { std::wcerr LAccess denied. Please run this program as Administrator. std::endl; return false; } else { // 其他错误API卸载失败但我们仍可尝试手动清理 std::wcout LAPI removal failed, attempting manual cleanup... std::endl; } } // 步骤2: 手动清理残留文件和注册表高风险操作 // 注意此部分代码需极度谨慎最好在虚拟机上测试通过后再使用 CleanupDriverResidues(driverName, environment); return (result ! 0); // 返回API调用是否成功 } // 辅助函数手动清理残留 void CleanupDriverResidues(const std::wstring driverName, const std::wstring environment) { std::wcout L\n--- Starting manual cleanup for driver: driverName L --- std::endl; // 2.1 清理注册表 - 这是最复杂也最危险的部分 std::wstring regPath LSYSTEM\\CurrentControlSet\\Control\\Print\\Environments\\; regPath environment L\\Drivers\\Version-3\\ driverName; // Version-3 对应驱动模型版本 HKEY hKey; LONG lResult RegOpenKeyExW(HKEY_LOCAL_MACHINE, regPath.c_str(), 0, KEY_ALL_ACCESS, hKey); if (lResult ERROR_SUCCESS) { std::wcout LFound registry key: regPath std::endl; // 首先尝试获取驱动文件列表从InfPath、DataFile等值 // ... 此处省略具体查询代码 RegDeleteTreeW(hKey, nullptr); // 递归删除该键下的所有子项和值 RegCloseKey(hKey); RegDeleteKeyExW(HKEY_LOCAL_MACHINE, regPath.c_str(), KEY_WOW64_64KEY, 0); // 删除键本身 std::wcout LDeleted registry key. std::endl; } else { std::wcout LRegistry key not found (may already be deleted): regPath std::endl; } // 2.2 清理驱动文件目录基于环境判断路径 std::wstring driverDir LC:\\Windows\\System32\\spool\\drivers\\; if (environment.find(Lx64) ! std::wstring::npos) { driverDir Lx64; } else if (environment.find(LW32X86) ! std::wstring::npos) { driverDir LW32X86; } else if (environment.find(LIA64) ! std::wstring::npos) { driverDir LIA64; } driverDir L\\3\\; // “3” 对应驱动版本目录 driverDir driverName; std::wcout LChecking driver directory: driverDir std::endl; // 注意直接删除系统目录文件非常危险 // 生产代码中此处应 // 1. 再次确认该目录只属于要删除的驱动通过之前从注册表读取的文件列表对比。 // 2. 尝试移动文件到临时目录而非直接删除。 // 3. 记录所有删除操作以便回滚。 // 此处仅为演示逻辑。 // if (DirectoryExists(driverDir)) { ... 删除操作 ... } }关键点与避坑指南DeletePrinterDriverEx的标志DPD_DELETE_UNUSED_FILES是核心它指示系统删除不再被任何打印机使用的驱动文件。但系统判断“未使用”可能保守导致文件残留。环境参数environment必须准确如Windows x64、Windows NT x86。获取不准会导致API调用失败。可以通过枚举驱动时得到的DRIVER_INFO_6.pEnvironment字段来确认。手动清理的风险CleanupDriverResidues函数中的操作是高危的。直接操作注册表和系统文件可能导致系统无法启动或打印功能完全损坏。务必在虚拟机或测试机上充分验证。实现完善的错误处理和日志记录。考虑先“标记删除”或移动到回收站而不是直接永久删除。对于注册表优先尝试使用SetupAPISetupUninstallOEMInf等更高级的安装程序API来卸载.inf这比直接删注册表键更安全。4. 进阶处理顽固驱动与系统服务有些驱动尤其是内核模式驱动或虚拟打印机驱动会更深地嵌入系统。4.1 处理驱动文件锁定有时驱动文件.dll被系统进程或后台服务锁定导致无法删除。解决方案是重启后删除这是最安全的方法。我们的程序可以在卸载驱动后将待删除的文件路径写入一个计划任务或MoveFileEx函数并设置MOVEFILE_DELAY_UNTIL_REBOOT标志让系统在下次启动时删除它们。// 计划在下次启动时删除文件 if (!MoveFileExW(LC:\\Windows\\System32\\spool\\drivers\\x64\\3\\BadDriver\\driver.dll, nullptr, MOVEFILE_DELAY_UNTIL_REBOOT)) { // 处理错误 }使用工具强制解锁在代码中集成或调用像Process Explorer的handle.exe这样的命令行工具先关闭锁定文件的句柄。但这需要提升的权限且操作不当会导致程序崩溃。4.2 卸载与打印相关的服务如果驱动注册了服务需要先停止并删除服务。bool RemoveDriverService(const std::wstring serviceName) { SC_HANDLE scm OpenSCManagerW(nullptr, nullptr, SC_MANAGER_ALL_ACCESS); if (!scm) return false; SC_HANDLE service OpenServiceW(scm, serviceName.c_str(), SERVICE_ALL_ACCESS); if (!service) { CloseServiceHandle(scm); return false; // 服务可能不存在 } SERVICE_STATUS status; ControlService(service, SERVICE_CONTROL_STOP, status); Sleep(500); // 等待服务停止 BOOL deleted DeleteService(service); CloseServiceHandle(service); CloseServiceHandle(scm); if (!deleted) { std::wcerr LDeleteService failed. Error: GetLastError() std::endl; // 可能是权限不足或服务标记为删除但需要重启 } return deleted ! 0; }5. 完整工具集成与安全实践将上述模块整合成一个完整的命令行工具。工具的基本流程如下权限检查启动时检查是否以管理员身份运行。参数解析接受驱动名称、环境、强制模式等参数。信息收集枚举驱动和打印机确认目标状态。预检与确认列出所有将受影响的打印机请求用户确认除非是静默模式。执行卸载 a. 删除所有关联打印机。 b. 调用DeletePrinterDriverEx。 c. 可选/强制模式执行手动残留清理。 d. 可选处理相关服务和计划重启删除。日志与回滚每一步操作都记录到日志文件。考虑实现一个简单的回滚机制例如在删除注册表项或文件前备份其路径。安全实践总结测试先行永远在非生产环境虚拟机中测试。权限最小化尽管需要管理员权限但代码内部操作应对资源进行精确判断避免“一刀切”删除。备份与日志任何删除操作前记录足够的信息。对于关键注册表键可以考虑先导出为.reg文件备份。用户交互在非静默模式下向用户清晰展示将要执行的操作和风险。依赖系统API尽可能优先使用DeletePrinterDriverEx、SetupUninstallOEMInf等官方API它们更了解系统内部依赖关系。通过这样一个从原理到源码的深度剖析与实践你不仅获得了一个强大的打印机驱动清理工具更重要的是掌握了在Windows环境下进行深度系统软件管理的核心方法论。这套思路同样适用于处理其他类型的设备驱动或顽固软件卸载是提升你C系统编程能力的绝佳练手项目。记住能力越大责任越大操作底层系统资源时谨慎永远是第一位的。

相关新闻

终极指南:如何免费快速打造你的个人微信记忆档案馆

终极指南:如何免费快速打造你的个人微信记忆档案馆

终极指南:如何免费快速打造你的个人微信记忆档案馆 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we/WeChatMs…

2026/10/12 0:55:45 阅读更多 →
【WPS AI数据透视表实战指南】:3分钟上手智能分析,告别手动拖拽时代

【WPS AI数据透视表实战指南】:3分钟上手智能分析,告别手动拖拽时代

更多请点击: https://intelliparadigm.com 第一章:WPS AI数据透视表的核心价值与演进逻辑 WPS AI数据透视表并非传统透视功能的简单升级,而是将自然语言理解、自动化模式识别与实时语义建模深度耦合的智能分析范式。其核心价值在于消解用户在…

2026/10/9 10:33:12 阅读更多 →
Magpie窗口超分辨率终极指南:从基础配置到实战精通

Magpie窗口超分辨率终极指南:从基础配置到实战精通

Magpie窗口超分辨率终极指南:从基础配置到实战精通 【免费下载链接】Magpie A general-purpose window upscaler for Windows 10/11. 项目地址: https://gitcode.com/gh_mirrors/mag/Magpie 还在为老旧软件在4K显示器上模糊不堪而苦恼吗?或者希望…

2026/10/11 7:36:25 阅读更多 →

最新新闻

IIS管理器打开全攻略:本机启动、远程连接与排错实战

IIS管理器打开全攻略:本机启动、远程连接与排错实战

搞Windows服务器的同学都清楚,IIS管理器这个窗口,看着不起眼,却是撑起大量Web业务的关键工具。很多人以为它就是个“打开就能用”的图形界面,但在实际运维里,光是怎么把它顺利打开、正常连上远程站点,就能筛…

2026/10/13 5:33:32 阅读更多 →
从compose到组合上下文:函数组合的工程化实战复盘

从compose到组合上下文:函数组合的工程化实战复盘

函数组合不是新东西,但真正把它做到"极致"和"优雅",我用了将近一年的时间反复打磨。这篇文章是我对这段时间的完整复盘。我不打算讲枯燥的范畴论,也不打算罗列一堆库的API,我想说的是:我如何从一个…

2026/10/13 5:33:32 阅读更多 →
充电器空载发热、待机功耗异常怎么办?温度保险电阻排查维修实战

充电器空载发热、待机功耗异常怎么办?温度保险电阻排查维修实战

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

2026/10/13 5:33:32 阅读更多 →
fio-3.8完整指南:从解压编译到IOPS与延迟分析实战

fio-3.8完整指南:从解压编译到IOPS与延迟分析实战

简介:FIO(Flexible I/O Tester)3.8 版本完整源代码压缩包,面向存储性能测试工程师、系统运维与内核/驱动开发者,用于在 SSD、HDD、RAID、NVMe 等场景下评估读写吞吐、IOPS 与延迟,并开展压力测试与瓶颈定位…

2026/10/13 5:33:32 阅读更多 →
python -v 和 python -V 的区别:命令行参数大小写敏感与解释器启动排查

python -v 和 python -V 的区别:命令行参数大小写敏感与解释器启动排查

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

2026/10/13 5:33:32 阅读更多 →
目标类型new表达式:现代编程语言的类型推断演进

目标类型new表达式:现代编程语言的类型推断演进

1. 目标类型new表达式的前世今生第一次看到var list new List<string>();这种写法时&#xff0c;我还在用Java写ArrayList<String> list new ArrayList<String>();。这种重复的类型声明总让我觉得像在说废话——明明右边已经写了类型&#xff0c;为什么左边…

2026/10/13 5:32:32 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目&#xff0c;我最大的感受是&#xff0c;大部分坑不是出在技术前沿&#xff0c;而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节&#xff0c;最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了&#xff0c;很难不碰到舵机控制这道坎。做智能小车要转方向&#xff0c;做机械臂要抬关节&#xff0c;做云台要偏航俯仰&#xff0c;背后都是同一个东西在干活&#xff1a;舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”&#xff1f;——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台&#xff1f;或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜&#xff1f;又或者&#xff0c;在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 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/12 21:05:09 阅读更多 →
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/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练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/12 18:11:17 阅读更多 →