Correzione: avvio lento della console e degli script di PowerShell

Ho notato che la console PowerShell a volte impiega molto tempo per aprirsi. Questo problema si verifica su computer diversi. In alcuni casi, potrebbero essere necessari diversi minuti per il caricamento di PowerShell. Ciò influisce sull'apertura della shell dei comandi stessa (powershell.exe o pwsh.exe) e sul tempo di esecuzione degli script di accesso PowerShell avviati tramite GPO o degli script nelle attività pianificate. Questo post spiega come identificare i potenziali motivi dell'avvio lento di PowerShell e ridurre i tempi di caricamento.

Ecco alcuni motivi comuni per cui il caricamento di PowerShell potrebbe richiedere molto tempo:

  • Le funzioni definite dall'utente nei file di profilo di PowerShell vengono caricate ogni volta che viene avviato il processo PowerShell.exe
  • Un numero significativo di moduli PS viene installato e caricato automaticamente
  • Il modulo PSReadLine carica un file enorme contenente la cronologia dei comandi di PowerShell
  • Rallentamenti significativi in ​​PowerShell e nel caricamento dei moduli sono causati da conflitti o danneggiamenti nei componenti .NET Framework.

ILMisura-Comandoil cmdlet può essere utilizzato per misurare il tempo di caricamento di un processo di PowerShell. Utilizzare questo comando per verificare il tempo di caricamento di PowerShell in modalità normale.:

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

Il comando mostrerà il tempo impiegato dal processo PowerShell per caricare ed eseguire un semplice comando.

All'avvio di PowerShell, potrebbe segnalare il tempo impiegato per il caricamento.

Loading personal and system profiles took XXX ms

Come puoi vedere in questo esempio, il caricamento del processo PowerShell ha richiesto 12 secondi. È parecchio. Questo messaggio viene visualizzato automaticamente se il tempo di caricamento dei profili PowerShellsupera i 500 ms.

Ciò suggerisce che i file di profilo di PowerShell eseguono codice lento ogni volta che viene avviato il processo.

Confronta la velocità di avvio del processo PowerShell quando i profili non vengono caricati. Per fare ciò, esegui il processo di shell con il file-nessun profiloopzione:

powershell.exe -noprofile

o per eseguire PowerShell Core:

pwsh.exe -noProfile

Come puoi vedere, PowerShell si avvia molto più velocemente quando i profili non vengono caricati. I profili PowerShell sono file PS1 utilizzati per configurare l'ambiente utente. Consentono inoltre all'utente di eseguire comandi specifici e caricare funzioni o moduli personalizzati.

Per impostazione predefinita, i file di profilo di PowerShell non vengono utilizzati (non vengono creati file di profilo). Il comando seguente visualizza un elenco di tutti i file di profilo che verranno caricati all'avvio del processo di PowerShell.

$profile | select *

Controlla manualmente il contenuto di tutti i file di profilo dell'utente oppure utilizza i seguenti comandi per visualizzarli:
Get-Content $PROFILE.AllUsersAllHosts
Get-Content $PROFILE.AllUsersCurrentHost
Get-Content $PROFILE.CurrentUserAllHosts
Get-Content $PROFILE.CurrentUserCurrentHost

Nel mio caso, alcuni comandi vengono aggiunti al fileMicrosoft.PowerShell_profile.ps1file utente. Esaminare il file del profilo per assicurarsi che tutti i comandi e le funzioni siano necessari. Se possibile, rimuovi i comandi non necessari e ottimizza il codice.

Un numero elevato di moduli installati potrebbe essere un'altra possibile ragione per l'avvio lento di PowerShell. PowerShell carica automaticamente i moduli dalle seguenti cartelle:

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

Il loro elenco può essere visualizzato come segue:

$Env:PSModulePath -split ';'

Elenca i moduli PS che sono stati caricati nella sessione.

Get-Module -ListAvailable

Elenca i moduli di terze parti installati.

Get-InstalledModule

