web-dev-qa-db-ja.com

バッチ/ 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行、出力タイプが1つしかないため、出力は適切にフォーマットされます。

AddressWidth  
64            
Description                           
Intel64 Family 6 Model 69 Stepping 1  

これは、WMICがUNICODEに出力するのに対し、標準のバッチコマンドはANSIに出力するためだと読んでいます。両方を結合して共通のフォーマットを共有できますか?誰かがさまざまな形式の種類、WMICがさまざまな種類に出力する理由、および/またはこの出力に寄与するその他の要因について詳しく説明できますか? パン粉 をいくつか見つけましたが、具体的なものはありません。

7
root

出力をWmicからmoreにパイプします。
wmic CPU Get AddressWidth |more >> "C:\test.txt"

背景を少し編集してください:表示される問題は、wmicの出力がユニコードutf-16であるためです。これは、各文字(より正確には、ほとんどの文字)が2バイトでエンコードされることを意味します。 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.

これらの最初の2バイト(FF FE)は、UTF-16のエンディアンを指定し、データ処理ツールがエンコーディングを認識できるようにします[UTF-16リトルエンディアン]。
明らかにtypeがこのチェックを行い、BOMが見つかった場合は、エンコーディングを正しく認識します。
一方、firstecho 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を介してそれを解釈すると、解釈方法を推測できません。/ほとんどの場合、/は1バイト( 'ANSI')を想定し、これにより、印刷不可能な文字(ゼロ、実際には上位バイト)のためにスペースが生成されます。 2バイトの文字エンコード)。

moreは、より多くの(しゃれを意図した)ケースを処理し、基本的なASCII文字)の正しい出力を生成します。そのため、この目的のハックとして一般的に使用されます。

1つの追加の注意:一部のエディター(メモ帳が最も単純な例です)は、BOMがなくても、一貫性がある場合、utf-16でエンコードされたファイルを適切に表示します。 echoに強制的にユニコード出力を生成させる方法があります(ただし、BOMを生成しないことに注意してください)-cmd /uを使用すると、内部コマンドの出力がユニコードになります。

なぜcmdユニコードのサポートがそれほど制限されているのか(またはほとんどの人が言うように-壊れている...)-おそらく歴史的/互換性の問題を私は本当に言うことはできません。

最後に、(他の多くの利点の中でも)より優れたUnicodeサポートが必要な場合は、powershellに移行することをお勧めします。

10
wmz

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

pdate 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
lit

WMICにデータをログファイルに追加させるだけでよい場合は、以下を試してください。

Test.bat

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      
0
Installer