修正: PowerShell コンソールとスクリプトの起動が遅い

PowerShell コンソールを開くのに時間がかかることがあります。この問題は別のコンピュータで発生します。場合によっては、PowerShell の読み込みに数分かかることがあります。これは、コマンド シェル自体 (powershell.exe または pwsh.exe) を開くことと、GPO 経由で起動されるログオン PowerShell スクリプトまたはスケジュールされたタスク内のスクリプトの実行時間に影響します。この投稿では、PowerShell の起動が遅い潜在的な原因を特定し、読み込み時間を短縮する方法について説明します。

PowerShell の読み込みに時間がかかる一般的な理由は次のとおりです。

  • PowerShell プロファイル ファイル内のユーザー定義関数は、PowerShell.exe プロセスが開始されるたびに読み込まれます。
  • かなりの数の PS モジュールがインストールされ、自動的にロードされます
  • PSReadLine モジュールは、PowerShell コマンドの履歴を含む巨大なファイルをロードします
  • PowerShell およびモジュールの読み込みの大幅な速度低下は、.NET Framework コンポーネントの競合または破損が原因で発生します。

測定コマンドコマンドレットを使用して、PowerShell プロセスの読み込み時間を測定できます。このコマンドを使用して、通常モードでの PowerShell のロード時間を確認します。

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

このコマンドは、PowerShell プロセスが単純なコマンドをロードして実行するのにかかった時間を表示します。

PowerShell が起動すると、読み込みにかかった時間が報告される場合があります。

Loading personal and system profiles took XXX ms

この例からわかるように、PowerShell プロセスの読み込みには 12 秒かかりました。それはかなり多いです。このメッセージは、PowerShell プロファイルの読み込み時間が長くなった場合に自動的に表示されます。500ミリ秒を超える.

これは、プロセスが開始されるたびに、PowerShell プロファイル ファイルが遅いコードを実行していることを示唆しています。

プロファイルが読み込まれていない場合の PowerShell プロセスの起動速度を比較します。これを行うには、次のコマンドを使用してシェル プロセスを実行します。-noprofileオプション:

powershell.exe -noprofile

または、PowerShell コアを実行するには:

pwsh.exe -noProfile

ご覧のとおり、プロファイルが読み込まれていない場合、PowerShell の起動ははるかに速くなりました。 PowerShell プロファイルは、ユーザー環境の構成に使用される PS1 ファイルです。また、ユーザーは特定のコマンドを実行したり、カスタム関数やモジュールをロードしたりすることもできます。

デフォルトでは、PowerShell プロファイル ファイルは使用されません (プロファイル ファイルは作成されません)。次のコマンドは、PowerShell プロセスの開始時に読み込まれるすべてのプロファイル ファイルのリストを表示します。

$profile | select *

ユーザーのすべてのプロファイル ファイルの内容を手動で確認するか、次のコマンドを使用して表示します。
Get-Content $PROFILE.AllUsersAllHosts
Get-Content $PROFILE.AllUsersCurrentHost
Get-Content $PROFILE.CurrentUserAllHosts
Get-Content $PROFILE.CurrentUserCurrentHost

私の場合、いくつかのコマンドがMicrosoft.PowerShell_profile.ps1ユーザーファイル。プロファイル ファイルを調べて、すべてのコマンドと機能が必要であることを確認します。可能であれば、不要なコマンドを削除し、コードを最適化します。

インストールされているモジュールの数が多いことも、PowerShell の起動が遅い原因として考えられます。 PowerShell は、次のフォルダーからモジュールを自動的に読み込みます。

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

それらのリストは次のように表示できます。

$Env:PSModulePath -split ';'

セッションにロードされた PS モジュールをリストします。

Get-Module -ListAvailable

インストールされているサードパーティ モジュールを一覧表示します。

Get-InstalledModule