Controlla l'elenco per vedere se hai bisogno di tutti i moduli. Disinstallare tutti i moduli PowerShell inutilizzati.:
Remove-Module -Name BurntToast
Uninstall-Module -Name BurntToast -AllVersions -Force

I moduli PowerShell installati manualmente devono essere disinstallati manualmente.

Per analizzare il tempo di caricamento di ciascun modulo, utilizzare il seguente comando:

Measure-Command { Import-Module ModuleName -Force }

Oppure controlla il tempo di caricamento di tutti i moduli PS in blocco:
$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
}
}

Scopri quali moduli impiegano più tempo a caricarsi.

Per impedire il caricamento automatico di tutti i moduli PS, aggiungere la seguente riga al file del profilo:

$PSModuleAutoLoadingPreference="None"

In questo caso, puoi caricare manualmente il modulo richiesto utilizzando il seguente comando:

Import-Module [ModuleName]

Assicurati di aggiungere i seguenti moduli comuni al file del tuo profilo:

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

Esiste anche un problema noto durante il caricamento del modulo PowerShell di VMware Infrastructure Management, noto anche comeVMware PowerCLI. Il caricamento del modulo su un computer non connesso a Internet potrebbe richiedere diversi minuti. Il problema è che in fase di caricamento il modulo cerca di controllare una lista esterna di certificati revocati (CRL,Elenco di revoche di certificati). A causa della mancanza di connettività Internet, questo processo è scaduto. La soluzione èdisabilitare il controllo CRL in Windows. È possibile disattivare il controllo CRL tramite il registro:

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

Oppure nell'applet Proprietà Internet:inetcpl.cpl->Avanzato-> deseleziona l'opzioneVerificare la revoca del certificato dell'editore (server)..

Il motivo per cui l'avvio di PowerShell potrebbe richiedere molto tempo è spesso dovuto al software antivirus installato sul computer. È possibile verificare quali DLL e moduli esterni vengono caricati all'avvio del processo PowerShell.

  1. Aprirecmd.exeed esegui il comando:powershell.exe -c "Write-Host $PID;Start-Sleep -s 60"
  2. Questo comando restituisce l'ID processo (PID) del processo PowerShell.exe in esecuzione. Copia ilPIDe incollalo nel comando seguente in una nuova sessione di PowerShell:
    Get-Process | where {$_.Id -eq <YOUR_PID>} | select -ExpandProperty modules
  3. Riceverai un elenco delle DLL caricate all'avvio del processo PowerShell. Controlla se la tua libreria antivirus è elencata. In tal caso, prova ad aggiungere i processi pwsh.exe e powershell.exe alle eccezioni antivirus.

Ad esempio, puoi utilizzare il comando seguente per aggiungere esclusioni all'antivirus Windows Defender integrato:

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

Leggi anche:Prompt dei comandi di Windows 10: nuova console e console legacy

Se si sospetta che l'avvio lento di PowerShell sia causato dal funzionamento lento della libreria .NET Framework, è possibile compilare tutti gli assembly utilizzati nel codice macchina nativo utilizzando il metodongen.exestrumento (Generatore di immagini native). Ciò migliorerà in modo significativo le prestazioni delle applicazioni .NET, incluso 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
}
}

Il classicoMonitoraggio del processolo strumento può essere utilizzato anche per analizzare il tempo di avvio di PowerShell. (https://technet.microsoft.com/en-us/sysinternals/processmonitor.aspx). CorrereProcMon64.exe, abilitare il filtro sul processo PowerShell.exe, aprire la shell PS e identificare le operazioni che hanno causato il ritardo maggiore.

Nel mio esempio, la lettura del file della cronologia dei comandi di PowerShell gestito dal modulo PSReadline ha richiesto circa 30 secondi. (C:UsersusernameAppDataRoamingMicrosoftWindowsPowerShellPSReadLineConsoleHost_history.txt). Il problema è stato causato daConsoleHost_history.txtfile di dimensioni superiori a 2 GB. La pulizia del file della cronologia ha ridotto significativamente il tempo di avvio di PowerShell.

Related Posts