No PowerShell, objetos são a base de tudo. Quase tudo que você manipula – arquivos, processos, serviços – é representado como um objeto com propriedades e métodos. Mas e quando você precisa criar seus próprios objetos para representar dados personalizados, como um registro de usuário, um item de inventário ou um resultado de uma consulta? É aí que entra o PSCustomObject, uma maneira eficiente e leve de criar objetos customizados sem a complexidade de classes formais.

O PSCustomObject é uma construção especial do PowerShell que permite criar objetos com um conjunto fixo de propriedades de forma rápida e com sintaxe limpa. Diferente de usar New-Object PSObject ou Add-Member, o PSCustomObject é otimizado para desempenho e legibilidade. Nesta aula, vamos explorar como criá-los, acessar e modificar suas propriedades, e aplicá-los em cenários reais.

Criando objetos customizados

Antes do PSCustomObject, era comum criar objetos usando New-Object PSObject e depois adicionar propriedades com Add-Member. Esse método funciona, mas é verboso e menos performático. Com o PSCustomObject, você define todas as propriedades de uma só vez, usando uma hashtable.

A sintaxe básica é: [PSCustomObject]@{ Propriedade1 = 'Valor1'; Propriedade2 = 'Valor2' }. O resultado é um objeto com as propriedades definidas, que você pode armazenar em uma variável, passar por pipelines, ou usar em expressões.

# Criando um objeto customizado simples
$usuario = [PSCustomObject]@{
    Nome = 'João Silva'
    Email = 'joao@exemplo.com'
    Idade = 30
}

# Exibindo o objeto
$usuario

No exemplo acima, $usuario é um objeto com três propriedades: Nome, Email e Idade. Você pode acessar cada propriedade usando a notação de ponto: $usuario.Nome. Além disso, objetos criados dessa forma são compatíveis com cmdlets como Select-Object, Where-Object e Export-Csv.

[PSCustomObject]@{}

A expressão [PSCustomObject]@{} é um acelerador de tipo (type accelerator) que instrui o PowerShell a interpretar a hashtable como um objeto customizado. A hashtable deve conter pares chave-valor, onde a chave se torna o nome da propriedade e o valor, o valor da propriedade. É importante notar que a ordem das propriedades é preservada a partir do PowerShell 3.0.

Você também pode criar objetos vazios e depois adicionar propriedades, mas não é recomendado porque o PSCustomObject é imutável em termos de estrutura (não é possível adicionar novas propriedades depois de criado, a menos que use Add-Member). Para objetos dinâmicos, prefira PSObject ou classes do PowerShell 5.0+.

# Criando um objeto com diferentes tipos de valores
$produto = [PSCustomObject]@{
    Nome = 'Notebook'
    Preco = 2500.00
    Quantidade = 10
    Disponivel = $true
}

# Acessando propriedades
$produto.Nome
$produto.Preco

# Modificando um valor (isso é permitido)
$produto.Preco = 2400.00
$produto

Observe que você pode modificar o valor de uma propriedade existente, mas não pode adicionar uma nova propriedade diretamente. Se precisar adicionar, use $produto | Add-Member -MemberType NoteProperty -Name 'Categoria' -Value 'Eletrônicos'.

Propriedades

As propriedades de um PSCustomObject são do tipo NoteProperty. Você pode acessá-las com notação de ponto ($objeto.Propriedade) ou com a sintaxe de dicionário ($objeto.'Propriedade'). Além disso, é possível listar todas as propriedades com $objeto.PSObject.Properties.

Para scripts mais complexos, você pode querer adicionar métodos ou outros tipos de membros. Embora PSCustomObject não suporte métodos nativamente, você pode usar Add-Member para adicionar ScriptMethod, ScriptProperty, etc. No entanto, para objetos com comportamento, considere usar classes.

# Listando propriedades
$usuario.PSObject.Properties | ForEach-Object { $_.Name, $_.Value }

# Usando Select-Object para selecionar propriedades
$usuario | Select-Object Nome, Idade

# Usando Where-Object para filtrar
$usuarios = @(
    [PSCustomObject]@{ Nome = 'Ana'; Idade = 25 }
    [PSCustomObject]@{ Nome = 'Carlos'; Idade = 35 }
    [PSCustomObject]@{ Nome = 'Beatriz'; Idade = 28 }
)
$usuarios | Where-Object { $_.Idade -gt 30 }

Casos de uso

O PSCustomObject é extremamente útil em várias situações:

  • Exportação de dados: Você pode criar objetos customizados e exportá-los para CSV, JSON ou XML usando cmdlets como Export-Csv.
  • Relatórios: Crie objetos com informações de sistema, como uso de disco, processos em execução, etc., e formate a saída.
  • Transformação de dados: Ao processar arquivos de log ou dados de APIs, você pode converter cada registro em um PSCustomObject para facilitar a manipulação.
  • Simulação de objetos de banco de dados: Represente linhas de uma tabela como objetos customizados.
