Módulos são a forma mais profissional e escalável de organizar e distribuir código em PowerShell. Eles permitem agrupar funções, variáveis, aliases e até recursos como DSC (Desired State Configuration) em um pacote reutilizável. Nesta aula, você vai aprender a criar seu próprio módulo do zero, entendendo os componentes essenciais: o arquivo de script (.psm1), o manifesto (.psd1) e como controlar o que é exportado para o usuário final.

Dominar a criação de módulos é fundamental para qualquer profissional que deseja compartilhar código de forma limpa, versionada e fácil de instalar. Além disso, módulos são a base para ferramentas como o PowerShell Gallery, onde você pode publicar seus próprios módulos para a comunidade.

Arquivo .psm1

O arquivo .psm1 é o coração do módulo. Ele contém as funções e lógica que o módulo expõe. Quando você importa um módulo, o PowerShell executa esse arquivo e disponibiliza as funções que foram marcadas para exportação. O nome do arquivo .psm1 deve coincidir com o nome do módulo (ex.: MeuModulo.psm1).

Dentro do .psm1, você pode definir funções, variáveis, aliases e até tipos personalizados. Tudo que for definido no escopo do módulo é privado por padrão. Para tornar algo público, você usa Export-ModuleMember (veremos adiante). Vamos criar um exemplo simples:

# MeuModulo.psm1
function Get-Saudacao {
    param([string]$Nome)
    "Olá, $Nome! Bem-vindo ao módulo."
}

function Set-Configuracao {
    param([string]$Chave, [string]$Valor)
    $script:Configuracoes[$Chave] = $Valor
}

# Variável privada do módulo
$script:Configuracoes = @{}

# Exporta apenas as funções desejadas
Export-ModuleMember -Function Get-Saudacao, Set-Configuracao

Observe que usamos $script: para declarar uma variável que persiste apenas no escopo do módulo. Isso evita conflitos com o escopo global. Ao importar o módulo, apenas as funções exportadas ficam disponíveis; variáveis e outras funções permanecem internas.

Manifesto (.psd1)

O manifesto é um arquivo de dados com extensão .psd1 que descreve o módulo: versão, autor, descrição, dependências, e quais arquivos fazem parte do módulo. Ele é opcional, mas altamente recomendado, pois permite que o PowerShell gerencie o módulo corretamente, especialmente para publicação e instalação via PowerShell Gallery.

O manifesto é criado com o cmdlet New-ModuleManifest. Ele gera um arquivo com todas as chaves padrão. Você pode editar manualmente ou usar o cmdlet. Aqui está um exemplo de manifesto para o nosso módulo:

# MeuModulo.psd1
@{
    RootModule = 'MeuModulo.psm1'
    ModuleVersion = '1.0.0'
    GUID = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
    Author = 'Seu Nome'
    CompanyName = 'Sua Empresa'
    Copyright = '(c) 2025 Seu Nome. Todos os direitos reservados.'
    Description = 'Módulo de exemplo para a aula de criação de módulos.'
    PowerShellVersion = '5.1'
    FunctionsToExport = @('Get-Saudacao', 'Set-Configuracao')
    CmdletsToExport = @()
    VariablesToExport = @()
    AliasesToExport = @()
    PrivateData = @{
        PSData = @{
            Tags = @('Exemplo', 'Aula')
            ProjectUri = 'https://exemplo.com'
            LicenseUri = 'https://exemplo.com/licenca'
        }
    }
}

O GUID é um identificador único do módulo. Você pode gerar com [guid]::NewGuid(). O campo FunctionsToExport é redundante com o Export-ModuleMember, mas é uma boa prática especificar no manifesto também.

Export-ModuleMember

O cmdlet Export-ModuleMember define quais membros do módulo (funções, cmdlets, variáveis, aliases) serão exportados para o escopo do chamador. Por padrão, sem usar esse cmdlet, o PowerShell exporta todas as funções e cmdlets definidos no módulo, mas não variáveis ou aliases. No entanto, é recomendável ser explícito para evitar expor funções internas.

O uso típico é no final do arquivo .psm1, listando os membros desejados. Você pode usar parâmetros como -Function, -Cmdlet, -Variable, -Alias. Exemplo:

Export-ModuleMember -Function Get-Saudacao, Set-Configuracao -Variable Configuracoes

No exemplo acima, também exportamos a variável $Configuracoes (que definimos com $script:Configuracoes). Isso pode ser útil se você quiser que o usuário acesse diretamente, mas geralmente é melhor manter variáveis privadas e fornecer funções para manipulá-las.

É importante notar que Export-ModuleMember só pode ser chamado no escopo do módulo (no arquivo .psm1). Se você tentar usá-lo fora, um erro será gerado.

Estrutura

