tech.guitarrapc.cóm

Technical updates

PowerShell 4.0 の機能についてまとめてみる (前編)

先日Windows 8.1やWindows Server 2012 R2がリリースされました。ようやく、PowerShell 4.0が一般でも利用開始になりうれしいことです。

さて、PowerShell 4.0ですが、DSCなど大きくアピールされていることの他にも修正や追加が入っています。今回はそれらをさくっと説明してみましょう。

What's New in Windows PowerShell

原文はTechNetで公開されています。

What's New in Windows PowerShell

最終更新が、記事時点ではAugust 21, 2013です。

New features in Windows PowerShell (Windows PowerShell の新機能)

Windows PowerShell Desired State Configuration (DSC)

Windows PowerShell 4.0の目玉機能と言われ紹介されています。

これまでの命令型プログラミング(Imperative Programming)とは違う、宣言型プログラミング(Declarative programming)であることにフォーカスが当たっていますが、その目的はPowerShellの大本とは変わっていません。

DSCは、Automationをより簡潔に記述し、再実行性を持たせ、Push/Pull型に対応するための仕組みと言えます。

より詳しくは本ブログでも今後扱いますが、今は過去記事TechNet - get started with windows powershell desired state configuration.を。

新コマンドSave Helpが追加されました。

イントラネット内部のリモートコンピュータに、任意のモジュールのヘルプをSave-Help Cmdletで保存可能になりました。

インターネットアクセスが可能なコンピュータで、Save-HelpCmdletを利用して、ヘルプが必要なModuleのHelpをインターネット上取得します。

そのファイルを、リモートPCや共有フォルダに置くことでリモートコンピュータはヘルプを利用可能になります。

例えば、Save-Help -DestinationPath d:\hoge -Module Microsoft.PowerShell.Managementのようにします。

Debugerの機能強化 - PowerShell Workflow / Remoting

PowerShell Workflowに関するデバッガーが機能強化されています。

例えリモートコンピュータで実行しているスクリプトであっても、リモートセッション越しにデバッグが可能になりました。これで、Workflowは、スクリプトレベルでPowerShell, PowerShell ISEの両方でデバッグが可能です。

またリモートデバッグセッションは、例えPowerShellリモートセッションが切断し再接続しても保持されます。

Register-ScheduledJobSet-ScheduledJobにRunNowパラメータが追加

即時実行のため、RunNowパラメータが追加されました。 これまでは、Triggerの設定が必要でしたが即時実行の際はRunNowで行えます。

Invoke-RestMethodInvoke-WebRequestでヘッダーをセット可能に

これらのCmdletで、-Headersパラメータを使ってWebRequestに全ヘッダーを付与可能になっています。

IDictionaryとなるので、このような感じです。

$headers = @{
    "X-SAP-LogonToken" = $logonToken ;
    "X-SAP-PVL"        = "fr-FR"}

Invoke-RestMethod -Method Get -Uri http://example.com -Headers $headers

Get-ModuleFullyQualifiedNameパラメータ(ModuleSpecification[]型)が追加されました。

PowerShell3.0まではNameパラメータで判断するしかありませんでした。4.0からはFullyQualifiedNameパラメータで、ModuleNameとModuleVersion、GUIDの内2つ以上の組み合わせを指定できます。

例えば次のようなことが可能です。

PS> Get-Module -FullyQualifiedName @{Modulename="valentia";Moduleversion="0.0"}

