如何检查 WMIC 是否输出空字符串或请求的 Windows 原始产品密钥



我尝试使用wmic命令来检查 Windows 产品密钥。我检查了一下,看看它是否返回 Windows 产品密钥或空行。但是条件IF "%%Z" == ""以及IF [%%Z] EQU []结果总是在执行Echo Lose,即key不是一个空字符串。

以下示例是显示第一部分的更简单版本。

@ECHO OFF
set cmd=wmic path softwarelicensingservice get OA3xOriginalProductKey
for /f "tokens=1 skip=1" %%Z in ('%cmd% ^| findstr /r /v "^$"') do (set RESULT=%%Z)
IF "%%Z" == "" (Echo Key %RESULT%) Else (Echo Lose)
PAUSE

分配给循环变量(如Z)的字符串值不能在循环外部引用。条件IF "%%Z" == ""始终将固定字符串"%Z"与固定字符串进行比较,""当然,固定字符串永远不会相等。条件IF [%%Z] EQU []首先导致尝试将固定字符串[%Z]转换为 32 位有符号整数值,该值在第一个字符[时已经失败,因此接下来要对[%Z]进行字符串比较[]也永远不会相等。

使用以下代码之前需要了解的一些事实:

  • SoftwareLicensingService 类仅在 Windows Vista 或更新的 Windows 客户端版本以及 Windows Server 2008 和更新的 Windows 服务器版本上可用。此类在 Windows Vista 和 Windows Server 2008.
    Windows 7 和 Windows Server 2008 R2 上的 SoftwareLicensingService 类没有OA3xOriginalProductKey属性OA3xOriginalProductKey
  • Microsoft文档中没有太多关于OA3xOriginalProductKey的文章。有 Windows 10 版本 1703 基本级别 Windows 诊断事件和字段Microsoft文档页面,以及 Windows 安装程序或就地升级完成后 OSD 任务序列不会继续,以及部署 Windows 10 企业版许可证,其中包含有关OA3xOriginalProductKey的一些信息。看起来此属性是在用于 Windows 8、Windows 8.1 和 Windows 10 客户端版本的 OEM 激活 3.0 系统中引入的。

可以使用以下批处理代码:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "RESULT="
for /F "delims=" %%I in ('%SystemRoot%System32wbemwmic.exe PATH SoftwareLicensingService GET OA3xOriginalProductKey /VALUE 2^>nul') do for /F "tokens=1* delims==" %%J in ("%%I") do set "RESULT=%%K"
if not defined RESULT echo Lose& goto EndBatch
echo Key %RESULT%
rem Other commands making use of environment variable RESULT.
:EndBatch
endlocal
pause

WMIC没有为属性OA3xOriginalProductKey输出值的情况下,使用 FINDSTR 过滤掉空行没有真正的帮助,因为使用 UTF-16 编码的WMIC的 Unicode 输出带有字节顺序标记 (BOM) 的小端序被在后台启动的cmd.exe实例处理错误,选项/C和指定的命令行作为将输出重定向到FINDSTR的附加参数转换为每个字符编码一个字节。

在这种情况下,环境变量RESULT定义为将单个回车符作为分配给环境变量的字符串。

处理WMIC的 Unicode 输出时cmd.exe的这种怪癖的解决方法是使用选项/VALUE在一行上获取属性OA3xOriginalProductKey的名称及其值,一行之间有一个等号,数据行上方和下方的两个空行。

所有五个捕获的行都由FOR处理,通常完全忽略空行。但是FOR没有空行要处理,因为cmd.exe将 UTF-16 编码的回车 + 换行 (0D 00 0A 00) 解释为回车 + 回车 + 换行 (0D 0D 0A) 的错误导致四个空行被解释为具有单个回车符的行,而开头带有OA3xOriginalProductKey=的行作为行在末尾也有一个额外的回车符。

因此,每条末尾带有回车符的整行首先分配给循环变量I

另一个FOR循环用于处理分配给循环变量的字符串I这会导致在处理之前从字符串值中删除错误的回车符。

因此,对于四个空行,第二个FOR没有要处理的字符串,因此确实忽略了四个空行。

第二个FOR循环通过使用等号作为字符串分隔符,将包含文本数据的唯一行拆分为两个子字符串。第一个子字符串OA3xOriginalProductKey分配给循环变量J,等号之后的第二个子字符串是分配给下一个的键,但一个循环K如果有键,否则K没有定义,接下来执行的命令 SET%%K替换为空字符串。

批处理文件使用前两行完全定义了所需的执行环境,并确保环境变量RESULT恰好没有使用第三个命令行在批处理文件外部定义。

带有两个FORSET命令的长命令行之后的IF条件首先检查环境变量RESULT现在是否使用实际键(而不仅仅是回车)定义,以确定接下来要执行的ECHO命令。

长命令行也可以是:

for /F "delims=" %%I in ('%SystemRoot%System32wbemwmic.exe PATH SoftwareLicensingService GET KeyManagementServiceMachine /VALUE 2^>nul') do for /F "tokens=2 delims==" %%J in ("%%I") do set "RESULT=%%J"

在这种情况下,只有OA3xOriginalProductKey=后面的字符串分配给指定的循环变量,JWMIC是否有密钥输出。否则,秒FOR没有任何东西可以分配给J,因此命令SET根本不执行,导致环境变量列表中仍然不存在RESULT

要了解使用的命令及其工作原理,请打开命令提示符窗口,在其中执行以下命令,然后完整而仔细地阅读每个命令的显示帮助页面。

  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • pause /?
  • rem /?
  • set /?
  • setlocal /?
  • wmic /?
  • wmic path /?
  • wmic path softwarelicensingservice /?
  • wmic path softwarelicensingservice get /?

阅读有关使用命令重定向运算符的Microsoft文档,了解2>nul|的说明。重定向运算符>|必须使用 FOR 命令行上的插入符号^进行转义,以便在 Windows 命令解释器在执行命令FOR之前处理此命令行时将其解释为文字字符,该命令使用在后台启动的单独命令进程执行嵌入式命令行。

相关内容

最新更新