Correção: inicialização lenta do console e scripts do PowerShell

Percebi que o console do PowerShell às vezes demora muito para abrir. Esse problema ocorre em computadores diferentes. Em alguns casos, pode levar vários minutos para o PowerShell carregar. Isso afeta a abertura do próprio shell de comando (powershell.exe ou pwsh.exe) e o tempo de execução dos scripts de logon do PowerShell iniciados via GPO ou scripts nas tarefas agendadas. Esta postagem explica como identificar possíveis motivos para a inicialização lenta do PowerShell e reduzir o tempo de carregamento.

Aqui estão alguns motivos comuns pelos quais o PowerShell pode demorar muito para carregar:

  • As funções definidas pelo usuário nos arquivos de perfil do PowerShell são carregadas sempre que o processo PowerShell.exe é iniciado
  • Um número significativo de módulos PS são instalados e carregados automaticamente
  • O módulo PSReadLine carrega um arquivo enorme contendo o histórico dos comandos do PowerShell
  • Lentidão significativa no PowerShell e no carregamento de módulos são causadas por conflitos ou corrupção nos componentes do .NET Framework.

OComando de mediçãocmdlet pode ser usado para medir o tempo de carregamento de um processo do PowerShell. Use este comando para verificar o tempo de carregamento do PowerShell no modo normal.:

powershell -noprofile -ExecutionPolicy Bypass ( Measure-Command { powershell "Write-Host 1" } ).TotalSeconds

O comando exibirá quanto tempo levou para o processo do PowerShell carregar e executar um comando simples.

Quando o PowerShell for iniciado, ele poderá relatar o tempo que levou para carregar.

Loading personal and system profiles took XXX ms

Como você pode ver neste exemplo, o processo do PowerShell demorou 12 segundos para carregar. Isso é bastante. Esta mensagem é exibida automaticamente se o tempo de carregamento dos perfis do PowerShellexcede 500 ms.

Isso sugere que os arquivos de perfil do PowerShell estão executando código lento sempre que o processo é iniciado.

Compare a velocidade de inicialização do processo do PowerShell quando os perfis não são carregados. Para fazer isso, execute o processo shell com o-sem perfilopção:

powershell.exe -noprofile

ou para executar o PowerShell Core:

pwsh.exe -noProfile

Como você pode ver, o PowerShell iniciou muito mais rápido quando os perfis não foram carregados. Perfis do PowerShell são arquivos PS1 usados ​​para configurar o ambiente do usuário. Eles também permitem ao usuário executar comandos específicos e carregar funções ou módulos personalizados.

Por padrão, os arquivos de perfil do PowerShell não são usados ​​(nenhum arquivo de perfil é criado). O comando a seguir exibe uma lista de todos os arquivos de perfil que serão carregados quando o processo do PowerShell for iniciado.

$profile | select *

Verifique o conteúdo de todos os arquivos de perfil do usuário manualmente ou use os seguintes comandos para exibi-los:
Get-Content $PROFILE.AllUsersAllHosts
Get-Content $PROFILE.AllUsersCurrentHost
Get-Content $PROFILE.CurrentUserAllHosts
Get-Content $PROFILE.CurrentUserCurrentHost

No meu caso, alguns comandos são adicionados aoMicrosoft.PowerShell_profile.ps1arquivo do usuário. Revise o arquivo de perfil para assegurar que todos os comandos e funções sejam necessários. Se possível, remova comandos desnecessários e otimize o código.

Um grande número de módulos instalados pode ser outro motivo possível para a inicialização lenta do PowerShell. O PowerShell carrega automaticamente módulos das seguintes pastas:

C:Users%username%DocumentsWindowsPowerShellModules
C:Program FilesWindowsPowerShellModules
C:Windowssystem32WindowsPowerShellv1.0Modules

Sua lista pode ser exibida da seguinte forma:

$Env:PSModulePath -split ';'

Liste os módulos PS que foram carregados na sessão.

Get-Module -ListAvailable

Liste os módulos de terceiros instalados.

Get-InstalledModule

Verifique a lista para ver se você precisa de todos os módulos. Desinstale todos os módulos do PowerShell não utilizados.:
Remove-Module -Name BurntToast
Uninstall-Module -Name BurntToast -AllVersions -Force

Os módulos do PowerShell instalados manualmente devem ser desinstalados manualmente.

Para analisar o tempo de carregamento de cada módulo, utilize o seguinte comando:

Measure-Command { Import-Module ModuleName -Force }

