与操作系统语言相关的输出%SystemRoot%\System32\systeminfo.exe
是以ASCII/ANSI/OEM编码的字符,这意味着使用在命令提示符窗口中运行时显示的代码页每个字符一个字节chcp
。代码页取决于为用于运行批处理文件的帐户配置的国家(地区)。只要感兴趣的数据不包含代码值大于 127 的字符(非ASCII字符),代码页并不重要。
systeminfo
filter by的输出findstr
是二进制文件,文件中的十六进制偏移量到冒号,字节的十六进制值,以及分号后的 ASCII 表示:
0000h: 48 6F 73 74 20 4E 61 6D 65 3A 20 20 20 20 20 20 ; Host Name:
0010h: 20 20 20 20 20 20 20 20 20 20 20 50 47 56 2D 50 ; PGV-P
0020h: 46 31 36 35 48 4E 4E 0D 0A 4F 53 20 4E 61 6D 65 ; F165HNN..OS Name
0030h: 3A 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 ; :
0040h: 20 20 20 20 4D 69 63 72 6F 73 6F 66 74 20 57 69 ; Microsoft Wi
0050h: 6E 64 6F 77 73 20 31 30 20 50 72 6F 0D 0A 4F 53 ; ndows 10 Pro..OS
0060h: 20 56 65 72 73 69 6F 6E 3A 20 20 20 20 20 20 20 ; Version:
0070h: 20 20 20 20 20 20 20 20 20 31 30 2E 30 2E 31 38 ; 10.0.18
0080h: 33 36 33 20 4E 2F 41 20 42 75 69 6C 64 20 31 38 ; 363 N/A Build 18
0090h: 33 36 33 0D 0A 4F 72 69 67 69 6E 61 6C 20 49 6E ; 363..Original In
00a0h: 73 74 61 6C 6C 20 44 61 74 65 3A 20 20 20 20 20 ; stall Date:
00b0h: 37 2F 32 32 2F 32 30 31 39 2C 20 36 3A 32 38 3A ; 7/22/2019, 6:28:
00c0h: 30 31 20 50 4D 0D 0A 53 79 73 74 65 6D 20 4D 61 ; 01 PM..System Ma
00d0h: 6E 75 66 61 63 74 75 72 65 72 3A 20 20 20 20 20 ; nufacturer:
00e0h: 20 20 4C 45 4E 4F 56 4F 0D 0A 53 79 73 74 65 6D ; LENOVO..System
00f0h: 20 4D 6F 64 65 6C 3A 20 20 20 20 20 20 20 20 20 ; Model:
0100h: 20 20 20 20 20 32 30 4A 4D 30 30 30 39 55 53 0D ; 20JM0009US.
0110h: 0A 53 79 73 74 65 6D 20 54 79 70 65 3A 20 20 20 ; .System Type:
0120h: 20 20 20 20 20 20 20 20 20 20 20 20 78 36 34 2D ; x64-
0130h: 62 61 73 65 64 20 50 43 0D 0A 42 49 4F 53 20 56 ; based PC..BIOS V
0140h: 65 72 73 69 6F 6E 3A 20 20 20 20 20 20 20 20 20 ; ersion:
0150h: 20 20 20 20 20 4C 45 4E 4F 56 4F 20 4E 31 51 45 ; LENOVO N1QE
0160h: 54 38 37 57 20 28 31 2E 36 32 20 29 2C 20 32 2F ; T87W (1.62 ), 2/
0170h: 32 37 2F 32 30 32 30 0D 0A 54 6F 74 61 6C 20 50 ; 27/2020..Total P
0180h: 68 79 73 69 63 61 6C 20 4D 65 6D 6F 72 79 3A 20 ; hysical Memory:
0190h: 20 20 20 20 38 2C 30 37 32 20 4D 42 0D 0A ; 8,072 MB..
的输出%SystemRoot%\System32\wbem\wmic.exe
始终是使用带有字节顺序标记(BOM)的 UTF-16 Little Endian 编码的Unicode编码。所以两个使用的命令行的输出是每个字符两个字节。wmic
命令行wmic bios get serialnumber /Format:list
以二进制形式生成输出:
0000h: FF FE 0D 00 0A 00 0D 00 0A 00 53 00 65 00 72 00 ; ÿþ........S.e.r.
0010h: 69 00 61 00 6C 00 4E 00 75 00 6D 00 62 00 65 00 ; i.a.l.N.u.m.b.e.
0020h: 72 00 3D 00 50 00 46 00 31 00 36 00 35 00 48 00 ; r.=.P.F.1.6.5.H.
0030h: 4E 00 4E 00 0D 00 0A 00 0D 00 0A 00 0D 00 0A 00 ; N.N.............
前两个字节FF FE
是 UTF-16 Little Endian 的字节顺序标记。每个 ASCII 字符用两个字节(16 位)编码,高字节的值为 0。换行符是回车符(0D 00)和换行符(0A 00)。首先输出两个空行,然后是包含感兴趣数据的行,最后又是两个空行。
命令行wmic cpu get name
以二进制形式生成输出:
0000h: FF FE 0D 00 0A 00 0D 00 0A 00 4E 00 61 00 6D 00 ; ÿþ........N.a.m.
0010h: 65 00 3D 00 49 00 6E 00 74 00 65 00 6C 00 28 00 ; e.=.I.n.t.e.l.(.
0020h: 52 00 29 00 20 00 43 00 6F 00 72 00 65 00 28 00 ; R.). .C.o.r.e.(.
0030h: 54 00 4D 00 29 00 20 00 69 00 35 00 2D 00 36 00 ; T.M.). .i.5.-.6.
0040h: 33 00 30 00 30 00 55 00 20 00 43 00 50 00 55 00 ; 3.0.0.U. .C.P.U.
0050h: 20 00 40 00 20 00 32 00 2E 00 34 00 30 00 47 00 ; .@. .2...4.0.G.
0060h: 48 00 7A 00 0D 00 0A 00 0D 00 0A 00 0D 00 0A 00 ; H.z.............
通过cmd.exe
处理批处理文件来重定向 Unicode 输出more
,现在每个字符一个字节输出到该批处理文件。但是 Windows 命令处理器在解释 UTF-16 LE 编码的行时有一个错误,因为它可以在使用以下命令行时看到:
wmic bios get serialnumber /Format:list | more >output.txt
该文件output.txt
包含二进制字节:
0000h: 0D 0D 0A 0D 0D 0A 53 65 72 69 61 6C 4E 75 6D 62 ; ......SerialNumb
0010h: 65 72 3D 50 46 31 36 35 48 4E 4E 0D 0D 0A 0D 0D ; er=PF165HNN.....
0020h: 0A 0D 0D 0A 0D 0A 0D 0A ; ........
每个 Unicode 编码的回车 + 换行 (0D 00 0A 00) 变成 ASCII 编码的回车 + 回车 + 换行 (0D 0D 0A)。
这才是真正的问题。.
使用正则表达式搜索字符串匹配所有行与至少一个字符的附加回车结果,空行也与此正则表达式搜索字符串匹配,输出从 Unicode 转换为 ASCII 不正确。
这取决于使用的文本编辑器如何解释无效的换行符序列。大多数文本编辑器将不带换行符的回车解释为行终止,但findstr
不这样做。
一种解决方案是显式搜索包含感兴趣数据的行。
@echo off
setlocal EnableExtensions DisableDelayedExpansion
(
%SystemRoot%\System32\systeminfo.exe | %SystemRoot%\System32\findstr.exe /L /C:"Host Name" /C:"OS Name" /C:"OS Version" /C:"Original Install Date" /C:"System Manufacturer" /C:"System Model" /C:"System Type" /C:"Total Physical Memory"
%SystemRoot%\System32\wbem\wmic.exe BIOS GET SerialNumber /VALUE | %SystemRoot%\System32\findstr.exe /L /C:SerialNumber
%SystemRoot%\System32\wbem\wmic.exe CPU GET Name /VALUE | %SystemRoot%\System32\findstr.exe /L /C:Name
echo %USERDOMAIN%\%USERNAME%
) >"%ComputerName%.txt"
endlocal
写入文件的数据%ComputerName%.txt
完全以 ASCII 编码,到处都用作0D 0A
行终止符。
有关代码小改动的一些附加信息:
- 该命令
more
被省略,因为不是真正必要的。从 Unicode 到 ASCII 的不正确转换是由 Windows 命令处理器完成的cmd.exe
。
- 此批处理文件未启用延迟的环境变量扩展,因为根本不需要。
- 所有可执行文件都使用众所周知的全限定文件名指定。因此
cmd.exe
不必使用环境变量的值PATHEXT
和PATH
.
- WMIC选项
/Format:list
被替换为/VALUE
产生相同输出的选项。
- FINDSTR与选项一起运行
/L
以明确指示findstr
运行文字搜索,尽管这是使用选项的默认设置/C:
。
一个更好的批处理文件代码是:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
(
%SystemRoot%\System32\systeminfo.exe | %SystemRoot%\System32\findstr.exe /L /C:"Host Name" /C:"OS Name" /C:"OS Version" /C:"Original Install Date" /C:"System Manufacturer" /C:"System Model" /C:"System Type" /C:"Total Physical Memory"
for /F "tokens=1* delims==" %%I in ('%SystemRoot%\System32\wbem\wmic.exe BIOS GET SerialNumber /VALUE') do if not "%%J" == "" echo Serial Number: %%J
for /F "tokens=1* delims==" %%I in ('%SystemRoot%\System32\wbem\wmic.exe CPU GET Name /VALUE') do if not "%%J" == "" echo CPU Name: %%J
echo Domain\User Name: %USERDOMAIN%\%USERNAME%
) >"%ComputerName%.txt"
endlocal
使用WMIC确定并使用ECHO输出的附加数据以与systeminfo
.
注意:如果环境变量的值或环境变量的值包含或,最后一个echo
命令行是不安全的。100% 安全将是:USERDOMAIN
USERNAME
)
&
@echo off
setlocal EnableExtensions DisableDelayedExpansion
(
%SystemRoot%\System32\systeminfo.exe | %SystemRoot%\System32\findstr.exe /L /C:"Host Name" /C:"OS Name" /C:"OS Version" /C:"Original Install Date" /C:"System Manufacturer" /C:"System Model" /C:"System Type" /C:"Total Physical Memory"
for /F "tokens=1* delims==" %%I in ('%SystemRoot%\System32\wbem\wmic.exe BIOS GET SerialNumber /VALUE') do if not "%%J" == "" echo Serial Number: %%J
for /F "tokens=1* delims==" %%I in ('%SystemRoot%\System32\wbem\wmic.exe CPU GET Name /VALUE') do if not "%%J" == "" echo CPU Name: %%J
) >"%ComputerName%.txt"
setlocal EnableDelayedExpansion
echo Domain\User Name: !USERDOMAIN!\!USERNAME!>>"%ComputerName%.txt"
endlocal
endlocal
要了解使用的命令及其工作原理,请打开命令提示符窗口,在其中执行以下命令,并仔细阅读每个命令显示的所有帮助页面。
echo /?
endlocal /?
findstr /?
for /?
if /?
setlocal /?
systeminfo /?
wmic /?
wmic bios /?
wmic bios get /?
wmic cpu /?
wmic cpu get /?