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

How to check if WMIC outputs an empty string or the requested original product key of Windows?

我尝试使用 wmic 命令来检查 Windows 产品密钥。我检查它是否返回 Windows 产品密钥或空行。但是条件 IF "%%Z" == ""IF [%%Z] EQU [] 总是导致执行 Echo Lose,即键不是空字符串。

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

@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][] 的字符串比较也不相等。

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

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

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "RESULT="
for /F "delims=" %%I in ('%SystemRoot%\System32\wbem\wmic.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 没有输出值,使用 FINDSTR 过滤掉空行没有实际帮助 属性 OA3xOriginalProductKey 因为 WMIC 的 Unicode 输出使用带字节顺序标记 (BOM) 的 UTF-16 Little Endian 编码被 cmd.exe 处理错误实例在后台启动,选项 /C 和指定的命令行作为将输出重定向到 FINDSTR 的附加参数,每个字符编码转换为单个字节。

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

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

所有五个捕获的行都由 FOR 处理,通常会完全忽略空行。但是 FOR 没有要处理的空行,因为 cmd.exe 解释 UTF-16 编码回车 return + 换行 (0D 00 0A 00) as carriage return + carriage return + line-feed (0D 0D 0A) 导致四个空行被解释为带有单个 carriage return 的行和该行以 OA3xOriginalProductKey= 开头作为行,最后还有一个额外的回车 return。

出于这个原因,每行末尾带有回车 return 的整行都首先分配给循环变量 I.

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

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

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

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

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

长命令行也可以是:

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

在这种情况下,如果 WMIC 根本没有输出键,则仅将 OA3xOriginalProductKey= 之后的字符串分配给指定的循环变量 J。否则,FOR 没有任何东西可以分配给 J,因此根本不会执行命令 SET,导致 RESULT 仍然不存在于环境变量列表中。

为了了解使用的命令及其工作原理,请打开 command prompt window,在其中执行以下命令,并仔细阅读每个命令显示的所有帮助页面。

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

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