コードを読むの楽しいですね。
さて、今回は みんな大嫌いなレジストリを PowerShell で扱うものです。
【リリース後に確認された問題】2014 年 8 月 13 日公開の更新プログラムの適用により問題が発生する場合がある記事がいま話題です。
早速、できる大人 @kkamegawa さんが問題のレジストリ走査をするスクリプトを書いてくださっています。
今回はこのスクリプトをパイプラインでちょいんとつなげてみることで、PowerShell のパイプラインな書き心地を楽しんでみましょう。
目次
パイプラインを使うなら
判定はWhere-Object
単純な成否のフィルタリングなら、Where-Object
が使えます。
もちろんif
での判定でもいいのですが、成否それぞれに処理をするのではなく、狙ったものだけを次のパイプラインに渡すのであればとても便利です。
Foreach か Foreach-Objectか
今回は、パイプラインをつなげるので Foreach-Obejct
を使います。
賛否両論なのか、なにか知りませんが(!?)、この2つは正確が異なります。
- Foreach の場合は、いったんコレクションを舐めてから、一斉に操作しています
Foreach ($x in $collection) { }
- Foreach-Objectは、コレクションをとりだして、一件ずつパイプラインの先に渡しています。この時処理に要したメモリはパイプラインをすぎると処理されてます
$collection | %{$_}
この性質の違いのため、Foreach
は比較的高速に動作します。が、コレクションをいったんメモリにのせてから処理をするのでメモリを多く食う傾向にあります。
一方で、Foreach-Object
は、パイプラインを渡すコストもあり、処理がForeach
より遅くなりがちですが、メモリが適正に処理されるので好ましい時が多いでしょう。
検証環境
Windows 8.1 Update1 で動かしている PowerShell V5 May Preview です。
PowerShell V3 以上でないと動きませんので、Windows 7な方はご注意ください。 (Windows 7 のデフォルトは V2なので)
コード
ということで、ちょいん
MS14-045 issue check by piepline.
1行にできますが、自重しました。
改行
はい
$message = "font '{0}' found! Your environmet will trouble with MS14-045. See https://support.microsoft.com/kb/2982791" $fontregistory = 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts\' (Get-Item -Path $fontregistory).Property ` | % { (Get-ItemProperty -path $fontregistory).$_ ` | where {$_.EndsWith('.otf')} ` | where {Test-Path $_} ` | %{ Write-Host ($message -f $_) -ForegroundColor Red;return} } Write-Host 'Your environment is OK.'
V2 な冗長な書き心地
もうヤダ
$message = "font '{0}' found! Your environmet will trouble with MS14-045. See https://support.microsoft.com/kb/2982791" $fontregistory = 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts\' (Get-Item -Path $fontregistory) | select -ExpandProperty Property | % {$x=$_; Get-ItemProperty -path $fontregistory | select -ExpandProperty $x | where {$_.EndsWith('.otf')} | where {Test-Path $_} | %{ Write-Host ($message -f $_) -ForegroundColor Red;return}} Write-Host 'Your environment is OK.'
まとめ
やってることは変わりません。が、こういう書き方もあるんだよーということで。
ちなみに処理速度は、おおよそ同じですね。メモリもわずかな違いです。
- Foreach
TotalSeconds : 7.2915443
- パイプライン
TotalSeconds : 7.1580007
レジストリは二度舐めが発生するのが面倒ですにぇ。