Oplossing: langzaam opstarten van PowerShell-console en scripts

Ik heb gemerkt dat het soms lang duurt voordat de PowerShell-console wordt geopend. Dit probleem doet zich op verschillende computers voor. In sommige gevallen kan het enkele minuten duren voordat PowerShell is geladen. Dit heeft invloed op het openen van de opdrachtshell zelf (powershell.exe of pwsh.exe) en de uitvoeringstijd van aanmeldings-PowerShell-scripts die via GPO of scripts in de geplande taken worden gestart. In dit bericht wordt uitgelegd hoe u mogelijke redenen voor het trage opstarten van PowerShell kunt identificeren en de laadtijd kunt verkorten.

Hier volgen enkele veelvoorkomende redenen waarom het laden van PowerShell lang kan duren:

  • Door de gebruiker gedefinieerde functies in PowerShell-profielbestanden worden elke keer geladen wanneer het PowerShell.exe-proces wordt gestart
  • Een aanzienlijk aantal PS-modules wordt automatisch geïnstalleerd en geladen
  • De PSReadLine-module laadt een enorm bestand met de geschiedenis van PowerShell-opdrachten
  • Aanzienlijke vertragingen bij het laden van PowerShell en modules worden veroorzaakt door conflicten of corruptie in .NET Framework-componenten.

DeMaatregel-Commandocmdlet kan worden gebruikt om de laadtijd van een PowerShell-proces te meten. Gebruik deze opdracht om de laadtijd van PowerShell in de normale modus te controleren.:

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

De opdracht geeft aan hoe lang het duurde voordat het PowerShell-proces een eenvoudige opdracht laadde en uitvoerde.

Wanneer PowerShell start, rapporteert het mogelijk de tijd die nodig was om te laden.

Loading personal and system profiles took XXX ms

Zoals u in dit voorbeeld kunt zien, duurde het laden van het PowerShell-proces 12 seconden. Dat is best veel. Dit bericht wordt automatisch weergegeven als de laadtijd van PowerShell-profielengroter is dan 500 ms.

Dit suggereert dat PowerShell-profielbestanden elke keer dat het proces start, trage code uitvoeren.

Vergelijk de opstartsnelheid van het PowerShell-proces wanneer profielen niet zijn geladen. Om dit te doen, voert u het shell-proces uit met de-geen profieloptie:

powershell.exe -noprofile

of om de PowerShell Core uit te voeren:

pwsh.exe -noProfile

Zoals u kunt zien, startte PowerShell veel sneller als de profielen niet waren geladen. PowerShell-profielen zijn PS1-bestanden die worden gebruikt om de gebruikersomgeving te configureren. Ze stellen de gebruiker ook in staat specifieke opdrachten uit te voeren en aangepaste functies of modules te laden.

Standaard worden PowerShell-profielbestanden niet gebruikt (er worden geen profielbestanden gemaakt). Met de volgende opdracht wordt een lijst weergegeven met alle profielbestanden die worden geladen wanneer het PowerShell-proces start.

$profile | select *

Controleer de inhoud van alle profielbestanden voor de gebruiker handmatig of gebruik de volgende opdrachten om ze weer te geven:
Get-Content $PROFILE.AllUsersAllHosts
Get-Content $PROFILE.AllUsersCurrentHost
Get-Content $PROFILE.CurrentUserAllHosts
Get-Content $PROFILE.CurrentUserCurrentHost

In mijn geval zijn er enkele opdrachten toegevoegd aan hetMicrosoft.PowerShell_profile.ps1gebruikersbestand. Controleer het profielbestand om er zeker van te zijn dat alle opdrachten en functies nodig zijn. Verwijder indien mogelijk onnodige opdrachten en optimaliseer de code.

Een groot aantal geïnstalleerde modules kan een andere mogelijke reden zijn voor het trage opstarten van PowerShell. PowerShell laadt automatisch modules uit de volgende mappen:

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

Hun lijst kan als volgt worden weergegeven:

$Env:PSModulePath -split ';'

Maak een lijst van de PS-modules die in de sessie zijn geladen.

Get-Module -ListAvailable

Maak een lijst van de geïnstalleerde modules van derden.

Get-InstalledModule

