子文档二:wdi-simple —— 命令行极简安装器
wdi-simple.c是 libwdi 提供的最简单的驱动安装示例,其代码行数不足 200 行,但却完整地展示了 libwdi 的核心工作流程。它非常适合开发者快速理解如何在自己的应用程序中集成驱动安装功能。
核心流程
wdi-simple 的执行流程可概括为四个步骤:
- 解析命令行参数:使用 GNU getopt 解析用户输入的 VID、PID、驱动类型、INF 名称、目标目录等。
- 准备驱动文件:调用
wdi_prepare_driver生成 INF 和 CAT 文件,并提取所需的驱动二进制。 - 枚举设备:调用
wdi_create_list获取当前系统中的所有 USB 设备链表。 - 匹配并安装:遍历设备链表,查找与指定 VID/PID 匹配的设备,若找到则调用
wdi_install_driver安装驱动;若未找到,则直接调用wdi_install_driver以“预安装”模式(仅复制 INF 到系统目录,等待设备插入)。
命令行参数设计
wdi-simple支持以下主要选项:
-v, --vid:设置 VID(十六进制)-p, --pid:设置 PID(十六进制)-i, --iid:设置复合设备的接口号(MI)-t, --type:驱动类型(0=WinUSB, 1=libusb-win32, 2=libusbK, 3=usbser, 4=custom)-n, --name:设备描述(用于 INF 中的设备名称)-f, --inf:INF 文件名-d, --dest:提取目录-e, --external:使用外部 INF 文件(替代内置模板)-x, --extract:仅提取文件,不安装-s, --silent:静默模式-c, --cert:安装嵌入的证书到受信任发布者存储
这些参数几乎覆盖了wdi_options_prepare_driver和wdi_options_install_driver结构体的所有字段,使得开发者可以灵活控制安装行为。
关键代码片段分析
1. 设备匹配与安装
for(;(ldev!=NULL)&&(r==WDI_SUCCESS);ldev=ldev->next){if((ldev->vid==dev.vid)&&(ldev->pid==dev.pid)&&(ldev->mi==dev.mi)&&(ldev->is_composite==dev.is_composite)){dev.hardware_id=ldev->hardware_id;dev.device_id=ldev->device_id;matching_device_found=TRUE;r=wdi_install_driver(&dev,ext_dir,inf_name,&oid);}}该循环遍历 libwdi 返回的设备链表,通过 VID/PID/MI 三要素匹配目标设备。一旦匹配成功,将设备的hardware_id和device_id赋值给dev结构体,然后调用wdi_install_driver执行安装。这种设计使得安装器可以自动适配当前插入的特定型号设备。
2. 预安装模式
当没有匹配的已连接设备时,wdi_install_driver仍然会被调用(此时dev结构体中仅包含 VID/PID/描述等信息,但hardware_id和device_id为空)。libwdi 内部会检测到设备未连接,转而调用SetupCopyOEMInf将 INF 复制到系统目录,并标记设备以便下次插入时自动安装。这实现了“先准备驱动,再插入设备”的用户体验。
3. 进度反馈
wdi-simple支持-b参数显示进度条(若指定 HWND 则作为父窗口,否则使用控制台窗口句柄)。它通过GetConsoleHwnd获取控制台窗口句柄,并将其传递给wdi_options_install_driver的hWnd字段,从而触发 libwdi 内部的进度对话框模式。这展示了 libwdi 如何在 GUI 和无头环境下切换安装界面。
使用场景
wdi-simple 非常适合以下场景:
- 驱动程序开发者的快速测试:在开发过程中快速为测试设备安装驱动。
- 自动化部署:通过脚本调用,实现无人值守的驱动安装。
- 学习 libwdi API 的入门参考:代码简洁,注释清晰,是理解 libwdi 工作原理的最佳起点。