# Exemplo: relatório de serviços em execução
$servicos = Get-Service | Where-Object { $_.Status -eq 'Running' } | ForEach-Object {
    [PSCustomObject]@{
        Nome = $_.Name
        NomeExibicao = $_.DisplayName
        Tipo = $_.ServiceType
        Iniciado = $_.StartType
    }
}
$servicos | Export-Csv -Path 'C:\relatorio_servicos.csv' -NoTypeInformation

Boas práticas

  • Use nomes de propriedades consistentes e significativos.
  • Evite criar objetos muito grandes; prefira coleções de objetos pequenos.
  • Considere usar classes do PowerShell 5.0+ quando precisar de métodos ou validação de propriedades.
  • Para scripts que serão reutilizados, defina funções que retornam PSCustomObject.

Referências

Exercícios

  1. Crie um script que leia o conteúdo de um arquivo CSV hipotético (simule com uma lista de hashtables) e converta cada linha em um PSCustomObject. Use o seguinte conjunto de dados: Nome, Cidade, Idade. Em seguida, exiba apenas os objetos onde a idade é maior que 30.
  2. ✓ Resposta:
    # Dados simulados (como se viesse de um CSV)
    $dados = @(
        @{ Nome = 'Alice'; Cidade = 'São Paulo'; Idade = 28 },
        @{ Nome = 'Bob'; Cidade = 'Rio de Janeiro'; Idade = 35 },
        @{ Nome = 'Carol'; Cidade = 'Belo Horizonte'; Idade = 22 }
    )
    
    # Converter para PSCustomObject
    $objetos = $dados | ForEach-Object {
        [PSCustomObject]@{
            Nome   = $_.Nome
            Cidade = $_.Cidade
            Idade  = $_.Idade
        }
    }
    
    # Filtrar idade > 30
    $objetos | Where-Object { $_.Idade -gt 30 }
    
  3. Crie uma função chamada New-Pessoa que aceite parâmetros Nome, Sobrenome e Idade e retorne um PSCustomObject com essas propriedades, mais uma propriedade calculada NomeCompleto que concatena Nome e Sobrenome.
  4. ✓ Resposta:
    function New-Pessoa {
        param(
            [string]$Nome,
            [string]$Sobrenome,
            [int]$Idade
        )
        [PSCustomObject]@{
            Nome         = $Nome
            Sobrenome    = $Sobrenome
            Idade        = $Idade
            NomeCompleto = "$Nome $Sobrenome"
        }
    }
    
    # Exemplo de uso
    $pessoa = New-Pessoa -Nome 'Maria' -Sobrenome 'Santos' -Idade 32
    $pessoa
    
  5. Dado um array de PSCustomObject representando produtos (com propriedades: Nome, Preco, Quantidade), escreva um script que calcule o valor total do estoque (Preco * Quantidade) e exiba o resultado.
  6. ✓ Resposta:
    $produtos = @(
        [PSCustomObject]@{ Nome = 'Caneta'; Preco = 1.50; Quantidade = 100 },
        [PSCustomObject]@{ Nome = 'Caderno'; Preco = 15.00; Quantidade = 50 },
        [PSCustomObject]@{ Nome = 'Borracha'; Preco = 0.75; Quantidade = 200 }
    )
    
    $valorTotal = 0
    foreach ($produto in $produtos) {
        $valorTotal += $produto.Preco * $produto.Quantidade
    }
    
    Write-Host "Valor total do estoque: R$ $valorTotal"
    
  7. Use um PSCustomObject para representar um processo em execução (com propriedades: Nome, PID, Memória em MB). Em seguida, crie uma lista com três processos fictícios e ordene por consumo de memória decrescente.
  8. ✓ Resposta:
    $processos = @(
        [PSCustomObject]@{ Nome = 'chrome.exe'; PID = 1234; MemoriaMB = 350.5 },
        [PSCustomObject]@{ Nome = 'notepad.exe'; PID = 5678; MemoriaMB = 45.2 },
        [PSCustomObject]@{ Nome = 'powershell.exe'; PID = 9012; MemoriaMB = 120.0 }
    )
    
    $processosOrdenados = $processos | Sort-Object -Property MemoriaMB -Descending
    $processosOrdenados | Format-Table -AutoSize
    
  9. Crie um script que, usando PSCustomObject, gere um relatório com as informações de três arquivos de uma pasta (simule os arquivos). Para cada arquivo, inclua: Nome, Tamanho em KB, Data de modificação. Exporte o relatório para um arquivo CSV chamado 'relatorio_arquivos.csv'.
  10. ✓ Resposta:
    # Simulação de arquivos
    $arquivos = @(
        [PSCustomObject]@{
            Nome = 'documento.txt'
            TamanhoKB = 12.5
            DataModificacao = Get-Date '2025-03-10'
        },
        [PSCustomObject]@{
            Nome = 'foto.jpg'
            TamanhoKB = 1024.0
            DataModificacao = Get-Date '2025-03-12'
        },
        [PSCustomObject]@{
            Nome = 'planilha.xlsx'
            TamanhoKB = 256.3
            DataModificacao = Get-Date '2025-03-15'
        }
    )
    
    $arquivos | Export-Csv -Path 'relatorio_arquivos.csv' -NoTypeInformation
    Write-Host 'Relatório exportado com sucesso.'