Controleer de lijst om te zien of u alle modules nodig heeft. Verwijder alle ongebruikte PowerShell-modules.:
Remove-Module -Name BurntToast
Uninstall-Module -Name BurntToast -AllVersions -Force

Handmatig geïnstalleerde PowerShell-modules moeten handmatig worden verwijderd.

Gebruik de volgende opdracht om de laadtijd van elke module te analyseren:

Measure-Command { Import-Module ModuleName -Force }

Of bekijk de laadtijd van alle PS-modules in bulk:
$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
}
}

Bekijk welke modules het langst nodig hebben om te laden.

Om te voorkomen dat alle PS-modules automatisch worden geladen, voegt u de volgende regel toe aan het profielbestand:

$PSModuleAutoLoadingPreference="None"

In dit geval kunt u de vereiste module handmatig laden met behulp van de volgende opdracht:

Import-Module [ModuleName]

Zorg ervoor dat u de volgende algemene modules aan uw profielbestand toevoegt:

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

Er is ook een bekend probleem bij het laden van de VMware Infrastructure Management PowerShell-module, ook wel bekend alsVMware PowerCLI. Het kan enkele minuten duren voordat de module is geladen op een computer die geen internetverbinding heeft. Het probleem is dat de module tijdens het laden probeert een externe lijst met ingetrokken certificaten (CRL,Certificaatintrekkingslijst). Door een gebrek aan internetverbinding is er een time-out opgetreden bij dit proces. De oplossing is omschakel CRL-controle uit in Windows. U kunt CRL-controle uitschakelen via het register:

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

Of in de applet Interneteigenschappen:inetcpl.cpl->Geavanceerd–> vink de optie uitControleer of het certificaat van de uitgever (server) is ingetrokken.

De reden dat het lang duurt voordat PowerShell opstart, is vaak de antivirussoftware die op de computer is geïnstalleerd. U kunt controleren welke externe DLL's en modules worden geladen wanneer het PowerShell-proces start.

  1. Opencmd.exeen voer het commando uit:powershell.exe -c "Write-Host $PID;Start-Sleep -s 60"
  2. Met deze opdracht wordt de proces-ID (PID) van het actieve PowerShell.exe-proces geretourneerd. Kopieer dePIDen plak het in de volgende opdracht in een nieuwe PowerShell-sessie:
    Get-Process | where {$_.Id -eq <YOUR_PID>} | select -ExpandProperty modules
  3. U ontvangt een lijst met de geladen DLL's wanneer het PowerShell-proces start. Controleer of uw antivirusbibliotheek in de lijst staat. Als dit het geval is, probeer dan de processen pwsh.exe en powershell.exe toe te voegen aan uw antivirusuitzonderingen.

U kunt bijvoorbeeld de onderstaande opdracht gebruiken om uitsluitingen toe te voegen aan de ingebouwde Windows Defender-antivirus:

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

Lees ook:Windows 10-opdrachtprompt: nieuwe console versus oudere console

Als u vermoedt dat het trage opstarten van PowerShell wordt veroorzaakt door een trage werking van de .NET Framework-bibliotheek, kunt u alle gebruikte assemblies compileren in native machinecode met behulp van dengen.exetool (Native Image Generator). Dit zal de prestaties van .NET-applicaties, inclusief PowerShell, aanzienlijk verbeteren:

$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
}
}

De klassiekerProcesmonitortool kan ook worden gebruikt om de opstarttijd van PowerShell te analyseren. (https://technet.microsoft.com/en-us/sysinternals/processmonitor.aspx). LoopProcMon64.exe, schakel het filter in voor het PowerShell.exe-proces, open de PS-shell en identificeer de bewerkingen die de grootste vertraging hebben veroorzaakt.

In mijn voorbeeld duurde het lezen van het PowerShell-opdrachtgeschiedenisbestand dat werd bijgehouden door de PSReadline-module ongeveer 30 seconden. (C:UsersusernameAppDataRoamingMicrosoftWindowsPowerShellPSReadLineConsoleHost_history.txt). Het probleem werd veroorzaakt door deConsoleHost_geschiedenis.txtbestand groter dan 2 GB. Het opschonen van het geschiedenisbestand verkortte de opstarttijd van PowerShell aanzienlijk.

Related Posts