Dia 29: PowerShell para M365 — Graph API, Exchange e SharePoint

O PowerShell é a ferramenta de automação indispensável para administradores do Microsoft 365. Com o Graph SDK, gerimos utilizadores, mailboxes, sites e Teams a partir de uma única consola. Neste Dia 29, exploramos os módulos principais e scripts práticos para o dia-a-dia.

ℹ O Microsoft Graph SDK substitui os módulos legados MSOnline e AzureAD, descontinuados oficialmente. Toda a automação nova deve usar o Graph SDK.

⚠️ Migrar scripts antigos que usam MSOnline ou AzureAD para o Graph SDK. Os módulos legados deixarão de funcionar. Usar Find-MgGraphCommand para mapear comandos antigos.

Neste artigo

1. Introdução ao PowerShell para M365

O M365 expõe a sua funcionalidade administrativa através de APIs REST que o PowerShell consome via módulos dedicados. Em vez de clicar no centro de administração, um administrador aplica configurações a centenas de objectos em segundos.

Módulo Âmbito Instalação
Microsoft.Graph Utilizadores, grupos, licenças Install-Module Microsoft.Graph
ExchangeOnlineManagement Mailboxes, regras, conectores Install-Module ExchangeOnlineManagement
PnP.PowerShell Sites, listas, permissões Install-Module PnP.PowerShell
MicrosoftTeams Equipas, canais, políticas Install-Module MicrosoftTeams
# Instalar todos os módulos
Install-Module Microsoft.Graph -Scope CurrentUser
Install-Module ExchangeOnlineManagement -Scope CurrentUser
Install-Module PnP.PowerShell -Scope CurrentUser
Install-Module MicrosoftTeams -Scope CurrentUser

2. Microsoft Graph SDK

O módulo Microsoft.Graph é o módulo oficial para interagir com a Graph API. Suporta autenticação interactiva, credenciais de cliente (app-only) e fluxo de código de dispositivo.

# Ligar com scopes de administração
Connect-MgGraph -Scopes "User.ReadWrite.All","Group.ReadWrite.All"

# Listar utilizadores
Get-MgUser -All | Select-Object DisplayName, UserPrincipalName, AccountEnabled

# Criar utilizador
New-MgUser -DisplayName "Ana Costa" `
  -UserPrincipalName "[email protected]" `
  -PasswordProfile @{Password="SenhaForte123!";ForceChangePasswordNextSignIn=$true} `
  -MailNickname "ana.costa" -AccountEnabled

# Atribuir licença M365
Set-MgUserLicense -UserId "[email protected]" `
  -AddLicenses @{SkuId="c7df2760-2c81-4ef7-bb25-d5cb1e9b6a3f"}

Disconnect-MgGraph

O Graph SDK organiza comandos por recurso: Get-MgUser, Get-MgGroup, Get-MgDevice. Cada verbo segue o padrão Verbo-MgRecurso.

3. Exchange Online Management

O módulo ExchangeOnlineManagement gere mailboxes, regras de transporte e conectores. Usa autenticação OAuth 2.0.

Connect-ExchangeOnline

# Listar mailboxes com tamanho
Get-Mailbox -ResultSize Unlimited |
  Get-MailboxStatistics |
  Select-Object DisplayName, TotalItemSize, ItemCount

# Criar mailbox partilhada
New-Mailbox -Shared -Name "Suporte Geral" `
  -PrimarySmtpAddress "[email protected]"

# Regra de transporte — bloquear .exe
New-TransportRule -Name "Bloquear Executáveis" `
  -AttachmentExtensionMatchesPatterns "\.exe$" `
  -RejectMessageReasonText "anexos executáveis não permitidos"

Disconnect-ExchangeOnline

O parâmetro -ResultSize Unlimited é essencial — sem ele, o Exchange devolve apenas 1000 resultados.

4. PnP PowerShell para SharePoint

O PnP PowerShell é a ferramenta mais completa para administrar SharePoint Online e Microsoft Lists — sites, listas, permissões e templates.

Connect-PnPOnline -Url "https://empresa.sharepoint.com/sites/RH" -Interactive

# Criar lista com colunas
New-PnPList -Title "Registo Férias" -Template GenericList
Add-PnPField -List "Registo Férias" -DisplayName "Colaborador" -Type Text
Add-PnPField -List "Registo Férias" -DisplayName "Data Início" -Type DateTime
Add-PnPField -List "Registo Férias" -DisplayName "Dias" -Type Number

# Adicionar item
Add-PnPListItem -List "Registo Férias" `
  -Values @{"Colaborador"="Ana Costa";"Data Início"="2026-09-01";"Dias"=10}

# Exportar para CSV
Get-PnPListItem -List "Registo Férias" |
  Export-Csv -Path "C:\temp\ferias.csv" -NoTypeInformation

Disconnect-PnPOnline

5. Teams PowerShell

O módulo MicrosoftTeams gere equipas, canais, membros e políticas de reunião. A partir da versão 4.0, usa o Graph SDK internamente.

Connect-MicrosoftTeams

# Criar equipa privada
New-Team -DisplayName "Projecto Alpha" -Visibility Private

# Adicionar canal
$gid = (Get-Team -DisplayName "Projecto Alpha").GroupId
Add-TeamChannel -GroupId $gid -DisplayName "Documentação"

# Adicionar membros em massa
$upns = @("[email protected]","[email protected]")
foreach ($u in $upns) { Add-TeamUser -GroupId $gid -User $u -Role Member }

Disconnect-MicrosoftTeams

6. Scripts Práticos

A potência do PowerShell revela-se ao combinar módulos num único script. Dois exemplos para cenários reais:

Relatório de utilizadores sem licença

Connect-MgGraph -Scopes "User.Read.All","Directory.Read.All"
$users = Get-MgUser -All -Property Id,DisplayName,UserPrincipalName,AssignedLicenses
$sem = $users | Where-Object { $_.AssignedLicenses.Count -eq 0 }
$sem | Select-Object DisplayName,UserPrincipalName |
  Export-Csv -Path "C:\temp\sem-licenca.csv" -NoTypeInformation
Write-Host "$($sem.Count) utilizadores sem licença."
Disconnect-MgGraph

Cópia de segurança de configuração de mailboxes

Connect-ExchangeOnline
$mbs = Get-Mailbox -ResultSize Unlimited
$backup = foreach ($mb in $mbs) {
  $s = Get-MailboxStatistics -Identity $mb.Identity
  [PSCustomObject]@{
    DisplayName=$mb.DisplayName; Smtp=$mb.PrimarySmtpAddress
    Size=$s.TotalItemSize; Items=$s.ItemCount
  }
}
$backup | Export-Csv "C:\temp\backup-mailboxes.csv" -NoTypeInformation
Disconnect-ExchangeOnline

7. Erros Comuns e Lista de Verificação

Erro Causa Solução
403 Acesso Negado Scopes insuficientes Adicionar scopes em Connect-MgGraph
429 Limitação de taxa Excesso de pedidos Usar -All; respeitar Retry-After
Resultados truncados Limite de 100/1000 -ResultSize Unlimited ou -All

Lista de verificação para produção

  • Usar autenticação moderna — nunca credenciais em texto no script
  • Para automação autónoma, usar certificados ou Managed Identity
  • Aplicar -ErrorAction Stop com blocos try/catch
  • Registar execução com Start-Transcript
  • Desligar sessões no fim (Disconnect-*)
  • Testar com utilizador de teste antes de produção
  • Guardar scripts em repositório Git

Artigos Relacionados