Questão Combine formatação de saída em lote / WMIC + ANSI / UNICODE


Ao criar uma ferramenta de auditoria para a minha rede, estou descobrindo que o WMIC está saindo com espaços entre cada caractere quando acompanhado pelo eco do texto normal. Por exemplo,

Este:

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

Retorna isso:

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     

Se eu remover (rem) a echo Foo linha, a saída é formatada bem desde que há apenas um tipo de saída:

AddressWidth  
64            
Description                           
Intel64 Family 6 Model 69 Stepping 1  

Eu estou lendo que isso é porque saídas WMIC para UNICODE, enquanto saída de comandos em lote padrão para ANSI. Ambos podem ser unidos para compartilhar um formato comum? Alguém pode, por favor, explicar com mais profundidade os diferentes tipos de formato, por que a WMIC produziria para um tipo diferente e / ou quaisquer outros fatores contribuintes para essa saída? Eu encontrei alguns migalhas de pão, mas nada concreto.


4


origem




Respostas:


Canalizar a saída de Wmic através more:
wmic CPU Get AddressWidth |more >> "C:\test.txt"

Edite para mais informações: o problema que você vê é devido a wmic saída sendo unicode utf-16. Isso significa que cada caractere (ou mais corretamente, a maioria deles) é codificado em dois bytes. wmic também coloca uma chamada BOM (byte order mark) no início da saída. Veja o conteúdo do byte abaixo:

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

Esses dois primeiros bytes (FEF) especificam endianness para UTF-16 e permitem que ferramentas de processamento de dados reconheçam a codificação [sendo UTF-16 little endian].
Obviamente type isso verifica e, se encontrar a lista de materiais, reconhece corretamente a codificação.
Por outro lado, se você primeiro  echo text e depois anexar Wmic saída - não há lista de materiais no começo e você pode ver a codificação inconsistente:
74 65 78 74 20 0D 0A 44-00 65 00 73 00 63 00 72 text ..D.e.s.c.r

Se você colocar isso type não pode inferir como interpretar, / mais provável / assume um único byte ('ANSI') e isso resulta em espaços produzidos para caracteres não imprimíveis (zeros, sendo de fato bytes de alta ordem de codificação de caracteres de dois bytes).

more lida com mais casos (trocadilhos) e produz resultados corretos para caracteres ASCII básicos, por isso é comumente usado como um hack para essa finalidade.

Uma nota adicional: alguns editores (sendo o bloco de notas o exemplo mais simples) irão exibir corretamente o arquivo codificado utf-16 se ele for consistente - mesmo sem BOM. Existe uma maneira de forçar echo para produzir saída unicode (mas cuidado, ela não produz BOM) - usando cmd /u provoca saída para comandos internos para ser unicode.

Eu não posso realmente dizer por que o suporte a cmd unicode é tão limitado (ou como diria a maioria - quebrado ...) - provavelmente problemas históricos / de compatibilidade.

A última coisa - se você precisar de melhor suporte a unicode (entre muitos outros benefícios) eu recomendaria migrar para powershell 


8



Isso é semelhante à resposta aceita no link que eu postei, o que funciona, mas não aborda realmente qual é o problema ou como moreresolve o problema. Eu editei minha pergunta para clareza - root
Eu expandi minha resposta (devo admitir que não li a resposta vinculada, mas more truque é comum) - wmz
Muito minucioso e bem explicado, obrigado. - root


o more comando não parece fazer a conversão bem. Observe o CR duplo (\ r) no arquivo de saída 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

Atualizar Parece que o PowerShell pode lidar com isso melhor.

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

É claro que a CIM é a direção que o PowerShell está seguindo no futuro. Melhor começar a usá-lo agora.

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

2



Existe uma correção para esse problema? - thaimin
@thaimin - Atualizou a resposta com possíveis soluções para o problema de conversão de codificação. - lit