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
- 2. Diferenças Principais entre as Duas Versões
- 3. Instalação no Windows
- 4. Instalação em Linux
- 5. Coexistência das Duas Versões
- 6. Compatibilidade de Módulos
- 7. Módulos Críticos: Az, AD e Exchange
- 8. Remoting em PowerShell 7
- 9. Migrar Scripts Passo a Passo
- 10. Erros Comuns na Migração
- 11. Performance e Novas Funcionalidades
- 12. Verificação de Scripts Após Migração
- 13. Checklist Final de Migração
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.
$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.
# ———————————
# 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.
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.
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.
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.
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.
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.
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
- [ ]
$PSVersionTableverificado 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.exeem vez depowershell.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
