特集
» 2006年07月26日 00時00分 UPDATE

特集:Windows PowerShellレビュー(後編):Windows PowerShellのパワーの源は.NETオブジェクト (1/3)

マイクロソフトの新シェルでは、コマンドの実行結果はテキストではなくオブジェクトだ。このことはかつてない操作性をもたらす。

[遠藤孝信,デジタルアドバンテージ]
特集:Windows PowerShellレビュー
Insider.NET

 

「特集:Windows PowerShellレビュー」のインデックス

連載目次

 前編ではWindowsの新しいシェルであるWindows PowerShell(以下、PowerShell)の対話式シェルとしての基本機能について紹介した。

 後編となる今回では、PowerShellにおけるオペレーションのベースとなっている「オブジェクトの操作」について解説していく。これはPowerShellがこれまでのテキスト・ベースのシェルと比較して画期的に異なるポイントだ。

コマンドの実行結果はオブジェクト

 これまでのUNIXシェルやWindowsのコマンド・プロンプトで実行されるコマンドの多くは、その実行結果をテキスト・データとして返す。これに対してPowerShellでは、コマンド(Cmdlet)の実行結果はすべて「オブジェクト」である。これはメソッドやプロパティを持った、.NET Frameworkのオブジェクト・モデルをベースとするオブジェクトだ。

 もちろん、最終的に画面に出力されたりファイルへリダイレクトされたりするときにはコマンドの実行結果はテキストとなるのだが、それまでにオブジェクトとしてさまざまな操作が可能だ。PowerShellを実際に使いながらそれを見てみよう。

■dirコマンドが返すファイル情報オブジェクト

 ここではまず、「dirコマンド」(前回で解説したように、これはCmdletの1つである「Get-ChildItemコマンド」のエイリアス)の実行結果をシェル変数$resultに代入する。シェル変数は「$変数名」の形式で表記され、宣言なしで使える(以降の実行例では、キーボードからの入力を黄色い文字で示している)。

PS C:\proj> dir Form1.cs

    Directory: Microsoft.PowerShell.Core\FileSystem::C:\proj

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        2006/07/12     23:05       2422 Form1.cs

PS C:\proj> $result = dir Form1.cs

dirコマンドの実行結果をシェル変数に代入
dirコマンドの実行結果はオブジェクトであるため、シェル変数「$result」にはそのオブジェクトが代入される。

 では、実行結果であるオブジェクトの型を知るために、$resultに対してGetTypeメソッドを呼び出してみよう。.NET開発者ならご存じのように、GetTypeメソッドはすべてのクラスの基本クラスであるObjectクラスで定義されているため、どのオブジェクトもこのメソッドを持っている。

PS C:\proj> $result.GetType()

IsPublic IsSerial Name                    BaseType
-------- -------- ----                    --------
True     True     FileInfo                System.IO.FileSys...

コマンドの実行結果に対するGetTypeメソッドの呼び出し
GetTypeメソッドはその型に関する情報を返す。このメソッドはすべてのクラスの基本クラスであるObjectクラスで定義されているため、どのオブジェクトに対しても呼び出し可能だ。

 このようにdirコマンドはファイル「Form1.cs」の情報をFileInfo型のオブジェクトで返している。これは、.NET Frameworkクラス・ライブラリにあるFileInfoクラス(System.IO名前空間)のオブジェクトだ*

* 実際には完全に同一ではない。PowerShell上でのFileInfoオブジェクトは、.NET Frameworkクラス・ライブラリのFileInfoオブジェクトにいくつかのプロパティやメソッドを追加して拡張している。標準のCmdletがその実行結果として利用する基本的なオブジェクトの多くはそのようになっている。これらの拡張のためのプロパティやメソッドの定義は、PowerShellのインストールされたディレクトリにある「types.ps1xml」で記述されている。また、「Add-Memberコマンド」によりコマンドラインからユーザーが動的にメンバを追加することもできる。


 FileInfoクラスには例えば、そのファイルをコピーするためのCopyToメソッドが用意されている。実際に、このメソッドを以下のようにして呼び出すことができる。

PS C:\proj> $result.CopyTo("c:\tmp\tmp.cs")

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        2006/07/12     23:05       2422 tmp.cs

PS C:\proj> dir /tmp/tmp.cs

    Directory: Microsoft.PowerShell.Core\FileSystem::C:\tmp

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        2006/07/12     23:05       2422 tmp.cs

FileInfo型の実行結果に対するCopyToメソッドの呼び出し
$resultが示すファイル「Form1.cs」をCopyToメソッドにより「c:\tmp\tmp.cs」にコピーしている。メソッド呼び出しの結果、tmp.csについての情報が表示されるのは、このメソッドの戻り値が、コピーされた新しいファイルを示すFileInfoオブジェクトのためである。

 また、FileInfoクラスにはファイルのサイズを取得するためのLengthプロパティも用意されている。もちろんこれも問題なく実行できる。

