Объединить форматирование выходных данных пакета /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 будет выводить данные другого типа и / или какие-либо другие факторы, влияющие на этот результат? Я нашел несколько хлебных крошек, но ничего конкретного.
4 ответа
Труба выход из 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
делает эту проверку, и если он находит спецификацию, то правильно распознает кодировку.
С другой стороны, если вы первый echo text
а затем добавить Wmic
вывод - в начале нет спецификации, и вы можете увидеть несовместимую кодировку: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, если он согласован - даже без спецификации. Есть способ заставить echo
производить вывод Unicode (но будьте осторожны, он не создает спецификацию) - используя cmd /u
заставляет вывод для внутренних команд быть unicode.
Я не могу точно сказать, почему поддержка Unicode в CMD настолько ограничена (или, как многие сказали бы, нарушена...) - возможно, проблемы с историей / совместимостью.
И последнее - если вам нужна лучшая поддержка юникода (среди многих других преимуществ), я бы порекомендовал перейти на powershell
more
команда, кажется, не делает преобразование хорошо. Обратите внимание на двойной CR (\r) в выходном файле x2.txt.
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
Если нам нужно только получить 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
Обратитесь к этому ответу:файл 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%"