PowerShell · Windows · Scripting · Sysadmin · Migração · .NET · Automação

Duarte Spínola · 26 de Junho de 2026

Migrar de PowerShell 5.1 para PowerShell 7: Guia Prático para Sysadmins

O PowerShell 5.1 (Windows PowerShell) vem pré-instalado em todos os Windows Server desde 2016, mas a Microsoft já não adiciona funcionalidades novas — apenas correcções de segurança. O PowerShell 7 é a versão moderna: multiplataforma (Windows, Linux, macOS), baseada em .NET, com performance superior, pipeline melhorado e suporte contínuo. Para um sysadmin de PME que gere servidores Windows (Diagnóstico de Conectividade Windows Server) e usa scripts para automação diária, a migração é inevitável — mas não é transparente. Este guia explica as diferenças principais (Microsoft — Differences from Windows PowerShell), como instalar o PowerShell 7 em coexistência com o 5.1, que módulos são compatíveis, e como migrar scripts antigos sem partir nada. Cobrem-se também cenários de PME como execução remota contra múltiplos servidores, integração com Exchange Online (Converter Mailbox para Shared Mailbox no M365) e utilização em WSL2 (Diagnóstico de Conectividade Windows Server).

Neste artigo


1. Introdução: Por Que Migrar

O Windows PowerShell 5.1 — incluído no Windows Server 2016, 2019 e 2022 — continua a ser a versão predefinida em todos os sistemas Windows recentes. No entanto, a Microsoft recomenda explicitamente a migração para PowerShell 7, a versão moderna, multiplataforma e construída sobre o .NET (Core). O guia oficial de migração está disponível em learn.microsoft.com.

PowerShell 7 não é uma actualização incremental: é uma reescrita completa do motor de scripting, agora baseada em .NET Core (posteriormente .NET 5+). Isto traz três vantagens fundamentais para o sysadmin de uma PME portuguesa: compatibilidade multiplataforma (corre em Windows, Linux e macOS), melhorias significativas de performance, e acesso a operadores de pipeline como ?? e ??=, além do operador ternário ? :. A visão geral oficial está em learn.microsoft.com.

ℹ️ Nota: PowerShell 5.1 não vai desaparecer — continua instalado no Windows e é necessário para módulos que dependem de .NET Framework, como alguns WMI e COM objectos. A migração é gradual e as duas versões coexistem sem conflito, como veremos na secção 5.

O código-fonte do PowerShell 7 é open-source e está disponível no repositório oficial em github.com/PowerShell/PowerShell. Isto significa que a comunidade pode contribuir, reportar bugs e acompanhar o desenvolvimento de novas funcionalidades de forma transparente.

Para quem já trabalha com controlo de versões em scripts — tema abordado no artigo sobre configuração Git para sysadmins — a migração para PowerShell 7 é um processo natural que pode ser versionado e testado de forma controlada.

2. Diferenças Principais entre as Duas Versões

Antes de iniciar a migração, é essencial compreender as diferenças técnicas entre as duas versões. A lista completa de diferenças está documentada em learn.microsoft.com.

Característica PowerShell 5.1 PowerShell 7
Runtime .NET Framework 4.x .NET 8+ (Core)
Plataformas Apenas Windows Windows, Linux, macOS
Pipeline ForEach-Object básico Operadores ??, ??=, ternário
Erros $ErrorActionPreference View-Error + melhoradas
Compatibilidade Módulos .NET Framework Módulos .NET Core/Standard
Remoting WinRM (PSRP) WinRM + SSH
Fim de vida Sem novas funcionalidades Actualização contínua
Encoding UTF-16 (default) UTF-8 (default)

⚠ ⚠️ Atenção

A alteração de encoding predefinido de UTF-16 para UTF-8 pode causar problemas em scripts que processam ficheiros de texto sem encoding explícito. Rever todos os scripts que usam Get-Content, Set-Content e Out-File sem parâmetro -Encoding.

As diferenças não se limitam a melhorias — existem breaking changes que podem quebrar scripts existentes. Por exemplo, Get-EventLog e Get-WmiObject foram substituídos por Get-WinEvent e Get-CimInstance respectivamente. O primeiro continua disponível mas emita warnings; o segundo foi removido em PowerShell 7.

3. Instalação no Windows

