No PowerShell, como posso analisar uma saída pré-formatada?

1

Existe algum conjunto de ferramentas para obter uma saída baseada em texto e canalizá-la para um objeto dinâmico que possa ser consultado como colunas?

Especificamente, estou invocando ..

query session /server:MYSERVER

.. que está saindo ..

SESSIONNAME       USERNAME                 ID  STATE   TYPE        DEVICE 
services                                    0  Disc                        
console           Jon                       1  Active  

Esta é a minha primeira tarefa em uma função de DevOps, para agir de acordo com essa saída com base nas condições das colunas, mas depois de várias tentativas de canalizar para o foreach etc. percebi que são apenas várias linhas de strings.

O que eu esperava era algo como ...

query session /server:MYSERVER | foreach '
{ '
    if ($_.Username -eq "Jon") '
    {'
        custom-action $_.ID '
    } '
}

(Note que eu não preciso necessariamente avaliar o nome de usuário, ou não apenas o nome de usuário, estou apenas fazendo isso neste exemplo.)

Obviamente, isso não funcionará porque isso ...

query session /server:192.168.1.103 | foreach { echo $_.GetType() }

.. gera isso ..

IsPublic IsSerial Name                                     BaseType                                                    
-------- -------- ----                                     --------                                                    
True     True     String                                   System.Object                                               
True     True     String                                   System.Object                                               
True     True     String                                   System.Object     

A única solução que encontrei é a extração manual das colunas usando String.Substring (). Eu estava esperando que houvesse ferramentas do PowerShell que automatizassem isso.

[[ Este é um exemplo, ]], mas alguns as colunas estão em branco e as colunas de largura fixa não têm a mesma largura entre elas, portanto, a análise seria muito mais manual do que os exemplos. Eu esperava que as atualizações de versão do Powershell pudessem ter ferramentas melhores, talvez?

Usando o Windows Server 2012 R2 (que possui o PowerShell 4).

    
por stimpy77 10.09.2013 / 08:34

3 respostas

2

Não há nada embutido.

No entanto, não deve ser muito difícil criar um auxiliar (em um módulo para fácil reutilização, é claro) que leva uma definição de cada coluna (por exemplo, nome, posição inicial, comprimento, tipo, ...; ou talvez critérios alternativos para separar as colunas se os comprimentos não puderem ser predeterminados) e criar um objeto personalizado.

    
por 10.09.2013 / 10:06
1

Este é um comentário para a resposta de Richard.

Isso é o que eu criei. Um seria foreach {} em todas as linhas (exceto a primeira linha, que é $ head) e passaria para essa função.

Function ParseFixedWidthCols($head,$line) {
    $colnamematches = $head | select-string "(\s*\w+\b\s*)" -allmatches | foreach { $_.matches }
    $cols = @()
    for ($ci=0; $ci -lt $colnamematches.Count; $ci++) {
        $col = $colnamematches[$ci].Value
        $cols += $col
    }
    $col = $cols[0]
    $ret = New-Object PSObject
    $cc = 0
    for ($ci=0; $ci -lt $cols.Count; $ci++) {
        $value = $line.Substring($cc, $cols[$ci].Length)
        $ret | Add-Member -MemberType NoteProperty -name $cols[$ci].Trim() -value $value.Trim()
        $cc += $cols[$ci].Length
    }
    return ret;
}
    
por 10.09.2013 / 12:07
0

Muitos desses utilitários pré-PowerShell consultam várias APIs do Windows subjacentes, como o WMI. Antes de cavar a análise de texto eu tentaria encontrar onde o utilitário obtém suas informações e iniciar a partir daí. Para o seu caso particular, eu não ficaria surpreso se ele estivesse realmente consultando a classe Win32_LogonSession do WMI, que você pode enumerar facilmente usando o PowerShell - e obter objetos formatados corretamente. Essa abordagem pode não funcionar em todas as situações, mas seria um bom ponto de partida, pelo menos.

$users = get-wmiobject -query "Select * from Win32_LogonSession"

Com um pouco de googling, isso parece uma função promissora para o que você precisa: função get-loggedonononferior

    
por 11.09.2013 / 09:04