Ou verifique o tempo de carregamento de todos os módulos PS em massa:
$modules = Get-InstalledModule| Select-Object -ExpandProperty Name -Unique
foreach ($mod in $modules) {
$time = Measure-Command { Import-Module $mod -Force }
[PSCustomObject]@{
Module = $mod
LoadTimeSec = $time.Totalseconds
}
}

Veja quais módulos demoram mais para carregar.

Para evitar que todos os módulos PS sejam carregados automaticamente, adicione a seguinte linha ao arquivo de perfil:

$PSModuleAutoLoadingPreference="None"

Neste caso, você pode carregar manualmente o módulo necessário usando o seguinte comando:

Import-Module [ModuleName]

Certifique-se de adicionar os seguintes módulos comuns ao seu arquivo de perfil:

Import-Module Microsoft.PowerShell.Utility
Import-Module Microsoft.PowerShell.Management

Há também um problema conhecido ao carregar o módulo VMware Infrastructure Management PowerShell, também conhecido comoVMware PowerCLI. O módulo pode levar vários minutos para carregar em um computador que não esteja conectado à Internet. O problema é que, ao carregar, o módulo tenta verificar uma lista externa de certificados revogados (CRL,Lista de revogação de certificados). Devido à falta de conectividade com a Internet, esse processo expirou. A solução édesativar a verificação de CRL no Windows. Você pode desativar a verificação de CRL por meio do registro:

reg add HKLMSYSTEMCurrentControlSetServicesSstpSvcParameters /v NoCertRevocationCheck /t REG_DWORD /d 0x00000001 /f

Ou no miniaplicativo Propriedades da Internet:inetcpl.cpl->Avançado-> desmarque a opçãoVerifique a revogação do certificado do editor (servidor).

O motivo pelo qual o PowerShell pode demorar muito para iniciar geralmente é o software antivírus instalado no computador. Você pode verificar quais DLLs e módulos externos são carregados quando o processo do PowerShell é iniciado.

  1. Abrircmd.exee execute o comando:powershell.exe -c "Write-Host $PID;Start-Sleep -s 60"
  2. Este comando retorna o ID do processo (PID) do processo PowerShell.exe em execução. Copie oPIDe cole-o no seguinte comando em uma nova sessão do PowerShell:
    Get-Process | where {$_.Id -eq <YOUR_PID>} | select -ExpandProperty modules
  3. Você receberá uma lista das DLLs carregadas quando o processo do PowerShell for iniciado. Verifique se sua biblioteca de antivírus está listada. Nesse caso, tente adicionar os processos pwsh.exe e powershell.exe às exceções do antivírus.

Por exemplo, você pode usar o comando abaixo para adicionar exclusões ao antivírus integrado do Windows Defender:

Add-MpPreference -ExclusionProcess "C:WindowsSystem32WindowsPowerShellv1.0powershell.exe","C:Program FilesPowerShell7pwsh.exe"

Leia também:Prompt de comando do Windows 10: novo console versus console legado

Se você suspeitar que a inicialização lenta do PowerShell é causada pela operação lenta da biblioteca do .NET Framework, você pode compilar todos os assemblies usados ​​em código de máquina nativo usando o comandongen.exeferramenta (Gerador de imagem nativa). Isto melhorará significativamente o desempenho dos aplicativos .NET, incluindo o PowerShell:

$env:PATH = [Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory()
[AppDomain]::CurrentDomain.GetAssemblies() | ForEach-Object {
$path = $_.Location
if ($path) {
$name = Split-Path $path -Leaf
Write-Host -ForegroundColor Yellow "`r`nRunning ngen.exe on '$name'"
ngen.exe install $path /nologo
}
}

O clássicoMonitor de ProcessoA ferramenta também pode ser usada para analisar o tempo de inicialização do PowerShell. (https://technet.microsoft.com/en-us/sysinternals/processmonitor.aspx). CorrerProcMon64.exe, habilite o filtro no processo PowerShell.exe, abra o shell PS e identifique as operações que causaram o maior atraso.

No meu exemplo, a leitura do arquivo de histórico de comandos do PowerShell mantido pelo módulo PSReadline levou cerca de 30 segundos. (C:UsersusernameAppDataRoamingMicrosoftWindowsPowerShellPSReadLineConsoleHost_history.txt). O problema foi causado peloConsoleHost_history.txtarquivo com tamanho superior a 2 GB. A limpeza do arquivo histórico reduziu significativamente o tempo de inicialização do PowerShell.

Related Posts