Uma estrutura de módulo bem organizada facilita a manutenção e o crescimento. Embora um módulo simples possa ser apenas um .psm1, módulos profissionais costumam ter pastas separadas para funções, testes, documentação, etc. Vamos criar uma estrutura recomendada:

MeuModulo/
├── MeuModulo.psd1
├── MeuModulo.psm1
├── Functions/
│   ├── Get-Saudacao.ps1
│   └── Set-Configuracao.ps1
├── Tests/
│   └── MeuModulo.Tests.ps1
└── Docs/
    └── README.md

Nessa estrutura, o .psm1 apenas importa os arquivos de funções usando dot-sourcing. Por exemplo:

# MeuModulo.psm1
$FunctionsPath = Join-Path $PSScriptRoot 'Functions'
Get-ChildItem -Path $FunctionsPath -Filter '*.ps1' | ForEach-Object {
    . $_.FullName
}

# Exporta as funções desejadas
Export-ModuleMember -Function Get-Saudacao, Set-Configuracao

Essa abordagem permite que cada função fique em um arquivo separado, facilitando a manutenção e o versionamento. Além disso, você pode adicionar testes Pester na pasta Tests e documentação na pasta Docs.

Boas práticas e observações finais

Ao criar módulos, siga estas boas práticas:

  • Use nomes de funções no padrão Verbo-Substantivo (aprovados pelo PowerShell).
  • Inclua comentários de ajuda (.SYNOPSIS, .EXAMPLE) em cada função.
  • Defina um manifesto completo com versão, autor e descrição.
  • Exporte apenas o que for necessário, usando Export-ModuleMember explicitamente.
  • Teste o módulo com Pester antes de publicar.
  • Versionamento semântico (1.0.0, 1.1.0, etc.) para facilitar atualizações.

Com esses conceitos, você está pronto para criar módulos profissionais e compartilhá-los com o mundo.

Referências

Exercícios

  1. Crie um módulo chamado MeuModulo com duas funções: Get-Ola e Get-Tchau. A função Get-Ola deve retornar "Olá, mundo!", e Get-Tchau deve retornar "Tchau!". Exporte apenas essas funções usando Export-ModuleMember. Teste o módulo importando e chamando as funções.

    ✓ Resposta: Crie o arquivo MeuModulo.psm1 com o seguinte conteúdo:
    function Get-Ola {
        "Olá, mundo!"
    }
    function Get-Tchau {
        "Tchau!"
    }
    Export-ModuleMember -Function Get-Ola, Get-Tchau
    Para testar, salve o arquivo em uma pasta chamada MeuModulo e execute Import-Module ./MeuModulo (ou Import-Module .\MeuModulo.psm1). Depois chame Get-Ola e Get-Tchau.
  2. Explique a diferença entre um módulo que usa Export-ModuleMember e um que não usa. Dê um exemplo de situação em que é útil ser explícito.

    ✓ Resposta: Sem Export-ModuleMember, o PowerShell exporta todas as funções e cmdlets definidos no módulo por padrão. Com ele, você controla exatamente o que é exposto. Ser explícito é útil quando você tem funções auxiliares internas que não devem ser chamadas pelo usuário, evitando poluição do namespace e conflitos.
  3. Crie um manifesto (.psd1) para o módulo do exercício 1, com versão 1.0.0, autor "Seu Nome", e descrição "Módulo de saudação". Use o cmdlet New-ModuleManifest ou edite manualmente.

    ✓ Resposta: Execute o comando: New-ModuleManifest -Path .\MeuModulo.psd1 -RootModule MeuModulo.psm1 -ModuleVersion '1.0.0' -Author 'Seu Nome' -Description 'Módulo de saudação'. Isso gera um arquivo .psd1 com as informações preenchidas.
  4. Considere a estrutura de módulo com pastas Functions, Tests e Docs. Escreva o conteúdo do arquivo .psm1 que carrega todas as funções da pasta Functions e exporta apenas as funções Get-Ola e Get-Tchau.

    ✓ Resposta: O conteúdo do .psm1 seria:
    $FunctionsPath = Join-Path $PSScriptRoot 'Functions'
    Get-ChildItem -Path $FunctionsPath -Filter '*.ps1' | ForEach-Object {
        . $_.FullName
    }
    Export-ModuleMember -Function Get-Ola, Get-Tchau
    Assumindo que as funções estão em arquivos separados dentro de Functions.
  5. Pesquise sobre o PowerShell Gallery e explique como você publicaria seu módulo. Liste os comandos básicos para publicar e instalar um módulo do gallery.

    ✓ Resposta: Para publicar no PowerShell Gallery, você precisa de uma conta (chave API) e usar o cmdlet Publish-Module. Exemplo: Publish-Module -Name .\MeuModulo -NuGetApiKey 'sua-chave'. Para instalar, use Install-Module -Name MeuModulo. Antes de publicar, é recomendável executar Test-ModuleManifest para validar o manifesto.