十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

WDK 10.0.19041.0驱动开发环境配置与KMDF驱动入门

WDK 10.0.19041.0驱动开发环境配置与KMDF驱动入门 简介Windows WDK 10.0.19041.0是一套面向Windows驱动开发者的完整工具包对应Windows 10 2004版本May 2020 Update主要用于构建、调试和测试内核态及用户态驱动程序。压缩包共包含231个文件以187个cab组件包和40个msi安装包为主体另附少量exe与xml配置整体大小约569.23MB便于离线部署完整的WDK开发环境。目前已有1041人学习下载适合正在从事或准备入门Windows驱动开发的工程师参考使用。借助该工具包开发者可以获得WDM/WDF框架支持、INF文件生成与驱动签名工具、WinDbg调试器以及Static Driver Verifier等静态分析工具同时可直接与Visual Studio集成覆盖从项目模板、编码编译到驱动验证的完整流程压缩包内组件划分清晰可依据自身需求选择性安装从而高效搭建适合Win10 2004的驱动开发与测试环境。1. 版本号拆解WDK 10.0.19041.0 到底对应什么系统1.1 从版本号看内核与SDK的对应关系拿到Windows WDK Version10.0.19041.0这串字符第一反应不是去搜怎么下载而是要读懂版本号背后的对应关系。WDK 10.0.19041.0 对应的正是 Windows 10 200420H1版本内核构建号是 19041也就是大家常说的20H1。这个版本号不是随便拍的它和 Windows SDK、Windows 内核版本之间存在严格的对应关系。驱动开发里有个基础概念必须搞清楚WDKWindows Driver KitWindows 驱动开发工具包是构建驱动所需的库、头文件、构建工具和签名工具的集合它依赖 Windows SDK 提供用户态头文件而 SDK 又依赖具体的 Windows 版本。所以当你说用 WDK 10.0.19041.0其实是在说我的目标平台是 Windows 10 2004 及同内核的后续版本。这里经常有人搞混WDK 10.0.19041.0 并不表示只能在这个系统上运行而是表示构建出的驱动以 19041 内核为目标。如果你用这个 WDK 构建的驱动放到 Windows 11内核 22000上通常也能加载因为驱动模型向后兼容但前提是要遵守微软的驱动兼容性规则而且最好在目标系统上做严格测试。我整理了一张对应表方便大家对照WDK 版本对应 Windows 版本内核 Build 号主要特性10.0.17763.0Windows 10 180917763对 KMDF/UMDF、WDF 的成熟支持10.0.18362.0Windows 10 190318362支持新式待机调试改进10.0.19041.0Windows 10 2004/20H119041对 WDF、Filter Driver、MiniFilter 支持稳定企业环境存量最大10.0.22000.0Windows 11 21H222000引入针对 Win11 的安全与兼容性调整10.0.26100.0Windows 11 24H226100最新的 WDK支持新的调试工具链1.2 都 2025 年了为什么还在用 19041这可能是很多新手最不理解的地方微软官网已经有更新版本的 WDK 了为什么还要专门去配一个 10.0.19041.0 的老版本说白了实际工作中选择 WDK 版本不是追新而是看目标。我见过不少企业级项目生产环境里大量部署的还是 Windows 10 2004 到 22H2 的镜像。驱动是跑在目标机器上的如果你开发的驱动目标环境就是这些老版本的 Windows 10用对应的 19041 WDK 反而最稳妥。另外一个很现实的原因很多第三方驱动库、过滤驱动框架、虚拟设备示例代码官方文档明确标注支持到 WDK 10.0.19041.0。比如一些企业安全软件的内核回调驱动、老式打印驱动、扫描仪驱动源码里写死了对 19041 头文件的依赖你用新版 WDK 去编译反而会出现一堆 API 变更后的报错。还有一部分情况是公司内部的 CI/CD 构建服务器还是老环境。在实际项目里构建服务器的 VS 版本、SDK 版本、WDK 版本经常是锁死的团队不会轻易升级因为升级一套驱动构建链的风险远比想象的复杂。所以 10.0.19041.0 这个版本在驱动开发现场依然有大量真实需求。2. 安装 WDK 19041 的正确姿势2.1 前置条件Visual Studio 版本的坑安装 WDK 10.0.19041.0 前必须确认自己的 Visual Studio 版本这是最大的坑没有之一。WDK 10.0.19041.0 官方要求的是 Visual Studio 2019 16.7 或更高版本但注意它并不支持 VS 2022 的某些早期版本。实际操作中我建议直接用 VS 2019因为 VS 2022 配合 19041 WDK 时偶尔会出现 MSBuild 工具链版本不匹配导致驱动项目打不开的情况。具体安装顺序是先装 Visual Studio 2019选择使用 C 的桌面开发工作负载然后在右侧的单个组件里勾选Windows 10 SDK (10.0.19041.0)。这里有个细节如果只装了 WDK 没装对应的 SDK构建驱动时会提示找不到windows.h或ntddk.h因为 WDK 的很多头文件依赖 SDK 的基础头文件。注意安装 VS 时建议把Windows 10 SDK和Windows 11 SDK区分开。即使系统是 Windows 11也不影响安装 Windows 10 SDK 19041。SDK 是可以多版本共存的但 WDK 在安装时会检测到已有 SDK 版本并提示匹配关系。2.2 下载安装与常见默认路径WDK 10.0.19041.0 的安装包可以从微软官方历史版本存档页下载文件名为wdksetup.exe。下载后双击运行建议先看一遍安装说明它会自动检测当前系统里是否有匹配的 SDK。安装组件可以选择完整安装也可以只安装Driver Development Kits下的核心部分。我一般会勾选全部反正磁盘占用也不算大。安装完成后WDK 的默认路径是C:\Program Files (x86)\Windows Kits\10\在这个目录下你会看到这些关键子目录子目录作用关键内容Include\10.0.19041.0驱动开发头文件km,km\wdm.h,km\ntddk.h,shared,umLib\10.0.19041.0驱动链接库km,um,wdf下分别有 x86/x64/arm64bin\10.0.19041.0构建与签名工具inf2cat.exe,signtool.exe,makecert.exeTools辅助调试与测试工具devcon.exe,verifier.exe等build构建脚本与目标定义WindowsDriver.common.targets等因为x64 架构已经是绝对主流所以平时用得最多的是Lib\10.0.19041.0\km\x64和Lib\10.0.19041.0\wdf\x64下的库文件。2.3 命令行确认环境是否就绪有时候安装界面显示成功但在 VS 里新建驱动项目还是报错这时候就需要在命令行里确认一下。打开 PowerShell 或 CMD执行Get-ChildItem C:\Program Files (x86)\Windows Kits\10\Include | Select-Object Name如果输出里能看到10.0.19041.0这个文件夹说明 WDK 的头文件已经安装成功。再执行Get-ChildItem C:\Program Files (x86)\Windows Kits\10\bin | Select-Object Name正常情况下会有一个10.0.19041.0目录里面是各种编译工具。如果这两个目录都有但 VS 里的驱动项目模板还是不可选多半是 VS 与 WDK 的集成组件出了问题重装一下 VS 的适用于驱动开发的 Windows SDK组件就能解决。3. 快速跑通第一个 KMDF 驱动项目3.1 创建驱动项目的模板选择环境配置好之后下一步是新建驱动项目。打开 VS 2019选择创建新项目搜索Driver会出现几个模板Kernel Mode Driver, Empty (KMDF)、Kernel Mode Driver, Empty (Legacy)、User Mode Driver, Empty (UMDF V2) 等。对于入门选Kernel Mode Driver, Empty (KMDF)是最合适的。它自带 WDF 的框架引用会自动帮你链接 WdfDriverEntry省去手动配置链接器的麻烦。选完后 VS 会生成一个基本的项目结构里面包含DriverProject.sln DriverProject.vcxproj DriverProject.inf其中.inf文件是驱动安装信息文件里面定义了驱动类型、服务名、硬件 ID 等关键信息。新建项目时VS 会自动生成一份可用的 INF 模板但很多字段需要手动调整。3.2 最小驱动代码与编译流程一个能编译通过的最小 KMDF 驱动核心代码只需要两个函数DriverEntry和DriverUnload。DriverEntry 是驱动的入口点相当于用户态程序的 main 函数。这个函数里至少要调用WdfDriverCreate来创建 WDF 驱动对象否则 WDF 框架没有被初始化驱动加载会失败。#include ntddk.h #include wdf.h DRIVER_INITIALIZE DriverEntry; EVT_WDF_DRIVER_UNLOAD DriverEvtUnload; NTSTATUS DriverEntry( _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ) { WDF_DRIVER_CONFIG config; NTSTATUS status; WDF_DRIVER_CONFIG_INIT(config, NULL); config.EvtDriverUnload DriverEvtUnload; status WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, config, WDF_NO_HANDLE); if (!NT_SUCCESS(status)) { return status; } DbgPrint(MyFirstDriver: DriverEntry called\n); return STATUS_SUCCESS; } VOID DriverEvtUnload( _In_ WDFDRIVER Driver ) { UNREFERENCED_PARAMETER(Driver); DbgPrint(MyFirstDriver: DriverUnload called\n); }直接按 F7 编译在x64\Debug或x64\Release目录下会生成DriverProject.sys文件和对应生成的.inf、.cat文件。这里经常遇到的一个编译错误是error C2220: warning treated as error - no object file generated这是 WDK 项目默认把警告视为错误导致的。很多驱动源码里用了未初始化的变量或有细微的类型不匹配在新编译器下会触发警告。临时处理方式是在项目属性 - C/C - 高级里把将警告视为错误改为否但从严谨的角度驱动代码最好还是老老实实修掉警告因为内核态一旦有隐患就是蓝屏级别的。3.3 部署到虚拟机测试驱动运行在 Ring 0 层一旦出错整个系统直接蓝屏。所以在开发阶段千万不要在自己日常使用的电脑上直接安装测试驱动务必准备一台 Windows 10 虚拟机。VMware Workstation 或 Hyper-V 都行我习惯用 VirtualBox WinDbg 的组合。虚拟机里要做的准备工作关闭驱动签名强制。在虚拟机启动时按 F8选择禁用驱动程序强制签名或者在管理员 CMD 里执行bcdedit /set testsigning on然后重启。这样虚拟机就允许加载未签名的测试驱动。将编译生成的.sys文件和.inf文件复制到虚拟机里。右键.inf文件选择安装或者用命令行工具devcon.exe install DriverProject.inf Root\MyDriver来安装。如果设备管理器里能看到驱动对应的设备且没有黄色感叹号说明加载成功。然后可以用 DebugView 软件抓取 DbgPrint 输出的日志确认 DriverEntry 是否正常执行。我在实际测试中发现虚拟机不能快照回滚到驱动加载前的状态否则驱动签名测试模式和 WDF 库版本会混乱。建议每次测试前拍一个干净快照出问题直接恢复效率最高。4. 签名、部署与系统集成环节4.1 测试签名非安全启动环境的配置64 位 Windows 默认强制要求驱动签名但测试阶段可以临时开启测试签名模式。上面提到的bcdedit /set testsigning on是第一步但还需要为驱动文件本身生成一个测试证书并签名否则仍然加载不了。生成自签名证书的完整命令流程是makecert -r -pe -ss My -n CNMyTestDriverCert -eku 1.3.6.1.5.5.7.3.3 MyTestDriverCert.cer执行完会在当前目录生成MyTestDriverCert.cer证书文件并把它放入当前用户的我的证书存储区。接下来用pvk2pfx将证书转为.pfx格式供 signtool 使用pvk2pfx -pvk MyTestDriverCert.pvk -spc MyTestDriverCert.cer -pfx MyTestDriverCert.pfx然后对驱动文件签名signtool sign /v /s My /n MyTestDriverCert /t http://timestamp.digicert.com DriverProject.sys这里-t指定时间戳服务器保证证书过期后驱动依然能验证签名时间。需要提醒的是测试签名只能在开启了 testsigning 的机器上加载生产环境的机器默认不会信任这个自签名证书。4.2 证书安装与驱动加载验证签名完成后还要把证书导入到系统受信任的根证书颁发机构和受信任的发布者存储区否则即使开启 testsigning系统依然会认为证书签发者不受信任。导入方法很简单双击.cer文件选择安装证书并手动选择存储区。安装驱动后可以用命令行验证驱动状态。在管理员 CMD 里输入sc query DriverProject如果输出STATE : 4 RUNNING说明驱动已经加载并运行起来了。再用sc stop DriverProject可以停止驱动sc delete DriverProject可以删除驱动服务。有个细节我在踩坑后才知道很多 WDF 驱动在安装后并不会显示为正在运行因为WdfDriverCreate之后如果没有创建任何设备对象驱动服务会处于已停止状态但它其实是按需加载的。这时候可以写一个创建控制设备对象的代码或者直接看系统事件日志里有没有对应驱动加载成功的事件记录。5. 常见问题与排查技巧实录5.1 问题速查表我把这段时间帮同事排查驱动环境的典型问题整理成一个表格遇到类似情况可以直接对照着处理问题现象可能原因解决方法VS 新建项目时找不到驱动模板VS 未安装替 Windows 开发驱动程序组件修改 VS 安装勾选使用 C 的桌面开发下的Windows 驱动开发工具包组件编译报错找不到ntddk.h未安装对应的 Windows 10 SDK 19041单独安装 SDK 10.0.19041.0或使用 VS Installer 添加链接报错unresolved external symbol WdfDriverCreate未链接 WDF 库或项目未选择 KMDF 版本确认项目属性 - Driver Settings - 驱动程序类型为 KMDF且链接WdfDriverEntry.lib部署时提示驱动签名验证失败驱动未签名或 testsigning 未开启按第 4 节流程完成测试签名并确认bcdedit /set testsigning on后重启虚拟机关机蓝屏怀疑驱动导致驱动代码有访问违规或内存越界用 WinDbg 打开虚拟机生成的内核转储使用!analyze -v定位崩溃栈把测试机随时快照备份安装 INF 提示系统找不到指定的文件INF 中的驱动程序文件路径错误或文件名不匹配检查 INF 的CopyFiles节中文件名与.sys实际文件名是否一致且所在目录与安装介质目录是否一致5.2 避坑心得从环境到代码的四个教训第一驱动编译环境与运行的 Windows 子系统没有必然关系但调试时如果你用 WSL 或其他虚拟化工具需要确保物理主机的 Hyper-V 和虚拟机监控程序不会被驱动调试干扰。我遇到过开着 Hyper-V 调试时WinDbg 无法建立内核连接的情况最后把虚拟机切换到独立调试端口才解决。第二WDK 10.0.19041.0 环境下的StartType设置很有讲究。在 INF 文件里定义驱动服务时StartType SERVICE_DEMAND_START表示按需启动适合测试StartType SERVICE_AUTO_START表示开机自启通常用于真正部署的驱动。测试阶段如果用 AUTO_START一旦驱动有 bug开机就会蓝屏而且很难抢救。所以初期开发务必用 DEMAND_START。第三Debug 版本和 Release 版本的驱动程序行为差异比用户态程序大得多。Debug 版本里大量 ASSERT 宏会断言条件如果条件不满足驱动会直接触发 bugcheck。Release 版本这些断言会被剔除。因此测试时用 Debug 版本能捕获更多问题但要评估性能影响。第四用DbgPrint输出日志时注意它不能用%s直接打印UNICODE_STRING它的Buffer是PWSTR需要先转成 ANSI 字符串。否则日志全会乱码排查问题的时候看不出任何有效信息。常见的做法是USHORT length UnicodeStr.Length; CHAR buffer[256]; if (length sizeof(buffer)) { RtlUnicodeBytesToAnsiStringLength... // 具体流程比较啰嗦 }更省事的方案是直接用%wZ格式说明符DbgPrint(RegistryPath: %wZ\n, RegistryPath);这个是 WDK 对UNICODE_STRING提供的专用打印格式比手动转换安全得多。类似的坑我在使用%S时也踩过用对了格式说明符能省下一堆调试时间。5.3 调试时的 WinDbg 配置要点如果要在虚拟机里做真正的内核调试建议配置内核调试的串口或网络连接。我用的是串口方式在虚拟机配置里添加一个命名管道然后在 WinDbg 里连接。宿主机的 WinDbg 命令是WinDbg -k com:pipe,port\\.\pipe\com1,resets0,reconnect虚拟机里的启动配置bcdedit /dbgsettings serial debugport:1 baudrate:115200 bcdedit /debug on这样就能在宿主机上看到驱动的 DbgPrint 输出并在蓝屏时拿到完整的调用栈。初次配置时注意虚拟机要关闭调试模式以外的安全启动功能否则 WinDbg 连接会一直被拒绝。5.4 常见的热词关联为什么总有人问 Windows 子系统问题在整理热词时看到不少人搜适用于 Linux 的 Windows 子系统必须更新到最新版本才能继续以及wsl --update 无法启动服务。虽然 WSL 和 WDK 不是一回事但如果你做驱动开发时同时在用 WSL 来跑构建脚本或 Linux 调试工具这两个环境确实会在同一台机器上共存。我实际遇到的情况是WDK 自带的一些 PowerShell 构建脚本会在 Windows 容器或 Windows 服务环境下执行而这些服务恰好和 WSL 的服务管理存在关联如果 WSL 服务被禁用部分构建任务会卡住。解决方法也比较简单就是用管理员权限执行wsl --update或者手动启动 WSL 服务net start LxssManager核心思路是WSL 的底层服务和 Windows 驱动调试的虚拟机调试监控服务都属于系统服务层两者在资源占用和权限上可能打架。建议在搭建驱动测试环境的机器上养成非必要不常开的习惯用哪个就启哪个避免后台服务互相干扰。写在最后的真实体会配 WDK 10.0.19041.0 这个环境前前后后替身边的人排过不少坑也总结出一点经验驱动开发环境配置这件事表面上是装个软件、建个项目但坑全藏在版本匹配和签名策略里。我见过太多人卡在 VS 版本不匹配卡在编译不过卡在签名被拒其实回头看看都是环境细节没对齐。我个人这两年最深的感受是不要盲目追求新版 WDK。你手上要维护的驱动跑在什么系统上就用对应内核版本的 WDK这个对应关系比最新最好重要得多。而且 10.0.19041.0 这个版本经过几年的沉淀很多兼容性问题早就被社区摸透了遇到问题搜解决方案也容易得多。如果你刚开始接触驱动开发建议从 VM 虚拟机 测试签名 KMDF 空项目这老三样入手先把流程跑通再往里面加业务逻辑这条路最省时间也最不容易半途而废。本文还有配套的精品资源点击获取
返回列表