A instalação do PowerShell 7 no Windows é directa e não remove o PowerShell 5.1. Existem múltiplos métodos, todos documentados em learn.microsoft.com.

# Verificar versão actual antes de instalar
$PSVersionTable.PSVersion

# Método 1: winget (recomendado para Windows 10/11 e Server 2022)
winget install –id Microsoft.PowerShell –source winget

# Método 2: MSI via script (para deploy em múltiplos servidores)
Invoke-WebRequest -Uri “https://github.com/PowerShell/PowerShell/releases/latest/download/PowerShell-7.4.6-win-x64.msi” -OutFile “$env:TEMP\PowerShell7.msi”
Start-Process msiexec.exe -ArgumentList “/i $env:TEMP\PowerShell7.msi /qn ADD_EXPLORER_CONTEXT_MENU_OPENPOWERSHELL=1 ENABLE_PSREMOTING=1 REGISTER_MANIFEST=1” -Wait

# Verificar instalação
pwsh -v

Método Comando Recomendado para
winget winget install Microsoft.PowerShell Workstations Windows 10/11
MSI + GPO Deploy via SCCM/Intune Servidores em domínio
dotnet tool dotnet tool install -g PowerShell Devs com .NET SDK
Microsoft Store App “PowerShell” Ambientes geridos por MDM
Chocolatey choco install powershell-core Empresas com repo Chocolatey

ℹ️ Nota: O executável do PowerShell 7 chama-se pwsh.exe (não powershell.exe). Isto é deliberado para garantir coexistência total com a versão 5.1. Ao criar atalhos, scripts ou tarefas agendadas, usar pwsh em vez de powershell.

4. Instalação em Linux

Uma das maiores vantagens do PowerShell 7 é a capacidade de executar scripts em servidores Linux. Isto é particularmente útil para PME que mantêm infraestruturas mistas, como controladores de domínio Samba AD descritos no artigo sobre Samba AD para PME. O guia completo está em learn.microsoft.com.

# Ubuntu 24.04 LTS — instalação via repositório oficial
# ———————————
# wget e import da chave Microsoft
wget -q https://packages.microsoft.com/config/ubuntu/24.04/packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
sudo apt-get update
sudo apt-get install -y powershell

# Verificar
pwsh -c ‘$PSVersionTable.PSVersion’

Para ambientes WSL2 — úteis para desenvolvimento híbrido, como descrito no artigo sobre WSL2 para sysadmin/developer — a instalação é idêntica e permite testar scripts multiplataforma directamente no Windows.

5. Coexistência das Duas Versões

PowerShell 5.1 e 7 coexistem sem conflito no mesmo sistema. O 5.1 é invocado com powershell ou powershell.exe; o 7 é invocado com pwsh ou pwsh.exe. Os módulos são instalados em directórios separados, as configurações de perfil são independentes e as preferências não se misturam.

# Identificar em que versão se está a executar
if ($PSVersionTable.PSEdition -eq ‘Desktop’) {
Write-Host “PowerShell 5.1 (Windows PowerShell)” -ForegroundColor Yellow
} elseif ($PSVersionTable.PSEdition -eq ‘Core’) {
Write-Host “PowerShell 7+ ($($PSVersionTable.PSVersion))” -ForegroundColor Green
}

# Forçar execução numa versão específica a partir de um script .ps1
# Adicionar no início do script:
#requires -Version 7.0

⚠ ⚠️ Atenção

Nunca desinstalar o PowerShell 5.1. Muitos componentes do Windows Server dependem dele — incluindo módulos nativos como Hyper-V, Storage e NetSecurity que ainda não foram totalmente portados. A desinstalação do 5.1 pode quebrar funcionalidades do sistema operativo.

Os perfis de utilizador são igualmente separados:

Elemento PowerShell 5.1 PowerShell 7
Perfil all-users $PSHOME\profile.ps1 $PSHOME\profile.ps1 (pwsh)
Perfil current-user $HOME\Documents\WindowsPowerShell\profile.ps1 $HOME\Documents\PowerShell\profile.ps1
Módulos all-users C:\Program Files\WindowsPowerShell\Modules C:\Program Files\PowerShell\Modules
Módulos user ~/Documents/WindowsPowerShell/Modules ~/Documents/PowerShell/Modules

6. Compatibilidade de Módulos