PS C:\proj> $result.Length
2422

FileInfo型の実行結果に対するLengthプロパティのアクセス
FileInfoクラスのLengthプロパティはそのファイルのサイズを返す。

 ちなみに、Lengthプロパティの型は64ビット符号付き整数であるInt64型である。

PS C:\proj> $result.Length.GetType()

IsPublic IsSerial Name                        BaseType
-------- -------- ----                        --------
True     True     Int64                       System.ValueType

FileInfoクラスのLengthプロパティの型
ファイル・サイズを取得するLengthプロパティの値も単なる数値ではなく、実際にはInt64型のオブジェクトである。

 FileInfo型についての情報はMSDNなどに記述されているが、あるオブジェクトがどのようなメンバ(=メソッドやプロパティ)を持っているかは「Get-Memberコマンド」により参照可能だ*

PS C:\proj> Get-Member -InputObject $result

   TypeName: System.IO.FileInfo

Name          MemberType  Definition
----          ----------  ----------
AppendText    Method      System.IO.StreamWriter AppendText()
CopyTo        Method      System.IO.FileInfo CopyTo(String de...
Create        Method      System.IO.FileStream Create()
CreateObjRef  Method      System.Runtime.Remoting.ObjRef Crea...
CreateText    Method      System.IO.StreamWriter CreateText()
Decrypt       Method      System.Void Decrypt()
……以下省略……

Get-Memberコマンドによるオブジェクトのメンバ一覧表示
Get-Memberコマンドでは-InputObjectオプションにより、対象となるオブジェクトを指定する。

* ここでは入力オブジェクトを-InputObjectオプションにより指定しているが、Get-Memberコマンドはパイプ(|)と組み合わせて使用するのが一般的だ。これについては後述する。


 なお、ここまでは分かりやすいようにコマンドの実行結果を最初にシェル変数に代入したが、実際にはコマンドをカッコでくくることにより、その実行結果のオブジェクトを直接扱うことができる。つまり以下のような実行が可能だ。

PS C:\proj> (dir Form1.cs).GetType()

IsPublic IsSerial Name                    BaseType
-------- -------- ----                    --------
True     True     FileInfo                System.IO.FileSys...

カッコによるコマンドの実行結果の参照
コマンドをカッコでくくることにより、その実行結果となるオブジェクトを直接扱うことができる。

 以下の例では、この記述方法を使っていく。

■オブジェクトの配列を返すdirコマンド

 ここまでの例では、dirコマンドのパラメータに「Form1.cs」を指定して1つのファイルについてのオブジェクトを扱ったが、dirコマンドは通常、複数のファイルやディレクトリを返す。このような場合にはコマンドの結果はオブジェクトの配列となる。

PS C:\proj> (dir).GetType()

IsPublic IsSerial Name                            BaseType
-------- -------- ----                            --------
True     True     Object[]                        System.Array

dirコマンドの実行結果の型
実行結果の型が「Object[]」となっていることから、それがObject型のオブジェクトの配列であることが分かる。

 配列では、その要素数(dirコマンドの場合にはファイルやディレクトリの総数)をLengthプロパティから得ることができる。

PS C:\proj> (dir).Length
8

PS C:\proj> dir

    Directory: Microsoft.PowerShell.Core\FileSystem::C:\proj

Mode            LastWriteTime   Length Name
----            -------------   ------ ----
-a---    2006/07/12     23:05     2422 Form1.cs
-a---    2006/07/10     17:15     1333 Form1.Designer.cs
-a---    2006/07/10     17:15      344 Form2.cs
-a---    2006/07/12     23:06      521 Program.cs
-a---    2006/07/10     17:15     3093 WindowsApplication1.csproj
d----    2006/07/12     23:00          bin
d----    2006/07/12     23:00          obj
d----    2006/07/12     23:00          Properties

dirコマンドの実行結果の要素数
dirコマンドは結果を配列で返すが、その要素数はArrayクラス(System名前空間)のLengthプロパティにより取得できる。ここではファイルとディレクトリが合計8個あるので、Lengthプロパティの値は8となる。

 また、配列の各要素へは大カッコ([])によりアクセスできる。

PS C:\proj> (dir)[0]

    Directory: Microsoft.PowerShell.Core\FileSystem::C:\proj

Mode            LastWriteTime   Length Name
----            -------------   ------ ----
-a---    2006/07/12     23:05     2422 Form1.cs

PS C:\proj> (dir)[0].Name
Form1.cs

配列の要素へのアクセス
配列の個々の要素へは大カッコでインデックス番号を指定してアクセスする。「(dir)[0]」はdirコマンドの実行結果の先頭のオブジェクトを示している。

 配列の全要素を順に操作したければ、foreachステートメントが使える*。foreachステートメントの記述方法はC#のそれとほぼ同様だ。以下の例では、拡張子が.csの各ファイルに対して、そのファイル名のみを小文字で表示している。

PS C:\proj> foreach ($file in dir *.cs) { $file.Name.ToLower() }
form1.cs
form1.designer.cs
form2.cs
program.cs

foreachステートメントによる配列要素のアクセス
「dir *.cs」の実行結果として返される配列の各要素が順にシェル変数$fileに代入され、中カッコ({})内のスクリプト(スクリプト・ブロックと呼ばれる)が実行される。ここではファイル名を得るためのNameプロパティを呼び出し、さらにそのToLowerメソッドを呼び出して小文字に変換している。NameプロパティはString型であり、ToLowerメソッドはStringクラスのメソッドである。

* PowerShellにはこれ以外にif、for、whileなどのステートメントが用意されている。これらはコマンドラインからも利用できるが、シェル・スクリプトの記述時に使用されるのが一般的だ。


■プロセスの操作

 ここまではファイルを扱ってきたが、別の例として実行中のプロセスを扱う場合についても簡単に紹介しておこう。

 実行中のプロセスの一覧はUNIXでは「psコマンド」で得られるが、PowerShellではそれが「Get-Processコマンド」のエイリアスとして用意されている。

PS C:\proj> ps

Handles  NPM(K)  PM(K)  WS(K) VM(M)  CPU(s)    Id ProcessName
-------  ------  -----  ----- -----  ------    -- -----------
    137       7   3484   6152    51    1.44   464 04WebServer
    106       6   1224   3608    35    0.03  2512 alg
     39       3   1880   4560    40    0.36  2996 ATOK17MN
    149       5   5192   9512    63    0.38  2620 CameraAssistant
    333      12   7572  13752   100    1.80  3188 CCAPP
    261       7   2808   2072    53    0.30  1940 CCEVTMGR
    185       5   2592   3660    38    0.25  1892 CCSETMGR
     51       3   2144   5728    44    0.08   772 conime
    625       7   2584   8348    76   22.08  1084 csrss
    130       6   1864   5500    48    4.06  3300 ctfmon
     72       4   2524   5252    43    0.27  1684 daemon
     79       4   2944   3692    50    0.72   768 dice

psコマンドによる実行中のプロセス一覧
項目ヘッダの項目名はそれぞれ以下のProcessクラスのプロパティを示している。
・NPM:NonpagedSystemMemorySize
・PM:PagedMemorySize
・WS:WorkingSet
・VM:VirtualMemorySize
・CPU:TotalProcessorTime

 このように、psコマンドでは現在実行されているプロセスの一覧が、メモリ使用量やCPU使用時間などとともに表示される。

 psコマンドも先ほどのdirコマンドと同様にオブジェクトの配列を返す。

PS C:\proj> (ps).GetType()

IsPublic IsSerial Name                            BaseType
-------- -------- ----                            --------
True     True     Object[]                        System.Array

psコマンドの実行結果の型
psコマンドの実行結果もdirコマンドと同様にオブジェクトの配列となっている。

 配列の要素となっているオブジェクトはこの場合、Processクラス(System.Diagnostics名前空間)のオブジェクトである。

PS C:\proj> ps explorer

Handles  NPM(K)  PM(K)  WS(K) VM(M)  CPU(s)    Id ProcessName
-------  ------  -----  ----- -----  ------    -- -----------
    643      19  25900  40272   149  139.95  2744 explorer

PS C:\proj> (ps explorer).GetType()

IsPublic IsSerial Name                    BaseType
-------- -------- ----                    --------
True     False    Process                 System.ComponentM...

psコマンドの実行結果の配列要素の型
ここではエクスプローラがすでに実行されているものとする。psコマンドが表示する各プロセスは、Process型のオブジェクトである。

 以下の例ではメモ帳(notepad.exe)を起動し、そのウィンドウのタイトルを表示してから、Killメソッドを呼び出すことによって強制終了させている。

PS C:\proj> notepad
PS C:\proj> (ps notepad).MainWindowTitle
無題 - メモ帳
PS C:\proj> (ps notepad).Kill()

Processオブジェクトによるプロセスの操作
メモ帳(notepad.exe)を起動し、そのウィンドウのタイトルを表示してから、Killメソッドを呼び出して強制終了させている。

 なおここではKillメソッドを呼び出しているが、Cmdletとして「Kill-Processコマンド」(エイリアス名は「kill」)が用意されており、プロセスを強制終了させるには通常こちらを使う。

       1|2|3 次のページへ

Copyright© 1999-2017 Digital Advantage Corp. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

Focus

- PR -

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。