リストをチェックして、すべてのモジュールが必要かどうかを確認してください。未使用の PowerShell モジュールをアンインストールします。
Remove-Module -Name BurntToast
Uninstall-Module -Name BurntToast -AllVersions -Force

手動でインストールした PowerShell モジュールは手動でアンインストールする必要があります。

各モジュールのロード時間を分析するには、次のコマンドを使用します。

Measure-Command { Import-Module ModuleName -Force }

または、すべての PS モジュールのロード時間を一括で確認します。
$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
}
}

どのモジュールのロードに最も時間がかかるかを確認します。

すべての PS モジュールが自動的にロードされないようにするには、プロファイル ファイルに次の行を追加します。

$PSModuleAutoLoadingPreference="None"

この場合、次のコマンドを使用して、必要なモジュールを手動でロードできます。

Import-Module [ModuleName]

次の共通モジュールをプロファイル ファイルに必ず追加してください。

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

また、VMware Infrastructure Management PowerShell モジュール (別名) をロードするときに既知の問題もあります。VMware PowerCLI。インターネットに接続されていないコンピューターにモジュールを読み込むには、数分かかる場合があります。問題は、モジュールのロード時に、取り消された証明書の外部リスト (CRL、CRL、証明書失効リスト)。インターネット接続がないため、このプロセスはタイムアウトになりました。解決策は、Windows での CRL チェックを無効にする。レジストリを使用して CRL チェックを無効にできます。

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

または、インターネット プロパティ アプレットで次のようにします。inetcpl.cpl->高度な–> オプションのチェックを外します発行者 (サーバー) 証明書の失効を確認する.

PowerShell の起動に時間がかかる理由は、多くの場合、コンピューターにインストールされているウイルス対策ソフトウェアにあります。 PowerShell プロセスの開始時に、どの外部 DLL とモジュールが読み込まれるかを確認できます。

  1. 開けるcmd.exeそして、次のコマンドを実行します。powershell.exe -c "Write-Host $PID;Start-Sleep -s 60"
  2. このコマンドは、実行中の PowerShell.exe プロセスのプロセス ID (PID) を返します。をコピーしますPIDそれを新しい PowerShell セッションの次のコマンドに貼り付けます。
    Get-Process | where {$_.Id -eq <YOUR_PID>} | select -ExpandProperty modules
  3. PowerShell プロセスの開始時に、ロードされた DLL のリストを受け取ります。ウイルス対策ライブラリがリストにあるかどうかを確認してください。その場合は、pwsh.exe プロセスと powershell.exe プロセスをウイルス対策例外に追加してみてください。

たとえば、以下のコマンドを使用して、組み込みの Windows Defender ウイルス対策に除外を追加できます。

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

こちらもお読みください:Windows 10 コマンド プロンプト: 新しいコンソールと従来のコンソール

PowerShell の起動の遅さの原因が .NET Framework ライブラリの動作の遅さであると思われる場合は、使用するすべてのアセンブリをネイティブ マシン コードにコンパイルできます。ngen.exeツール (ネイティブ イメージ ジェネレーター)。これにより、PowerShell を含む .NET アプリケーションのパフォーマンスが大幅に向上します。

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

古典的なプロセスモニターこのツールを使用して、PowerShell の起動時間を分析することもできます。 (https://technet.microsoft.com/en-us/sysinternals/processmonitor.aspx)。走るProcMon64.exe、PowerShell.exe プロセスのフィルターを有効にし、PS シェルを開いて、最大の遅延の原因となった操作を特定します。

私の例では、PSReadline モジュールによって保持されている PowerShell コマンド履歴ファイルの読み取りに約 30 秒かかりました。 (C:UsersusernameAppDataRoamingMicrosoftWindowsPowerShellPSReadLineConsoleHost_history.txt)。問題の原因は、ConsoleHost_history.txtサイズが 2 GB を超えるファイル。履歴ファイルをクリーニングすると、PowerShell の起動時間が大幅に短縮されました。

Related Posts