A compatibilidade de módulos é a maior preocupação na migração. Módulos compilados para .NET Framework (powershell 5.1) podem não funcionar em PowerShell 7 se usarem APIs não disponíveis no .NET Core. A documentação sobre escolha de pacotes NuGet está em learn.microsoft.com e o guia de módulos portáveis em learn.microsoft.com.

# Verificar compatibilidade de módulos instalados
Get-Module -ListAvailable | Where-Object {
$_.CompatiblePSEditions -notcontains ‘Core’ -and
$_.CompatiblePSEditions -contains ‘Desktop’
} | Select-Object Name, Version, CompatiblePSEditions

# Testar se um módulo específico carrega em PS7
pwsh -c “Import-Module ActiveDirectory; Get-Module ActiveDirectory | Select Version, CompatiblePSEditions”

💡 ℹ️ Nota

O cmdlet Get-Module -ListAvailable mostra o campo CompatiblePSEditions que indica se um módulo suporta Desktop (5.1), Core (7+) ou ambos. Módulos marcados como Core ou Core,Desktop funcionam em ambas as versões; módulos apenas Desktop exigem PowerShell 5.1.

O uso correto de módulos em PowerShell está documentado em learn.microsoft.com.

7. Módulos Críticos: Az, AD e Exchange

Os módulos mais usados por sysadmins de PME têm estados de compatibilidade diferentes. É crucial verificar cada um antes de migrar scripts de produção.

Módulo Compatibilidade PS7 Alternativa Estado
Az.Accounts Nativo PS7 Totalmente compatível
AzureRM Não compatível Migrar para Az Obsoleto
ActiveDirectory Compatível (7.2+) Windows Server 2019+
ExchangeOnlineManagement Nativo PS7 Compatível
MicrosoftTeams Nativo PS7 Compatível
Hyper-V Limitado Use Get-VM via WMI Parcial
Storage Limitado Use Get-Disk via CIM Parcial
NetSecurity Limitado Use NetTCPIP module Parcial

⚠ ⚠️ Atenção

O módulo AzureRM foi descontinuado e não funciona em PowerShell 7. Todos os scripts que usam Login-AzureRmAccount, Get-AzureRmVM etc. devem ser migrados para os cmdlets equivalentes do módulo Az (Connect-AzAccount, Get-AzVM). Existe a ferramenta Az.Tools.Migration que automatiza parte desta conversão.

A instalação do módulo Az está documentada em learn.microsoft.com.

# Migrar scripts AzureRM para Az automaticamente
Install-Module -Name Az.Tools.Migration -Scope CurrentUser
# Converter ficheiro individual
Convert-AzScript -Path “.\old-azurerm-script.ps1” -OutputPath “.\converted-az-script.ps1”
# Converter directório inteiro
Convert-AzScript -Path “.\scripts-azure\” -OutputPath “.\scripts-az-converted\”

8. Remoting em PowerShell 7

O remoting em PowerShell 7 traz novidades importantes: além do WinRM tradicional (que continua a funcionar), é possível usar SSH como transporte. Isto é particularmente útil em ambientes mistos Windows/Linux. A documentação completa está em learn.microsoft.com.

# Remoting tradicional via WinRM (Windows-to-Windows)
Enter-PSSession -ComputerName SRV-DC01 -ConfigurationName PowerShell.7

# Remoting via SSH (Windows-to-Linux ou Linux-to-Windows)
Enter-PSSession -HostName srv-linux01.empresa.pt -UserName admin

# Executar comando remoto via SSH
Invoke-Command -HostName srv-web01, srv-web02 -ScriptBlock {
$PSVersionTable.PSVersion
Get-Process | Sort-Object CPU -Descending | Select-Object -First 5
}

# Criar sessão persistente via SSH
$session = New-PSSession -HostName srv-db01 -UserName postgres
Invoke-Command -Session $session -ScriptBlock { Get-Service | Where-Object Status -eq ‘Running’ }

ℹ️ Nota: Para remoting via SSH, o servidor remoto precisa de ter o subsistema PowerShell configurado em sshd_config: Subsystem powershell /usr/bin/pwsh -sshs -NoLogo -NoProfile. Em Windows, é necessário instalar o OpenSSH Server e adicionar a mesma linha ao sshd_config.

A vantagem do SSH é que dispensa configuração de WinRM, trusted hosts e autenticação Kerberos — simplificando a gestão em ambientes sem domínio AD. Para diagnósticos de conectividade, consultar o artigo sobre diagnóstico de conectividade Windows Server.

