前回の続きです。
今回の対象範囲
今回は、
についてわかる範囲で補足を入れていく感じにします。
モジュールの自動検出の完全な受け入れ
TODO : もう少し調べる
MSDNを読んでもいまいちなんのためのバグ修正なのかわかりませんでした...
モジュールの自動検出順が、
- PowerShell 3.0 ~ 5.0 :
$PSHome\Modules
→$env:PSModulePath
の順 - PowerShell 5.1 ~ :
$env:PSModulePath
のみ
になったということでしょうか?
また、
これにより、PowerShell によって提供されるコマンド (Get-ChildItem など) を定義するユーザー作成のモジュールを、自動的に読み込み、組み込みコマンドを正しくオーバーライドできます。
との事なのでPowerShell標準のコマンドレットをカスタマイズしやすくするための改善の様です。
ファイルのリダイレクトの非ハードコード化
こちらはわかりやすく、かつ結構な人が望んでいた改善ではないでしょうか。
これまでのPowerShellでは>(>>)
演算子を使ってファイルリダイレクトした場合のエンコーディングはUnicode
固定でした。
これは、>(>>)
演算子は内部的にOut-File
コマンドレットに置き換えられるのですが、その際の引数に-Endoding Unicode
がハードコーディングされていたために起きていました。
PowerShell 5.0だとSystem.Management.Automation.FileRedirection
クラスがOut-File
コマンドレットへの置き換えをになっている様で、ILSpyで中身を見ると、
// WMF 5.0 (Windows 10) internal Pipe GetRedirectionPipe(ExecutionContext context, PipelineProcessor parentPipelineProcessor) { // ・・・(中略)・・・ CommandProcessorBase commandProcessorBase = context.CreateCommand("out-file", false); CommandParameterInternal parameter = CommandParameterInternal.CreateParameterWithArgument(PositionUtilities.EmptyExtent, "Encoding", "-Encoding:", PositionUtilities.EmptyExtent, "Unicode", false, false); commandProcessorBase.AddParameter(parameter); if (this.Appending) { parameter = CommandParameterInternal.CreateParameterWithArgument(PositionUtilities.EmptyExtent, "Append", "-Append:", PositionUtilities.EmptyExtent, true, false, false); commandProcessorBase.AddParameter(parameter); } parameter = CommandParameterInternal.CreateParameterWithArgument(PositionUtilities.EmptyExtent, "Filepath", "-Filepath:", PositionUtilities.EmptyExtent, this.File, false, false); commandProcessorBase.AddParameter(parameter); this.PipelineProcessor = new PipelineProcessor(); this.PipelineProcessor.Add(commandProcessorBase); // ・・・(後略)・・・ }
な感じで-Endoding
パラメーターがハードコードされています。
そして、WMF 5.1ではこの-Endoding Unicode
のハードコードが取り除かれました。
System.Management.Automation.FileRedirection
クラスを見ると、
// WMF 5.1 (Windows 10 Insider Preview) internal Pipe GetRedirectionPipe(ExecutionContext context, PipelineProcessor parentPipelineProcessor) { // ・・・(中略)・・・ CommandProcessorBase commandProcessorBase = context.CreateCommand("out-file", false); CommandParameterInternal parameter = CommandParameterInternal.CreateParameterWithArgument(PositionUtilities.EmptyExtent, "Filepath", "-Filepath:", PositionUtilities.EmptyExtent, this.File, false, false); commandProcessorBase.AddParameter(parameter); if (this.Appending) { parameter = CommandParameterInternal.CreateParameterWithArgument(PositionUtilities.EmptyExtent, "Append", "-Append:", PositionUtilities.EmptyExtent, true, false, false); commandProcessorBase.AddParameter(parameter); } this.PipelineProcessor = new PipelineProcessor(); this.PipelineProcessor.Add(commandProcessorBase); // ・・・(後略)・・・ }
と、
CommandParameterInternal parameter = CommandParameterInternal.CreateParameterWithArgument(PositionUtilities.EmptyExtent, "Encoding", "-Encoding:", PositionUtilities.EmptyExtent, "Unicode", false, false);
の行が消えているのが確認できます。
この修正により、WMF 5.1からは$PSDefaultParameterValues
変数を以下の様に設定することで、>(>>)
演算子を使ったリダイレクトのエンコーディングを変えることができます。
$PSDefaultParameterValues["Out-File:Encoding"] = "Ascii"
なお、$PSDefaultParameterValues
自体はPowerShell 3.0から導入された、コマンドレットを呼ぶ際の引数のデフォルト値を制御するための機能になります。
$PSDefaultParameterValues["[コマンドレット名]:[パラメーター名]"] = [デフォルト値]
の形式でコマンドレットのデフォルト値を制御することができます。
詳細はabout_Parameters_Default_Valuesを参照してください。
メンバーへのアクセスでのバグ再発の修正
こちらはMSDNの説明の通りでしょう。
WMF 5.0 で新しく発生したバグにより、System.Reflection.RuntimeType のメンバーにアクセスできませんでした ([int].ImplementedInterfaces など)。 WMF5.1 ではこのバグが修正されています。
[int].ImplementedInterfaces
で試してみると、以下の様にWMF 5.0では値をとれなかったのがWMF 5.1では正しくとれる様に改善されます。
# WMF 5.0 PS C:\> [int].ImplementedInterfaces PS C:\> # WMF 5.1 PS C:\> [int].ImplementedInterfaces IsPublic IsSerial Name BaseType -------- -------- ---- -------- True False IComparable True False IFormattable True False IConvertible True False IComparable`1 True False IEquatable`1
ただ、この改善がどれくらいの人にとってうれしいのかはよくわかりません...
COM オブジェクトでのいくつかの問題の修正
こちらもMSDNの説明の通り、とくに触れることは無いでしょう。
WMF 5.0 では、COM オブジェクト上のメソッドを呼び出して COM オブジェクトのプロパティにアクセスする新しい COM バインダーが導入されました。
この新しいバインダーによりパフォーマンスが大幅に向上しましたが、バグもいくつか含まれていました。
WMF5.1 ではそれが修正されました。
例として出されているコードは、WMF 5.0、5.1で実行すると以下の様になります。
# WMF 5.0 PS C:\> $obj = new-object -com wscript.shell PS C:\> $obj.SendKeys([char]173) PS C:\> 173 # WMF 5.1 PS C:\> $obj = new-object -com wscript.shell PS C:\> $obj.SendKeys([char]173) PS C:\> -
ちなみにWMF 5.0でこの例を正しく動かすには以下の様に明示的に[string]
にキャストする必要があります。
# WMF 5.0 PS C:\> $obj = new-object -com wscript.shell PS C:\> $obj.SendKeys([string][char]173) PS C:\> -
[ordered] がクラス内で許可されなかった
WMF 5.1ではクラス内で[ordered]
が使える様になりました。
WMF5 では、クラスで使用されるリテラル形を検証するクラスが導入されました。
[ordered] はリテラル形のように見えますが、真の .Net 型ではありません。
WMF5 は、クラスの内の [ordered] で誤ってエラーを報告しました。
について、[ordered]
はPowerShellの言語仕様書にも、
4.3.9 The ordered type
Type ordered is a pseudo type used only for conversions.
とあり、型変換のためだけに使う疑似型であることが明記されています。
WMF 5.0では[ordered]
という特例に対する考慮が漏れていた(もしくは後回しにした)といった感じでしょうか。
複数のバージョンがあるトピックについてのヘルプが機能しない
TODO : もう少し調べる
こちらについては検証環境を作ることができず検証ができませんでした...
とりあえずWMF 5.1では、
WMF 5.1 では、最新バージョンのトピックのヘルプを返すことでこれが解決されています。
だけ押さえておけば良いと思います。