PowerShell 3-DLRがついに登場!

PowerShell 3はWindows 8とともに正式にリリースされます。CTPは、Windows 8 Developer Previewのリリースと共に登場しました(2011年9月の会議// Build / Microsoft)。 2回目のCTPリリースは、クリスマスの直前に登場しました。

数か月間、PowerShell 3で遊ぶ機会がありましたが、今、私の印象についてお話したいと思います。



はじめに



多くのリリースがこのリリースでリリースされましたが、私( と私-およそTranslにとっての主な変更点は、PowerShellがDynamic Language Runtimeに基づいていることです。 共通言語ランタイム(CLR)で動的言語( IronRuby、IronPython-およそtransl。 )を実装できる環境で、これが.NET Frameworkの中核です。 DLRを使用すると、.NET Frameworkで実行される動的言語を簡単に開発できます。 もちろん、PowerShellはもともと.NETフレームワークの動的言語でしたが、以前に登場したため、歴史的にはDLRとは関係ありませんでした。 そして今、PowerShellがついにDLRに移植されました。

PowerShell 3はDLRを使用して実装されていますが、IronPythonやIronRubyと比較して、あらゆる意味で動的言語ではありません。 DLRのドキュメントからいくつかの図を示します。

DLRの概要





図では、3つの主要なセクション(CodePlexのDLR実装)を見ることができます:ホスティング、ランタイム、および言語。 ただし、すべてが.NET Framework 4.0 CLRに移植されているわけではありません。

移植されたDLR





*ピンクで強調表示されている図は、CLR 4.0に移植されたものです-約 perev。

PowerShell 3は、CLRに移植されるすべて(またはほとんどすべて)を利用しますが、開発チームは不本意により、DLRの残りをオペレーティングシステムに移植しませんでした。 したがって、PowerShell 3は、共有ASTおよび式ツリー、DynamicObjectおよびCall Site Cachingランタイムと共にDLR言語実装機能を使用しますが、ScriptRuntime、ScriptScope、ScriptSourceまたはCompiledCodeの共通ホスティングからは何も使用しません。

これは、PowerShellのAPIをホストするIronRubyおよびIronPythonスクリプトを使用できないことを意味します。 ただし、PowerShell 2ホスティングに使用されるものと同じAPIを使用できます。PSObjectの代わりに、C#で出力を処理するときにDynamicを使用する必要があります。 そして、これは実際に重要なことです。

PowerShell 3で発生し、DLRへの移行の直接的な結果であるすべての変更を検討するつもりはありません。 ただし、注意が必要な重大なことがいくつかあります。 まず、パフォーマンスとパフォーマンスの違いに気付くかもしれません。 PowerShell 3のリリースにより、スクリプト、関数、およびコマンドレットのパフォーマンス比、およびスクリプトとバイナリの読み込み時間について知っていたことが忘れられました。 スクリプトと関数は、各呼び出しの前に解釈されなくなりましたが、コンパイルされ、実行され、キャッシュされることさえあります(時々)。 その結果、スクリプトの最初の起動と最初のインポートは予想よりもやや長くなりますが、それ以降のスクリプトおよびそれらからの関数へのすべての呼び出しははるかに高速に実行されます。 そして、これはファイル内のすべてのスクリプトとモジュール内の事前定義関数に適用されます。 同じ関数を数回連続して起動することは、同じコードをコンソールに何度も貼り付けるよりもはるかに高速です。

もう1つの重要な変更点は、PSObjectの放棄です。

PowerShell 3では、PSObjectは実際には動的オブジェクトです。つまり、PSObjectで使用された擬似リフレクションメソッドを使用する代わりに、C#から呼び出されたコマンドレットとスクリプトの出力をdynamicキーワードで使用できます。 ところで、これは氷山の一角にすぎません。



PowerShell 2では、Extended Type System(ETS)のすべてがPSObjectに基づいていました。 types.ps1xmlファイルからでも、オブジェクトのAdd-Member呼び出しからでも、BaseObjectがラップするPSObjectには常に新しいメンバーが追加されています。 PSObjectにラップされていないオブジェクトでAdd-Memberメソッドが呼び出された場合、-Passthruパラメーターを指定して出力を処理し、オブジェクトをPSObjectにラップして、新しいメンバーを追加できるようにする必要がありました。 さらに、オブジェクトが特定のタイプにキャストされた場合、追加されたETSメンバーはほとんどの場合失われました。 以下にスクリプトの例を示します。

$psObject = Get-ChildItem $psObject.Count $Count1 = ($psObject | where { $_.PSIsContainer }).Count [IO.FileSystemInfo[]]$ioObject = Get-ChildItem $ioObject.Count $Count2 = ($ioObject | where { $_.PSIsContainer }).Count $Count3 = ($ioObject | where { $_ -is [IO.DirectoryInfo] }).Count
      
      







PowerShell 2では、$ Count1と$ Count3には現在のディレクトリ内のフォルダーの数が含まれ、$ Count2は常に0になります。 PSIsContainerプロパティは、実際にはFileSystemInfoにキャストすると失われるETSプロパティであるため、この変数は常にゼロとして評価されます。

PowerShell 3では、結果は異なります。 PowerShellはすべてを動的オブジェクトとして機能するようになり、Add-MemberはこれらのETSメンバーを追跡するためにPSObjectを必要としなくなりました。 そのため、上記のスクリプトは、予想どおり、$ Count1、$ Count2、および$ Count3を同じように返します。 明らかに、Add-Memberの「-Passthru」オプションは、単純な割り当てではなく、物事をトンネリングするためにのみ必要です。 ただし、エンティティがPSObjectでラップする価値がある場合があります。

PowerShellをDLRに移植することは大きな前進であることに同意するでしょう。 ただし、すでに実装されている機能を破壊する可能性のある大きな変更に備えてください。 たとえば、上記のスクリプトに次の3行を追加して、PowerShell 2およびPowerShell 3 CTP2で実行してみてください。

 $Count1 -eq $Count2 $e = $ioObject[0] | Add-Member NoteProperty Note "This is a note" -Passthru $f = $ioObject[0] | Add-Member NoteProperty Note "This is a note" -Passthru
      
      





PowerShell 2ではFalseになり、次の2行は問題なく機能します。 PowerShell 3では、最初の行はTrueを返し、PSObjectにラップされていない場合でも、Add-Memberが基になるオブジェクトを変更するため、3行目は「Add-Member:名前のメンバーを追加できません」というエラーを生成します。既に存在します。」

いずれにせよ、将来的には、DLRについて何か別のことを書いて、PowerShellにどのような変更が加えられたのかを書きます。 しかし今のところ、私は心に十分な食べ物があると思います。



All Articles