-------
ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Script     0.0        valentia                            {Get-ValentiaCredential, Get-ValentiaGroup, Get-ValentiaMo...

Windows Server 2012 R2 のデフォルトの ExecutionPolicyがRemoteSignedになりました

これまでは、Restrictedでしたが、RemoteSignedに変わり、デフォルトでスクリプト実行が可能になっています。

うれしいですね!

なお、Windows8.1では、これまで通りRestrictedです。

Dynamic Method が可能になりました。

過去に「PowerShell Version 4では property 以外に methodも dynamic Invokeできるようになりました」で紹介しています。これまでは動的なプロパティ名実行は可能でしたが、メソッド名実行は出来ませんでした。

つまり、このような実行が可能になっています。

$method = "GetType"
$path.$method()

非同期実行されているWorkflow JobがPSElapsedTimeoutSecでタイムアウトになっても消されないようになりました。

そのままです。PowerShell WorkflowのコモンパラメータであったPSElapsedTimeoutSecで時間制限を超えても、WorkflowJobが削除されなくなっています。

New-JobTriggerSet-JobTriggerに新たにRepeatIndefinitelyパラメータが追加されています。

これまでは、-RepetitionDurationで、繰り返し実行の期間を明確に定める必要がありました。

そのため、2時間以内の5分ごと繰り返しは、RepetitionIntervalを5分、RepetitionDurationを2時間として設定可能でした。

が、2時間とは限らず、最大時間が不定な場合に困りました。

今後、PowerShell 4.0では、RepetitionDurationが不定の場合は、RepeatIndefinitelyパラメータを指定することで最大長の指定をしないことが可能です。

Enable-JobTriggerDisable-JobTriggerPassThruパラメータが追加されました。

これで、Objectの生成結果を処理したり受け渡せます。

Add-ComputerRemove-ComputerでWorkGroupを示すパラメータは、WorkGroupNameになりました。

従来は、Add-ComputerWorkgroupName。 一方で、Remove-Computerで、Workgroupとなっていました。

新コモンパラメータとしてPipelineVariableが追加されました。

これにより、パイプラインで渡していく処理で、Foreach-Objectを使って自動変数を変数に格納していた処理が簡易になりえます。

例えば、PowerShell 3.0までで、フォルダの各ファイルをフォルダ\ファイルで示す場合このようにしていました。

Get-ChildItem *.ps1 |
    % {$fi = $_; $_} |
    Select-String function |
    % {"$($fi.Directory.BaseName)\$($_.Filename)"}

それが、PipelineVariableを使うことで、一段Foreach-Objectを減らせるようになります。

Get-ChildItem *.ps1 -PipelineVariable fi |
    Select-String function |
    % {"$($fi.Directory.BaseName)\$($_.Filename)"}

便利ですね。PowerShellは、 Pipeline Orientatedでもあるので、これは大きいです。

自身でキーワードを設定できるようになりました。

これは理解できていないです。

コレクションのメソッド構文でのフィルタリングサポート

これまで、コレクションのフィルタといえば、パイプラインを通してのWhere-Objectでした。

が、PowerShell4.0からは、メソッド形式で.Where().ForEach()がサポートされています。

内部のフィルタは、ScriptBlock内での{}匿名デリゲートとなります。*1

例えば、従来のフィルタはこのように行いました。

Get-Process | where WorkingSet -gt 100000000

メソッド構文を利用することで、このように書けます。結果は両方とも同じです。

(Get-Process).Where({$_.WorkingSet -gt 100000000})

Handles NPM(K)  PM(K)  WS(K) VM(M)   CPU(s)   Id ProcessName
------- ------  -----  ----- -----   ------   -- -----------
    518     34 140536 148816   557   390.88 4796 chrome
    206     69 128280 152664   312 1,234.63 5576 chrome
   1755     88 114404 175160   526   410.77 6932 chrome
   1750    519  83476 185532   730    59.80 7528 explorer
   1090     91  79200 105416   483   203.20 6992 iTunes
   2196    182 334824 382808  1053 4,713.41 7424 krile
    823     51 149400 159900   434   134.11 5456 opera
    589     34 107648 104716   444   118.20 7076 opera
   2956     95 127636 170304   531   282.59 7420 opera
    911    140 194076 234700  1060    84.28 4492 powershell_ise
   1393     60 194376 192848   492     3.48 8064 RDCMan
   1031     98 195164 210976   797    58.22 6032 SourceTree
    776     79  85532 120212   374     8.17 3540 WWAHost

また、ForEachも同様です。例えば、従来のForeach-Objectで行っていた処理がこのように書けます。

# これが
1..10 | Foreach-Object {"[" + $_ + "]"}

# こう
(1..10).ForEach({"[" + $_ + "]"})

これらは、一度変数に入れることで、メソッド構文のメリットを受けられます。*2

$array = 1..10
$array.ForEach({"[" + $_ + "]"})

ScriptBlockの匿名デリゲート内部ではまだインテリセンスのサポートも効かないため、これからに期待です。

Get-ProcessIncludeUserNameスイッチが追加されました。

これまで、Get-Processでは、そのプロセスの実行ユーザー名が取得できませんでした。

PowerShell 4.0からは、管理者の昇格したPowerShellでプロセスの実行ユーザが取得可能です。

PS> Get-Process -IncludeUserName

Handles      WS(K) VM(M)   CPU(s)     Id UserName          ProcessName
-------      ----- -----   ------     -- --------          -----------
    286      16280   115     0.69   7892 WINDOWS81X64\a... AppleMobileDeviceHelper
    347      11588   101    16.47   1548 NT AUTHORITY\S... AppleMobileDeviceService
    267      11392   110     0.58   8008 WINDOWS81X64\a... ATH
    155       9572    39    84.45   4236                   audiodg
    188      40360   196     1.36   2320 WINDOWS81X64\a... chrome
    208      27904   243   576.30   3376 WINDOWS81X64\a... chrome
    518     154844   557   404.06   4796 WINDOWS81X64\a... chrome
    206     116052   276 1,349.55   5576 WINDOWS81X64\a... chrome
    195      88860   266    44.73   6308 WINDOWS81X64\a... chrome

また、UserNameの表示順を一番右にしたいなどという場合は、C:\Windows\System32\WindowsPowerShell\v1.0\DotNetTypes.format.ps1xmlを調整も可能です。

新コマンドGet-FileHashが追加されました。

これまでのファイルハッシュは、.NETを使っていました。PowerShellでもファイルハッシュが取得できます。

PS> Get-FileHash -Path d:\hoge.exe

Algorithm       Hash                                                                   Path
---------       ----                                                                   ----
SHA256          A6C92C7FED82F0D531BAE8254D33BF7D27BF3AAF4102407ED5F6771CBE660609       D:\hoge.exe

Module を修飾名で実行する必要がある場合があります。

  1. マニュフェストでDefaultCommandPrefixキーをしている場合
  2. あるいは、Prefix付でModuleをインポートした場合

これらの場合、ExportedCommandsではprefix付でモジュールのコマンドが表示されます。

その場合は、コマンド名ではなくModule\コマンド名とprefix付でで実行する必要があります。

$PSVersionTable.PSVersion が 4.0になりました。

以下がWindows 8.1での表示です。

$PSVersionTable

Name                           Value
----                           -----
PSVersion                      4.0
WSManStackVersion              3.0
SerializationVersion           1.1.0.1
CLRVersion                     4.0.30319.34003
BuildVersion                   6.3.9600.16394
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0}
PSRemotingProtocolVersion      2.2

まとめ

まずは、New features in Windows PowerShellについて紹介しました。

次回は、PowerShell 4.0の残りの更新内容を紹介します。

  • New features in Windows PowerShell Integrated Scripting Environment (ISE)
  • New features in Windows PowerShell Workflow
  • New features in Windows PowerShell Web Services
  • New features in Windows PowerShell Web Access
  • Notable bug fixes in Windows PowerShell 4.0

お楽しみに!

*1:Previewまでは、String内に記述.Where("$_.WorkingSet -gt 1000000000")だったので改善ですね。

*2:コマンドからだと括弧でくくる必要があるので使いにくい