Windows 11 24H2+ 上 wmic 失效导致 AMD 显卡检测失败的问题与修复

问题背景

Desktopet 是一款基于 Godot 4 开发的桌面宠物应用。由于 Godot 的透明窗口功能在不同 GPU 驱动下行为不一致,AMD 显卡必须使用 D3D12 渲染驱动才能正确显示透明背景;若误用 OpenGL3,窗口背景将渲染为纯黑色。

为此,启动器脚本(launcher.bat / launcher.ps1)在启动游戏前会自动检测显卡类型,对 AMD/Radeon/ATI 显卡强制传入 --rendering-driver d3d12 参数。

问题现象

Windows 11 24H2 及更高版本(包括 25H2)的设备上,AMD 显卡用户反映游戏窗口出现黑色背景,宠物无法正常显示透明效果。

根本原因

launcher.bat 原始检测逻辑依赖 wmic 命令:

1
2
3
4
5
6
7
for /f "skip=1 delims=" %%a in ('wmic path Win32_VideoController get Name 2^>nul') do (
echo "%%a" | findstr /i "AMD Radeon ATI" >nul
if not errorlevel 1 (
set "DRIVER=d3d12"
goto :launch
)
)

wmic.exe 已在 Windows 11 21H1 起标记为弃用,并在 24H2+ 中默认不再安装。

由于命令末尾加了 2>nul 静默错误,wmic 不可用时脚本不会报错,for 循环直接跳过,驱动变量保持默认值 opengl3,AMD 显卡就此被错误地用 OpenGL3 驱动启动,导致透明窗口变黑。

注意:findstr /i "AMD Radeon ATI" 的语义是匹配任意一个关键词,”AMD Radeon RX 7900 XT” 完全可以命中 “AMD” 和 “Radeon”,关键词本身没有问题,问题在于 wmic 根本没有执行。

修复方案

wmic 检测失败后,增加基于 Windows 注册表的回退检测。

Display Adapters 设备类在注册表中有固定的类 GUID:{4d36e968-e325-11ce-bfc1-08002be10318},每个显卡对应一个子键(00000001 等),其中 DriverDesc 值存储了显卡的完整描述名称。reg query 命令在所有 Windows 版本上均可用,无需任何额外依赖。

1
2
3
4
5
6
7
8
9
10
REM Method 2: Fallback to registry query (Display Adapters class GUID)
for /L %%i in (0,1,9) do (
for /f "tokens=2*" %%a in ('reg query "HKLM\SYSTEM\CurrentControlSet\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}\000%%i" /v DriverDesc 2^>nul') do (
echo "%%b" | findstr /i "AMD Radeon ATI" >nul
if not errorlevel 1 (
set "DRIVER=d3d12"
goto :launch
)
)
)

最终脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@echo off
setlocal
REM Desktopet Launcher (Batch) - GPU detection without PowerShell
REM For dev use; installer shortcut uses launcher.ps1

set "DRIVER=opengl3"

REM Method 1: Detect GPU via wmic (may be unavailable on Windows 11 24H2+)
for /f "skip=1 delims=" %%a in ('wmic path Win32_VideoController get Name 2^>nul') do (
echo "%%a" | findstr /i "AMD Radeon ATI" >nul
if not errorlevel 1 (
set "DRIVER=d3d12"
goto :launch
)
)

REM Method 2: Fallback to registry query (Display Adapters class GUID)
for /L %%i in (0,1,9) do (
for /f "tokens=2*" %%a in ('reg query "HKLM\SYSTEM\CurrentControlSet\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}\000%%i" /v DriverDesc 2^>nul') do (
echo "%%b" | findstr /i "AMD Radeon ATI" >nul
if not errorlevel 1 (
set "DRIVER=d3d12"
goto :launch
)
)
)

:launch
start "" "%~dp0Desktopet.exe" --rendering-driver %DRIVER%

诊断方法

如需手动验证显卡检测是否正常,可在命令行分别执行:

1
2
3
4
5
REM 验证 wmic 是否可用
wmic path Win32_VideoController get Name

REM 验证注册表查询是否有效
reg query "HKLM\SYSTEM\CurrentControlSet\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}\0000" /v DriverDesc

若第一条无输出或报错,说明系统已移除 wmic,注册表回退方案为必要修复。

经验总结

  1. 不要依赖已弃用的系统工具做关键检测wmic 已被 Get-CimInstance(PowerShell)取代,新项目应直接使用后者。

  2. 静默错误会掩盖问题2>nul 虽然让脚本更整洁,但在关键检测步骤应有明确的回退或日志。

  3. 注册表是更稳定的数据源reg query 无外部依赖,跨 Windows 版本兼容性更好,适合作为硬件信息查询的兜底方案。

  4. 双渲染驱动策略的必要性:Godot 透明窗口在 AMD + OpenGL3 组合下存在已知缺陷,区分驱动启动是目前的最佳实践。

技术要点

1. Godot 渲染驱动选择

  • D3D12:AMD 显卡透明窗口的正确选择
  • OpenGL3:AMD 显卡下透明窗口会变黑
  • Vulkan:部分设备支持,但兼容性不如 D3D12

2. 注册表查询技巧

  • 设备类 GUID 是固定的:{4d36e968-e325-11ce-bfc1-08002be10318}
  • 显卡设备通常从 0000 开始编号
  • DriverDesc 值包含完整的显卡描述信息

3. 向后兼容性设计

  • 优先使用现代方法(wmic)
  • 提供回退方案(注册表查询)
  • 保持脚本在旧版 Windows 上的可用性

结语

这个问题的解决过程体现了在游戏开发中处理系统兼容性的重要性。随着 Windows 系统的不断更新,开发者需要时刻关注系统工具的变化,并为关键功能设计可靠的备选方案。通过这次修复,我们不仅解决了当前的问题,也为未来可能出现的类似兼容性问题积累了宝贵经验。

对于使用 Godot 引擎开发桌面应用的开发者来说,显卡驱动的正确选择直接影响用户体验。希望这篇技术分享能为遇到类似问题的开发者提供参考和帮助。