结合批处理/WMIC + ANSI/UNICODE 输出格式

结合批处理/WMIC + ANSI/UNICODE 输出格式

在为我的网络创建审计工具时,我发现 WMIC 在输出常规文本时,每个字符之间都会有空格。例如,

这:

@echo off
echo Foo >> "C:\test.txt"
wmic CPU Get AddressWidth >> "C:\test.txt"
wmic CPU Get Description >> "C:\test.txt"

返回此:

Foo 
A d d r e s s W i d t h     

 6 4                         

 D e s c r i p t i o n                                                       

 I n t e l 6 4   F a m i l y   6   M o d e l   6 9   S t e p p i n g   1     

如果我删除(rem)该echo Foo行,则输出格式很好,因为只有一种输出类型:

AddressWidth  
64            
Description                           
Intel64 Family 6 Model 69 Stepping 1  

我读到这是因为 WMIC 输出为 UNICODE,而标准批处理命令输出为 ANSI。两者可以合并以共享通用格式吗?有人可以更深入地解释不同的格式类型、为什么 WMIC 会输出为不同的类型以及/或导致此输出的任何其他因素吗?我发现了一些面包屑,但没有具体内容。

答案1

Wmic通过管道传输输出more
wmic CPU Get AddressWidth |more >> "C:\test.txt"

编辑以获取更多背景信息:您看到的问题是由于wmic输出是 unicode utf-16 造成的。这意味着每个字符(或者更准确地说,大多数字符)都用两个字节编码。wmic还会在输出的开头放置一个所谓的 BOM(字节顺序标记)。请参阅下面的字节内容:

FF FE 44 00 65 00 73 00-63 00 72 00 69 00 70 00 ..D.e.s.c.r.i.p.

前两个字节 (FF FE) 指定 UTF-16 的字节顺序,并允许数据处理工具识别编码 [UTF-16 小端字节序]。
显然,type它会进行此检查,如果找到 BOM,则正确识别编码。
另一方面,如果你第一的 echo text然后附加Wmic输出 - 开头没有 BOM,并且您可以看到不一致的编码:
74 65 78 74 20 0D 0A 44-00 65 00 73 00 63 00 72 text ..D.e.s.c.r

如果您将它通过,type它就无法推断如何解释,/最有可能/假设单字节('ANSI')并且这会导致为不可打印字符产生空格(零,实际上是双字节字符编码的高位字节)。

more处理更多(双关语)情况并为基本 ASCII 字符生成正确的输出,这就是为什么它通常用作此目的的黑客攻击。

补充一点:如果文件一致,某些编辑器(记事本是最简单的例子)将正确显示 utf-16 编码文件 - 即使没有 BOM。有一种方法可以强制echo生成 unicode 输出(但请注意它不会生成 BOM)- 使用cmd /u导致输出内部命令是unicode。

我真的说不出为什么 cmd unicode 支持如此有限(或者像大多数人会说的那样 - 损坏了...) - 可能是历史/兼容性问题。

最后一件事 - 如果你需要更好的unicode支持(以及许多其他好处),我建议迁移到powershell

答案2

more命令似乎不能很好地完成转换。请注意 x2.txt 输出文件中的双 CR (\r)。

C:>wmic diskdrive where "model = 'HGST HTS725050A7E630 ATA Device'" get index >x1.txt
C:>wmic diskdrive where "model = 'HGST HTS725050A7E630 ATA Device'" get index | more >x2.txt
C:>odd x1.txt
000000    ff    fe    49    00    6e    00    64    00    65    00    78    00    20    00    20    00
       377 376   I  \0   n  \0   d  \0   e  \0   x  \0      \0      \0
000010    0d    00    0a    00    30    00    20    00    20    00    20    00    20    00    20    00
        \r  \0  \n  \0   0  \0      \0      \0      \0      \0      \0
000020    20    00    0d    00    0a    00
            \0  \r  \0  \n  \0
000026

C:>odd x2.txt
000000    49    6e    64    65    78    20    20    0d    0d    0a    30    20    20    20    20    20
         I   n   d   e   x          \r  \r  \n   0
000010    20    0d    0d    0a    0d    0d    0a    0d    0a
            \r  \r  \n  \r  \r  \n  \r  \n

更新 看起来 PowerShell 可以更好地处理这个问题。

Get-WmiObject Win32_diskdrive |
    Where-Object { $_.Model -like '*WD*' } |
    Select-Object -Property Model |
    Out-File -PSPath t1.txt

Get-WmiObject Win32_diskdrive |
    Where-Object { $_.Model -like '*WD*' } |
    Select-Object -Property Model |
    Out-File -PSPath t2.txt -Encoding default

很明显,CIM 是 PowerShell 未来的发展方向。最好现在就开始使用它。

Get-CimInstance CIM_DiskDrive |
    Where-Object { $_.Model -like '*WD*' } |
    Select-Object -Property Model |
    Out-File -PSPath t1.txt

Get-CimInstance CIM_DiskDrive |
    Where-Object { $_.Model -like '*WD*' } |
    Select-Object -Property Model |
    Out-File -PSPath t2.txt -Encoding default

答案3

如果我们只需要让 WMIC 将其数据添加到日志文件,请尝试以下操作:

测试脚本

set Log=%~dpn0.log&::
set L=^>^>"%Log%" 2^>^&1 echo&::

%L% ^
wmic /APPEND:"%Log%" /locale:ms_409 service get name,startname,state,status&::
wmic /APPEND:"%Log%" /locale:ms_409 service get name,startname,state,status&::

notepad "%Log%"

exit

生成的 Test.log 文件将如下所示:

wmic /APPEND:"D:\Test\T.log" /locale:ms_409 service get name,startname,state,status
Name                                      StartName                    State    Status  
AdobeARMservice                           LocalSystem                  Running  OK      
AJRouter                                  NT AUTHORITY\LocalService    Stopped  OK      
ALG                                       NT AUTHORITY\LocalService    Stopped  OK      
AppHostSvc                                LocalSystem                  Running  OK      
AppIDSvc                                  NT Authority\LocalService    Stopped  OK      

答案4

参考这个答案:WMIC.bat 文件无法正确导出/输出

More此批处理文件向您展示了使用和不使用命令将结果导出到文本文件的行为的区别。

@echo off
REM https://stackoverflow.com/questions/34075745/wmic-bat-file-will-not-export-output-properly?answertab=active#tab-top
Title WMIC file will not export/output properly
set "WithoutMore=%~dp0WithoutMore.txt"
set "WithMore=%~dp0WithMore.txt"

(
    wmic csproduct
    wmic cpu get name,AddressWidth,Description
    wmic diskdrive get model,size
    WMIC PATH Win32_Battery Get EstimatedChargeRemaining
    ipconfig /all
)>"%WithoutMore%"

Start "" "%WithoutMore%"

(
    wmic csproduct
    wmic cpu get name,AddressWidth,Description
    wmic diskdrive get model,size
    WMIC PATH Win32_Battery Get EstimatedChargeRemaining
    ipconfig /all
) | more >"%WithMore%"

Start "" "%WithMore%"

相关内容