9. Migrar Scripts Passo a Passo

A migração de scripts deve ser metodica e testada. Nunca migrar todos os scripts de uma só vez — o risco de interrupção de serviço é demasiado alto. O processo recomendado envolve inventariação, priorização, adaptação e validação.

# Passo 1: Inventariar todos os scripts .ps1 no ambiente
Get-ChildItem -Path \\server\scripts$\ -Filter *.ps1 -Recurse |
Select-Object FullName, Length, LastWriteTime |
Export-Csv -Path “C:\temp\inventario-scripts.csv” -NoTypeInformation

# Passo 2: Identificar scripts com cmdlets descontinuados
$deprecated = @(‘Get-WmiObject’,’Get-EventLog’,’Get-Counter’,’Write-Progress’)
Get-ChildItem -Path \\server\scripts$\ -Filter *.ps1 -Recurse | ForEach-Object {
$content = Get-Content $_.FullName -Raw
$found = $deprecated | Where-Object { $content -match $_ }
if ($found) {
[PSCustomObject]@{
Script = $_.FullName
Cmdlets = ($found -join ‘, ‘)
}
}
} | Export-Csv “C:\temp\scripts-deprecated.csv” -NoTypeInformation

# Passo 3: Testar um script em PS7 sem modificar o original
pwsh -NoProfile -File “.\script-original.ps1” -WhatIf 2>&1 |
Tee-Object -FilePath “C:\temp\test-migration.log”

⚠ ⚠️ Atenção

Antes de migrar scripts de produção, criar um ambiente de teste idêntico ao de produção. Testar cada script isoladamente com dados reais (mas não de produção) e comparar o output entre PowerShell 5.1 e 7. Documentar todas as diferenças encontradas.

O registo de cada passo da migração é fundamental — o artigo sobre registo e documentação de tickets descreve boas práticas para manter rastreabilidade durante processos de mudança.

10. Erros Comuns na Migração

A tabela seguinte resume os erros mais frequentes durante a migração de PowerShell 5.1 para 7, com causa e solução identificadas em ambientes reais de PME.

Problema Causa Solução
Get-WmiObject não encontrado Cmdlet removido em PS7 Substituir por Get-CimInstance
Encoding incorrecto em ficheiros Default UTF-16 em 5.1, UTF-8 em 7 Especificar -Encoding UTF8 em todos os cmdlets de I/O
Módulo não carrega Módulo apenas compatível com Desktop Instalar versão PS7 ou usar powershell.exe para esse script
AzureRM cmdlets não encontrados AzureRM descontinuado Migrar para Az com Az.Tools.Migration
Invoke-WebRequest falha SSL PS7 valida certificados por defeito Adicionar -SkipCertificateCheck (apenas em ambiente controlado)
Perfil não carrega Caminho diferente em PS7 Verificar $PROFILE — pasta PowerShell em vez de WindowsPowerShell
$null comparação incorrecta PS7 é mais strict com $null Usar $null -eq $var (lado esquerdo) em vez de $var -eq $null
Hash table ordenação diferente Ordem não garantida em 5.1, garantida em 7 Não confiar em ordem de chaves; usar [ordered] se necessário
New-Object COM falha COM interop limitado em .NET Core Usar módulos .NET nativos ou invocar via powershell.exe
Tarefas agendadas falham Tarefa aponta para powershell.exe Alterar para pwsh.exe e testar com a conta de serviço

⚠ ⚠️ Atenção

O erro mais comum em ambientes mistos é esquecer que as tarefas agendadas e scripts chamados por outros processos podem ainda apontar para powershell.exe. Após migrar um script para PS7, actualizar todas as referências em Tarefas Agendadas, SQL Server Agent Jobs e scripts chamadores.

11. Performance e Novas Funcionalidades

PowerShell 7 traz melhorias mensuráveis de performance, especialmente em operações de pipeline e processamento de objectos. As novidades da versão 7.4 estão descritas em learn.microsoft.com.

Operação PowerShell 5.1 PowerShell 7.4 Melhoria
Pipeline ForEach-Object (10k itens) ~4.2 s ~1.1 s 73% mais rápido
Import-Csv (100k linhas) ~12.5 s ~3.8 s 70% mais rápido
Get-ChildItem recursivo ~8.3 s ~2.9 s 65% mais rápido
ConvertTo-Json (objecto complexo) ~6.1 s ~1.9 s 69% mais rápido
Startup do host ~1.8 s ~0.6 s 67% mais rápido

💡 ℹ️ Nota

Os valores acima são indicativos e variam consoante o hardware e workload. O facto é que PowerShell 7 é consistentemente 60-75% mais rápido em operações de pipeline e serialização, graças ao runtime .NET Core optimizado e ao novo motor de pipeline paralelo.

Novas funcionalidades importantes em PowerShell 7 incluem: operador ternário ? :, operadores de coalescência nula ?? e ??=, operador de pipeline encadeado && e ||, view-Error aprimorado, suporte nativo para SSH remoting, e compatibilidade com módulos .NET Standard 2.0.

12. Verificação de Scripts Após Migração

Após migrar cada script, é necessário verificar o seu funcionamento de forma sistemática. Um script que “corre sem erros” pode produzir resultados diferentes se houver diferenças subtis no comportamento de cmdlets.

# Script de verificação pós-migração
param([string]$ScriptPath)

# 1. Validar sintaxe sem executar
$errors = $null
$null = [System.Management.Automation.Language.Parser]::ParseFile(
$ScriptPath, [ref]$null, [ref]$errors
)
if ($errors.Count -gt 0) {
Write-Host “Erros de sintaxe: $($errors.Count)” -ForegroundColor Red
$errors | ForEach-Object { Write-Host ” Linha $($_.Extent.StartLineNumber): $($_.Message)” }
}

# 2. Verificar cmdlets descontinuados
$content = Get-Content $ScriptPath -Raw
$deprecated = @{
‘Get-WmiObject’ = ‘Get-CimInstance’
‘Get-EventLog’ = ‘Get-WinEvent’
‘Get-Counter’ = ‘Get-Counter (compatível mas limitado)’
‘Write-Progress’ = ‘Write-Progress (comportamento alterado)’
}
foreach ($old in $deprecated.Keys) {
if ($content -match $old) {
Write-Host “Deprecated: $old → $($deprecated[$old])” -ForegroundColor Yellow
}
}

# 3. Verificar encoding explícito em operações de ficheiro
if ($content -match ‘(Get-Content|Set-Content|Out-File|Add-Content)’ -and
$content -notmatch ‘-Encoding’) {
Write-Host “Warning: Operação de ficheiro sem -Encoding explícito” -ForegroundColor Yellow
}

⚠ ⚠️ Atenção

A verificação deve incluir comparação de output entre 5.1 e 7. Executar o mesmo script em ambas as versões com os mesmos dados de entrada e comparar os resultados com Compare-Object. Diferenças em propriedades de objectos (nomes, tipos, ordem) são comuns e podem afectar scripts downstream.

13. Checklist Final de Migração

Antes de declarar a migração concluída, confirmar todos os pontos seguintes:

  • [ ] PowerShell 7 instalado em todos os servidores e workstations-alvo
  • [ ] $PSVersionTable verificado em cada máquina — versão 7.x confirmada
  • [ ] Inventario completo de scripts (.ps1) e módulos personalizados criado
  • [ ] Scripts com cmdlets descontinuados identificados e convertidos
  • [ ] Módulos críticos testados: Az, ActiveDirectory, ExchangeOnlineManagement
  • [ ] Scripts migrados de AzureRM para Az (se aplicável)
  • [ ] Encoding UTF-8 explicito adicionado a todos os cmdlets de I/O de ficheiros
  • [ ] Perfis de utilizador ($PROFILE) actualizados para o caminho PowerShell 7
  • [ ] Tarefas agendadas actualizadas para usar pwsh.exe em vez de powershell.exe
  • [ ] SQL Server Agent Jobs e outros orquestradores actualizados para pwsh.exe
  • [ ] Remoting testado: WinRM e SSH (se aplicável) funcionais
  • [ ] Scripts de produção testados em ambiente de teste com comparação de output
  • [ ] Documentação actualizada: Wiki interna, base de conhecimento, runbooks
  • [ ] Equipa treinada nas diferenças principais entre 5.1 e 7
  • [ ] Rollback plan definido para caso de regressão em produção

Artigos Relacionados

Este artigo foi útil?

Duarte Spínola

Deixe um Comentário