PowerShell Memo

このサイトはPowerShell(MSH/Monad)奮闘記です

管理人「newpops吉岡洋」が
「PowerShell(旧名:MSH/Monad)」の研究結果を日々綴っていきます。

【お知らせ】
この日記からPowerShellのTipsを抽出し「PowerShell FAQ」として整理しました。


2005-12-27

[]ファイルをダウンロードする

「System.Net.WebClient」はファイルのダウンロードアップロードができます。

ファイルのダウンロード(ファイルを保存)

ファイルの読み込み処理 - PowerShell Memoのサンプルと同様です。

ダウンロードしたファイルを保存する
MSH C:\> $url="http://www.google.co.jp/intl/ja_jp/images/logo.gif"
MSH C:\> $webClient = new-object System.Net.WebClient
MSH C:\> $webClient.DownloadFile($url, "C:\logo.gif")

ファイルのダウンロード(Stream)

ダウンロードしたファイルの内容を取得する
MSH C:\> $url="http://www.google.co.jp/index.html"
MSH C:\> $webClient = new-object System.Net.WebClient
MSH C:\> $stream = $webClient.OpenRead($url)
MSH C:\> $stream.getType().fullname
System.Net.ConnectStream
MSH C:\> $reader = new-object System.IO.StreamReader($stream)
MSH C:\> $reader.ReadToEnd()
<html><head><meta http-equiv="content-type" content="text/html; 
(中略)
  • OpenReadメソッドで「ConnectStream」を取得。
  • Stream型のオブジェクトは「System.IO.StreamReader」で読み込み処理を行います。
  • ReadToEndメソッドはStreamを最後まで読み込みます。
  • 1行ずつ読み込む場合はReadLineメソッドです。

2005-12-26

[]ファイルの読み込み処理

ファイルを行単位で処理する

「get-contents」はファイル内容を取得するCmdletです。

「get-contents」をパイプ経由でforeachに渡すと、ファイル内容を行単位で処理できます。

テキストファイルに書かれたURLを読み込んでファイルをダウンロードする

URLを書いたテキストファイル(URL.txt)
MSH C:\> get-content .\URL.txt
http://www.google.co.jp/intl/ja_jp/images/logo.gif
http://rss.rssad.jp/rss/itm/rss.xml
URLを読み込んでダウンロードする
MSH C:\> $webClient = new-object System.Net.WebClient
MSH C:\> $saveDir = "C:\Download\"
MSH C:\> get-content .\URL.txt | foreach{
>> $fileName = $_.SubString($_.LastIndexOf("/") + 1);
>> $webClient.DownloadFile($_, $saveDir + $fileName);
>> }
>>
ダウンロードしたファイルを確認する
MSH C:\> ls C:\Download


    Directory: FileSystem::C:\Download


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        2005/12/27      1:49       8754 logo.gif
-a---        2005/12/27      1:49      13093 rss.xml

2005-12-25

[]パラメータ群が複数ある場合の調べ方(3)

パラメータ群が複数ある場合の調べ方(2) - PowerShell Memoの続きです。

Cmdletのパラメータを調べる

今回は「new-object」の「Com」パラメータ群について調べてみましょう。

ParameterSetInfo(Com)
MSH C:\> $((gcm new-object).ParameterSets)[1].Name
Com
MSH C:\> $((gcm new-object).ParameterSets)[1].Parameters


Name                            : ComObject
Type                            : System.String
IsMandatory                     : True
Position                        : 0
ValueFromPipeline               : False
ValueFromPipelineByPropertyName : False
ValueFromRemainingArguments     : False
HelpMessage                     :
Aliases                         : {}
Attributes                      : {Com,
 System.Management.Automation.ValidateNotNullOrEmptyAttribute}

Name                            : Verbose
Type                            : System.Boolean
IsMandatory                     : False
Position                        : -2147483648
ValueFromPipeline               : False
ValueFromPipelineByPropertyName : False
ValueFromRemainingArguments     : False
HelpMessage                     :
Aliases                         : {vb}
Attributes                      :
 {System.Management.Automation.AliasAttribute, __AllParameterSets}

Name                            : Debug
Type                            : System.Boolean
IsMandatory                     : False
Position                        : -2147483648
ValueFromPipeline               : False
ValueFromPipelineByPropertyName : False
ValueFromRemainingArguments     : False
HelpMessage                     :
Aliases                         : {db}
Attributes                      :
 {__AllParameterSets, System.Management.Automation.AliasAttribute}

Name                            : ErrorAction
Type                            : System.Management.Automation.ActionPreference
IsMandatory                     : False
Position                        : -2147483648
ValueFromPipeline               : False
ValueFromPipelineByPropertyName : False
ValueFromRemainingArguments     : False
HelpMessage                     :
Aliases                         : {ea}
Attributes                      :
 {System.Management.Automation.AliasAttribute, __AllParameterSets}

Name                            : ErrorVariable
Type                            : System.String
IsMandatory                     : False
Position                        : -2147483648
ValueFromPipeline               : False
ValueFromPipelineByPropertyName : False
ValueFromRemainingArguments     : False
HelpMessage                     :
Aliases                         : {ev}
Attributes                      :
 {__AllParameterSets, System.Management.Automation.AliasAttribute}

Name                            : OutVariable
Type                            : System.String
IsMandatory                     : False
Position                        : -2147483648
ValueFromPipeline               : False
ValueFromPipelineByPropertyName : False
ValueFromRemainingArguments     : False
HelpMessage                     :
Aliases                         : {ov}
Attributes                      :
 {System.Management.Automation.AliasAttribute, __AllParameterSets}

Name                            : OutBuffer
Type                            : System.Int32
IsMandatory                     : False
Position                        : -2147483648
ValueFromPipeline               : False
ValueFromPipelineByPropertyName : False
ValueFromRemainingArguments     : False
HelpMessage                     :
Aliases                         : {ob}
Attributes                      :
 {System.Management.Automation.ValidateRangeAttribute,
 System.Management.Automation.AliasAttribute, __AllParameterSets}

パラメータに「IsMandatory」プロパティがありますが、これはそのパラメータが必須かどうかを表します。

例えば、「ComObject」パラメータは「IsMandatory」がTrueですから必須パラメータということになります。


以下はIEのCOMオブジェクトを取得するサンプルです。

$ie = new-object -Com InternetExplorer.Application

「-Com」でパラメータ群を「Com」を指定し、その後に「必須パラメータ」である「ComObject」として「InternetExplorer.Application」を渡しています。


参考記事

この辺のパラメータ周りの仕組みと実装は以下の記事が参考になります。

2005-12-24

[]「Monadの管理者ガイド」をオンラインで読む

Monadの管理者ガイドが近日発売 - PowerShell Memoで紹介した「Monadの管理者ガイド」。

注文したAmazonで「配送予定日: 2005/12/3 - 2005/12/5」となっているのですが、ステータスは未発送のままで、未だに届きません。


でも海外ではすでに発売されているようですね。

no titleでは一部がオンラインで読めるようになっています。


全てを読むには有料登録しなければいけませんが、14日の無料試用登録だけでも「1章分」はオンラインで読んだり、PDFダウンロードできます。

ただし、無料試用登録だけでもクレジットカード情報を入力する必要があり、14日以内に登録をキャンセルしないと有料モードに切り替わります。

その後は自動課金されるのでご注意を。(^^;

2005-12-23

[]パラメータ群が複数ある場合の調べ方(2)

パラメータ群が複数ある場合の調べ方(1) - PowerShell Memoの続きです。


Cmdletのパラメータを調べる

「new-object」は「Net」と「Com」という名前で区別されるパラメータ群を持っています。

ParameterSetInfo(Net)
MSH C:\> $((gcm new-object).ParameterSets)[0].Name
Net
MSH C:\> $((gcm new-object).ParameterSets)[0].Parameters


Name                            : TypeName
Type                            : System.String
IsMandatory                     : True
Position                        : 0
ValueFromPipeline               : False
ValueFromPipelineByPropertyName : False
ValueFromRemainingArguments     : False
HelpMessage                     :
Aliases                         : {}
Attributes                      : {Net}

Name                            : Arguments
Type                            : System.Object[]
IsMandatory                     : False
Position                        : 1
ValueFromPipeline               : False
ValueFromPipelineByPropertyName : False
ValueFromRemainingArguments     : False
HelpMessage                     :
Aliases                         : {}
Attributes                      : {Net}

Name                            : Verbose
Type                            : System.Boolean
IsMandatory                     : False
Position                        : -2147483648
ValueFromPipeline               : False
ValueFromPipelineByPropertyName : False
ValueFromRemainingArguments     : False
HelpMessage                     :
Aliases                         : {vb}
Attributes                      :
 {System.Management.Automation.AliasAttribute, __AllParameterSets}

Name                            : Debug
Type                            : System.Boolean
IsMandatory                     : False
Position                        : -2147483648
ValueFromPipeline               : False
ValueFromPipelineByPropertyName : False
ValueFromRemainingArguments     : False
HelpMessage                     :
Aliases                         : {db}
Attributes                      :
 {__AllParameterSets, System.Management.Automation.AliasAttribute}

Name                            : ErrorAction
Type                            : System.Management.Automation.ActionPreference
IsMandatory                     : False
Position                        : -2147483648
ValueFromPipeline               : False
ValueFromPipelineByPropertyName : False
ValueFromRemainingArguments     : False
HelpMessage                     :
Aliases                         : {ea}
Attributes                      :
 {System.Management.Automation.AliasAttribute, __AllParameterSets}

Name                            : ErrorVariable
Type                            : System.String
IsMandatory                     : False
Position                        : -2147483648
ValueFromPipeline               : False
ValueFromPipelineByPropertyName : False
ValueFromRemainingArguments     : False
HelpMessage                     :
Aliases                         : {ev}
Attributes                      :
 {__AllParameterSets, System.Management.Automation.AliasAttribute}

Name                            : OutVariable
Type                            : System.String
IsMandatory                     : False
Position                        : -2147483648
ValueFromPipeline               : False
ValueFromPipelineByPropertyName : False
ValueFromRemainingArguments     : False
HelpMessage                     :
Aliases                         : {ov}
Attributes                      :
 {System.Management.Automation.AliasAttribute, __AllParameterSets}

Name                            : OutBuffer
Type                            : System.Int32
IsMandatory                     : False
Position                        : -2147483648
ValueFromPipeline               : False
ValueFromPipelineByPropertyName : False
ValueFromRemainingArguments     : False
HelpMessage                     :
Aliases                         : {ob}
Attributes                      :
 {System.Management.Automation.ValidateRangeAttribute,
 System.Management.Automation.AliasAttribute, __AllParameterSets}

Verbose以降は全てのCmdletに存在するUbiquitous Parametersと呼ばれるパラメータです。

そのUbiquitous Parametersを除くと「ParameterSetInfo(Net)」は2つのパラメータを持ちます。

  • TypeName
    • String
  • Arguments
    • Object[]

例えば、以下は「System.Datetime」オブジェクトを生成するサンプルですが、

MSH C:\> new-object System.Datetime 2005,12,23,0,33,0

2005年12月23日 0:33:00

TypeNameは生成するオブジェクトのクラス名(System.Datetime)で、

ArgumentsはTypeNameで指定するクラスのコンストラクタに渡す引数配列(2005,12,23,0,33,0)になります。


続く・・・

2005-12-22

[]パラメータ群が複数ある場合の調べ方(1)

Cmdletのパラメータを調べる

Cmdletは「System.Management.Automation.CmdletInfo」で定義されます。

MSH C:\> (get-command new-object).getType().fullname

System.Management.Automation.CmdletInfo

Cmdletのパラメータ群は「ParameterSetInfo」で定義され、「CmdletInfo」は「ParameterSetInfo」のコレクションである「ParameterSets」を保持します。


Cmdletは複数のパラメータ群を持つことができます。例えば「new-object」がそうです。

以下のコマンドで分かるように「write-host」のパラメータ群は1つ、「new-object」のパラメータ群は2つです。

MSH C:\> (get-command write-host).ParameterSets.Count

1

MSH C:\> (get-command new-object).ParameterSets.Count

2

2つのパラメータ群はそれぞれ「Net」「Com」という名前です。

.NETオブジェクト、COMオブジェクトを生成する際のパラメータ群になります。

MSH C:\> $((gcm new-object).ParameterSets)[0].Name

Net

MSH C:\> $((gcm new-object).ParameterSets)[1].Name

Com


続く・・・

2005-12-21

[]パラメータの別名(エイリアス)を調べる

別名(エイリアス)を取得する

Cmdletのいくつかのパラメータは、別名(エイリアス)を持ちます。

例えば、「ErrorAction」の別名は「ea」ですから、

以下の2つのスクリプトは同じ意味です。

remove-item "sample.txt" -ErrorAction SilentlyContinue

remove-item "sample.txt" -ea SilentlyContinue

このような別名を調べるサンプルを作成してみました。

get-ParamAlias.msh
PARAM([String]$cmdlet)

$a = (get-command $cmdlet).ParameterSets
$b = ($a | foreach{$_.parameters} | where{[String]::IsNullOrEmpty($_.Aliases) `
-eq $false})
"<<" + $cmdlet + ">>"
$b | foreach{$_.Name + "=" + $_.Aliases}

利用方法

MSH C:\> get-ParamAlias write-host
<<write-host>>
Verbose=vb
Debug=db
ErrorAction=ea
ErrorVariable=ev
OutVariable=ov
OutBuffer=ob

2005-12-20

[]任意のオブジェクトを作成する(3)

任意のオブジェクトを作成する(2) - PowerShell Memoの続きです。

今回は「MshScriptMethod」を利用してメソッドを追加するサンプルを紹介します。

メソッドの追加(MshScriptMethod)

以下のサンプルでは「name(MshNoteProperty)」を表示する「introduce(MshScriptMethod)」メソッドを追加しています。

MSH C:\> $obj = new-object Management.Automation.MshObject
MSH C:\>
MSH C:\> # プロパティ追加
MSH C:\> $name = "newpops"
MSH C:\> $p = new-object Management.Automation.MshNoteProperty `
>> "name", $name
>> $obj.MshObject.Members.Add($p)
>>
MSH C:\> # メソッド追加
MSH C:\> $script = {write-host "My name is" $this.name}
MSH C:\> $sm = new-object System.Management.Automation.MshScriptMethod `
>> "introduce", $script
>> $obj.MshObject.Members.Add($sm)
>>
MSH C:\> # メソッド実行
MSH C:\> $obj.introduce()
My name is newpops

2005-12-19

[]Monadの次リリースは来年1月上旬

Monadの次リリース

ニュースグループでMonadの次リリースの話題がありました。

来年1月上旬を予定しているそうです。

We are sorry, the page you requested cannot be found

From : Leonard Chung [MSFT]

We're aiming for the 1st half of January for the next release of Monad with

Single Shell functionality.

2005-12-18

[]任意のオブジェクトを作成する(2)

任意のオブジェクトを作成する(1) - PowerShell Memoの続きです。

「System.Management.Automation.MshObject」に任意のプロパティやメソッドを追加することで、任意のオブジェクトを作成することができます。


MshScriptPropertyは[ScriptBlock]としてプロパティを定義します。

[ScriptBlock]に計算式を含めることで、他のプロパティの値に連動して値が変換するプロパティを作成できます。

プロパティの追加(MshScriptProperty)

以下のサンプルでは「value(MshNoteProperty)」の値を3倍した値を持つ、「NewScriptProperty(MshScriptProperty)」を追加しています。

MSH C:\> $o = new-object Management.Automation.MshObject
MSH C:\> $value = [int]10
MSH C:\> $p = new-object Management.Automation.MshNoteProperty `
"value", $value
MSH C:\> $script = {$this.value * 3}
MSH C:\> $sp = new-object Management.Automation.MshScriptProperty `
"NewScriptProperty", $script
MSH C:\> $o.MshObject.Members.Add($p)
MSH C:\> $o.MshObject.Members.Add($sp)
MSH C:\> $o

 value   NewScriptProperty
 -----   -----------------
    10                  30

MSH C:\> $o.value = 15
MSH C:\> $o


 value   NewScriptProperty
 -----   -----------------
    15                  45

2005-12-17

[]任意のオブジェクトを作成する(1)

「System.Management.Automation.MshObject」に任意のプロパティやメソッドを追加することで、任意のオブジェクトを作成することができます。

プロパティの追加(MshNoteProperty)

以下のサンプルでは「String」型と「int」型のプロパティを追加しています。

MSH C:\> $o = new-object Management.Automation.MshObject
MSH C:\> $value1 = "TEST"
MSH C:\> $value2 = [int]100
MSH C:\> $p1 = new-object Management.Automation.MshNoteProperty `
>> "NewProperty1", $value1
>> $p2 = new-object Management.Automation.MshNoteProperty `
>> "NewProperty2", $value2
>> $o.MshObject.Members.Add($p1)
>> $o.MshObject.Members.Add($p2)
>>
MSH C:\> $o

NewProperty1  NewProperty2
------------  ------------
TEST                   100

MSH C:\> $o | gm

    TypeName: System.Management.Automation.MshCustomObject

Name         MemberType   Definition
----         ----------   ----------
Equals       Method       System.Boolean Equals(Object obj)
GetHashCode  Method       System.Int32 GetHashCode()
GetType      Method       System.Type GetType()
ToString     Method       System.String ToString()
NewProperty1 NoteProperty System.String NewProperty1=TEST
NewProperty2 NoteProperty System.Int32 NewProperty2=100

2005-12-16

newpops2005-12-16

[]MSH Minesweeper GUI game

MSH Minesweeper GUI game

敬服しました。

MSH Minesweeper GUI game












素晴らしい。(^^;

2005-12-15

[]Obfuscated Monad Script

難読化

Monadでソースコードを難読化するという記事です。

Proudly Serving My Corporate Masters: Obfuscated Monad Script

ここで紹介されているサンプル自体は確かに難読化されていますが、

難読化ソースを出力するツールは紹介されていません。

・・・というか、作者はツールではなく手で難読化スクリプトを書いたらしい。


サンプルは何をやっているかというと、

難読化された文字列「$s」を1文字ずつ読み込んで、「文字列対応表」を作成しながら文字列を複合化しています。


サンプルを実行した後、

$store.getEnumerator() | sort key

と入力すると、「文字列対応表(keyでソート)」が見えるので理解しやすいでしょう。


文字列対応表
MSH C:\> $store.getEnumerator() | sort key

Key  Value
---  -----
A    a
B    h
C    t
D    s
E    m
F    i
G    d
H    o
I    n
J    l
K    k
L    e
M    y
N    u
O    g
P    r
Q    w
R    that
S    sam-i-am
T    that sam-i-am!
U    i do not
V    like
W    do you
X    green eggs and ham
Y    them
Z    i do not like green eggs and ham
[    would you
\    like them
]    here or there
^    i would not
_    like them here or there
`    i would not like them
a    anywhere
b    i do not like them
c    would you like them
d    in a house
e    with a mouse
f    i do not like them in a house
g    i do not like them with a mouse
h    i do not like them here or there
i    i do not like them anywhere
j    i do not like them, sam-i-am

2005-12-14

[]Scripting with the Microsoft Shell

MSHのScript Centerがオープン

MicrosoftのWebにMSHのScript Centerが設置されました。

これから、MSHの関連情報を集約していく感じですね。


VBScriptのサンプルMSH移植版サンプルも置いてあります。

感想

現時点では、WMIを利用したサンプル/記事ばかりです。

WMIを利用したVBScriptをよく利用しているサーバ管理者に、MSHへの移植を促すのが目的でしょうか。


個人的には単なるVBScriptからの移植はそこそこにして、MSHに移行するメリットを記事として取り上げて欲しいですね。

Cmdletやパイプによってコードが非常にコンパクトになりますし、VBScriptよりもエラーハンドリングしやすくなるでしょうし、そこをアピールしてMSHを励行すべきかなと。

2005-12-13

[]連想配列のソート

ニュースグループで「連想配列のソート方法」を見つけたので紹介します。

連想配列のソート

まず、3つの要素を含む連想配列を作成します。

MSH C:\> $hash = @{one = 1;two = 2; three=3}

中身を確認してみます。

MSH C:\> $hash

Key                            Value
---                            -----
two                            2
three                          3
one                            1


では、Key、Valueでソートしてみましょう。

Keyでソート
MSH C:\> $hash.getEnumerator() | sort key

Key                            Value
---                            -----
one                            1
three                          3
two                            2
Valueでソート
MSH C:\> $hash.getEnumerator() | sort value

Key                            Value
---                            -----
one                            1
two                            2
three                          3

2005-12-12

[]クラス名を検索する

読み込まれているアセンブリからクラス名を検索し、フルネームを取得するスクリプトを紹介します。

クラス名を検索するスクリプト

find-class.msh
param([String]$target)

if ($target -eq ""){return}
[AppDomain]::CurrentDomain.GetAssemblies() | foreach{$_.gettypes()} | `
where{$_.fullname -match $target} | write-host

利用方法

「DivideByZeroException」の検索
MSH C:\> find-class DivideByZeroException
System.DivideByZeroException
「DriveNotFoundException」の検索
MSH C:\> find-class DriveNotFoundException
System.IO.DriveNotFoundException
System.Management.Automation.DriveNotFoundException

2005-12-11

[]MSHのデバッグ手法(6)

「Trap」構文を利用して例外処理を実装する場合、通常、Trap対象とする例外クラスの指定が必要です。*1

そのため、スクリプトでエラーが発生した時に、例外クラスの名前がすぐに分かると便利です。

発生した例外クラス名を調べる

get-exception.msh
param([int]$index=0)

if($error.count -ne 0)
{
    # インデックスが範囲外の場合は処理しない
    if($index -gt $error.count - 1) {return}
    
    $thisError = $error[$index]
    if ($thisError -is [System.Management.Automation.RuntimeException])
    {
        $thisError.InnerException.GetType().FullName
    }
    elseif ($thisError -is [System.Management.Automation.ErrorRecord])
    {
        $thisError.CategoryInfo
    }
}

利用方法

get-exception [index]

  • 例外クラスの情報を取得します。
  • [index]は$errorのindexです。
    • 「0」→最後に発生した例外クラスの情報を取得
    • 「1」→最後から2番目に発生した例外クラスの情報を取得
    • [index]を省略するとデフォルト値の「0」が使われます。
RuntimeExceptionの例
MSH C:\> 1/0
Attempted to divide by zero.
At line:1 char:3
+ 1/0 <<<<
MSH C:\> get-exception
System.DivideByZeroException
ErrorRecordの例
MSH C:\> set-location z:
set-location : Cannot find drive. A drive with name 'z' does not exist.
At line:1 char:13
+ set-location  <<<< z:
MSH C:\> get-exception


Category   : ObjectNotFound
Activity   : set-location
Reason     : DriveNotFoundException
TargetName : z
TargetType : String

*1:例外クラスを指定しない記述も可能です。その場合、全ての例外を捕捉してしまうため、細かな制御はできません。

2005-12-10

[]基本構文(15)

「Trap」による例外処理

例外処理を行うには「Trap」構文を利用します。Javaで言うと「Catch」です。

例外処理についてJavaと比べると、
  • Java」は例外監視範囲を「try」で指定しますが、
  • 「Monad」の場合はスクリプト全体が例外監視範囲になるようです。

「DivideByZeroException」をキャッチする(エラー表示+処理継続)

以下のスクリプトでは「$i」が0の時にゼロ除算で「DivideByZeroException」が発生します。

そこでTrapで「DivideByZeroException」をキャッチしてエラーメッセージを表示しています。

$i = 3
while ($i -ge -3)
{
    trap [DivideByZeroException]
    {
        "divide by zero trapped"
    }
    1 / $i--
}

実行結果
MSH C:\> $i = 3
MSH C:\> while ($i -ge -3)
>> {
>>     trap [DivideByZeroException]
>>     {
>>         "divide by zero trapped"
>>     }
>>     1 / $i--
>> }
>>
0.333333333333333
0.5
1
divide by zero trapped
Attempted to divide by zero.
At line:7 char:8
+     1 /  <<<< $i--
-1
-0.5
-0.333333333333333
  • Trapでキャッチしてメッセージを表示した後は、通常のエラー(行番号など)を表示し、処理を継続します。

「DivideByZeroException」をキャッチする(エラー表示+処理中止)

「trap」のスクリプトブロックで「break」を利用すると・・・

$i = 3
while ($i -ge -3)
{
    trap [DivideByZeroException]
    {
        "divide by zero trapped"
        break
    }
    1 / $i--
}
実行結果
MSH C:\> $i = 3
MSH C:\> while ($i -ge -3)
>> {
>>     trap [DivideByZeroException]
>>     {
>>         "divide by zero trapped"
>>         break
>>     }
>>     1 / $i--
>> }
>>
0.333333333333333
0.5
1
divide by zero trapped
Attempted to divide by zero.
At line:8 char:8
+     1 /  <<<< $i--
  • 通常のエラー(行番号など)を表示した後に処理を中止します。

「DivideByZeroException」をキャッチする(エラー非表示+処理継続)

「trap」のスクリプトブロックで「continue」を利用すると・・・

$i = 3
while ($i -ge -3)
{
    trap [DivideByZeroException]
    {
        "divide by zero trapped"
        continue
    }
    1 / $i--
}
実行結果
MSH C:\> $i = 3
MSH C:\> while ($i -ge -3)
>> {
>>     trap [DivideByZeroException]
>>     {
>>         "divide by zero trapped"
>>         continue
>>     }
>>     1 / $i--
>> }
>>
0.333333333333333
0.5
1
divide by zero trapped
-1
-0.5
-0.333333333333333
  • 通常のエラー(行番号など)を表示せずに処理を継続します。

参考:MSH Language and Syntax

2005-12-09

[]PropertyGridの活用

NewsGroupで「PropertyGrid」を使ったサンプルを見つけました。

PropertyGridでオブジェクト解析をしよう!

ObjectViewer.msh
function ObjectViewer
{ 
    # 初期処理
    [void][System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") 

    # フォーム設定
    $form = new-object "System.Windows.Forms.Form" 
    $form.Size = new-object System.Drawing.Size @(600,600) 
    $PG = new-object "System.Windows.Forms.PropertyGrid" 
    $PG.Dock = [System.Windows.Forms.DockStyle]::Fill 

    # 引数の処理
    $form.text = "$args" 
    $PG.selectedobject = $args[0].mshObject.baseobject 

    # パーツ配置/フォーム表示
    $form.Controls.Add($PG) 
    $form.topmost = $true 
    $form.showdialog() 
} 
set-alias ov ObjectViewer

ObjectViewerの利用方法

Explorerの情報を見る

ov (ps)[5]

  • Explorerがプロセス名で6番目の場合
スクリーンショット

2005-12-08

[]記事が100件を超えました

2005年8月末から本日記を書き始めましたが、昨日でようやく記事が100件を超えました。

過去の日記を見返してみる・・・

見返すと、やはり色々と改善点がありますね。

  • うまくカテゴリ分けできていない
    • MSHカテゴリを細分化しなければ・・・。
  • Cmdlet紹介記事の書き方が統一されていない
  • 調査中で止まったものがいくつか(^^;
  • サンプルを探しづらい(管理者の私ですら)
    • サンプルをまとめる必要あり。

やりたい事、作りたいサンプルは多数ありますが、時間が取れずにスタックしています。

まずは「out-ie」のExcel版である「out-chart」を作成したい・・・。

2005-12-07

[]MSHのデバッグ手法(5)


MSHのデバッグ手法(4) - PowerShell Memoの続きです。

trace-expression

単一のコマンドラインに対してトレースソースを有効にするには以下の構文を利用します。

To a file

trace-expression –name <categoryname> -Options All –Expression { <command line> } –file <filename>

To the Monad host

trace-expression –name <categoryname> -Options All –Expression { <command line> } –MshHost

To the debugger

trace-expression –name <categoryname> -Options All –Expression { <command line> } -debugger

<categoryname>にはトレースソースを設定します。

トレースソースは「get-tracesource」コマンドで取得可能です。

MSH C:\> get-tracesource | sort name

Options  Name             Listeners  Description
-------  ----             ---------  -----------
None     AliasCommands    {Default}  The *-alias commands
None     AliasInfo        {Default}  The command information for aliases. Aliases
None     AliasProvider    {Default}  The CmdletProvider for shell aliases
None     AssemblyConfigur {Default}  AssemblyConfigurationEntry
None     ASSERT           {Default}  Msh Assertions
None     AuthorizationMan {Default}  tracer for AuthorizationManager
None     AutomationEngine {Default}  AutomationEngine
None     CertificateProvi {Default}  The core command provider for certificates
None     Cmdlet           {Default}  Cmdlet
None     CmdletConfigurat {Default}  CmdletConfigurationEntry
None     CmdletInfo       {Default}  The command information for MSH cmdlets that
(中略)

2005-12-06

[]MSHのデバッグ手法(4)

Windows ”Monad” Shell Beta 2 Documentation Packに含まれる「TracingQuickStart.doc」には、

デバッグ系の情報がまとまっています。

trace-expression

trace-expressionは引数として渡したスクリプトについて、

特定のトレースソースを有効にします。

例えば、以下のスクリプトにおいて、

$a = [int][string][double]"234.567"

型変換のトレースソースを有効にしてみます。

MSH C:\> trace-expression TypeConversion { $a = [int][string][double]"234.567"
>>  } -mshhost
>>
DEBUG: TypeConversion Information: 0 : Converting "double" to "System.Type".
DEBUG: TypeConversion Information: 0 :     Standard type conversion.
DEBUG: TypeConversion Information: 0 :         Type conversion from string.
DEBUG: TypeConversion Information: 0 :             Conversion to System.Type
DEBUG: TypeConversion Information: 0 :     The conversion is a standard conversion.
 No custom type conversion will be attempted.
DEBUG: TypeConversion Information: 0 : Converting "234.567" to "System.Double".
DEBUG: TypeConversion Information: 0 :     Standard type conversion.
DEBUG: TypeConversion Information: 0 :         Type conversion from string.
DEBUG: TypeConversion Information: 0 :             Converting to double or single.
DEBUG: TypeConversion Information: 0 :     The conversion is a standard conversion.
 No custom type conversion will be attempted.
DEBUG: TypeConversion Information: 0 : Converting "string" to "System.Type".
DEBUG: TypeConversion Information: 0 :     Standard type conversion.
DEBUG: TypeConversion Information: 0 :         Type conversion from string.
DEBUG: TypeConversion Information: 0 :             Conversion to System.Type
DEBUG: TypeConversion Information: 0 :     The conversion is a standard conversion.
 No custom type conversion will be attempted.
DEBUG: TypeConversion Information: 0 : Converting "234.567" to "System.String".
DEBUG: TypeConversion Information: 0 :     Standard type conversion.
DEBUG: TypeConversion Information: 0 :         Converting numeric to string.
DEBUG: TypeConversion Information: 0 :     The conversion is a standard conversion.
 No custom type conversion will be attempted.
DEBUG: TypeConversion Information: 0 : Converting "int" to "System.Type".
DEBUG: TypeConversion Information: 0 :     Standard type conversion.
DEBUG: TypeConversion Information: 0 :         Type conversion from string.
DEBUG: TypeConversion Information: 0 :             Conversion to System.Type
DEBUG: TypeConversion Information: 0 :     The conversion is a standard conversion.
 No custom type conversion will be attempted.
DEBUG: TypeConversion Information: 0 : Converting "234.567" to "System.Int32".
DEBUG: TypeConversion Information: 0 :     Standard type conversion.
DEBUG: TypeConversion Information: 0 :         Type conversion from string.
DEBUG: TypeConversion Information: 0 :             Converting to integer.
DEBUG: TypeConversion Information: 0 :             Exception converting to 
 integer: "Input string was not in a correct format.".
DEBUG: TypeConversion Information: 0 :             Converting to integer
 passing through double.
DEBUG: TypeConversion Information: 0 :             Numeric Conversion
 through Syustem.Double.
DEBUG: TypeConversion Information: 0 :     The conversion is a standard 
 conversion. No custom type conversion will be attempted.

このようにMSH内部の型変換の様子が分かります。

2005-12-05

[]MSHのデバッグ手法(3)

MSHのデバッグ手法(2) - PowerShell Memoの続きです。

エラー内容を分析する(2)

「System.Management.Automation.ErrorRecord」オブジェクト

もエラー内容を把握するのに役に立ちます。

「InvocationInfo」
MSH C:\> $thisError.InvocationInfo.gettype().fullname
System.Management.Automation.InvocationInfo
MSH C:\> $thisError.InvocationInfo

MyCommand        : System.Management.Automation.CmdletInfo
ScriptLineNumber : 1
OffsetInLine     : -2147483648
ScriptName       :
Line             : start-service $servicename
PositionMessage  :
                   At line:1 char:14
                   + start-service  <<<< $servicename
InvocationName   : start-service
PipelineLength   : 0
PipelinePosition : 0
「FullyQualifiedErrorId」
MSH C:\> $thisError.FullyQualifiedErrorId
ParameterArgumentValidationErrorNullNotAllowed,
 System.Management.Automation.Commands.StartServiceCommand

2005-12-04

[]MSHのデバッグ手法(2)

エラー内容を分析する

エラー発生時のオブジェクトを格納する「$error」。

「$error」を調べることでエラー内容を分析することができます。


試しに、意図的に「start-service」でエラーを発生させてみます。

MSH C:\> start-service $servicename
start-service : Cannot bind argument to parameter 'ServiceName' because it is null.
At line:1 char:14
+ start-service  <<<< $servicename

$errorにはエラー内容が配列として格納されています。

MSH C:\> $error.gettype().fullname
System.Collections.ArrayList
MSH C:\> $error.count
1

今回発生させたエラーについて調べてみましょう。

MSH C:\> $thisError = $error[0]
MSH C:\> $thisError
start-service : Cannot bind argument to parameter 'ServiceName' because it is null.
At line:1 char:14
+ start-service  <<<< $servicename

$errorの要素は「ErrorRecord」オブジェクトです。

MSH C:\> $thisError.gettype().fullname
System.Management.Automation.ErrorRecord

エラーの詳細は「CategoryInfo」を見ると分かります。

MSH C:\> $thisError.CategoryInfo


Category   : InvalidData
Activity   : start-service
Reason     : ParameterBindingValidationException
TargetName :
TargetType :

Categoryは以下の種類があります。

CategoryDescription
CloseErrorFor errors that result when closing.
DeadlockDetectedFor errors that result when a deadlock is detected.
DeviceErrorFor errors that result when a device reported an error.
FromStdErrFor errors that result when a non-MSH command reported an error to its STDERR pipe. The engine uses this category when it executes a native console application and captures the errors reported by the native application. Avoid using FromStdErr in other circumstances.
InvalidArgumentFor errors that result when an invalid argument is specified.
InvalidDataFor errors that result when invalid data is specified.
InvalidOperationFor errors that result when an invalid operation is requested.
InvalidResultFor errors that result when an invalid result is returned.
InvalidTypeFor errors that result when an invalid Type is specified.
MetadataErrorFor errors that result when the metadata contains an error.
NotImplementedFor errors that result when a referenced API is not implemented.
NotInstalledFor errors that result when an item is not installed.
NotSpecifiedFor errors detected by MSH that result because an exception did not specify an error category or the specified error category is invalid.
ObjectNotFoundFor errors that result when an object cannot be found (such as file, directory, computer, and system resource objects).
OpenErrorFor errors that result when opening.
OperationStoppedFor errors that result when an operation has stopped.
OperationTimeoutFor errors that result when an operation has exceeded its timeout limit.
ParserErrorFor errors that result when a parser encounters an error.
PermissionDeniedFor errors that result when an operation is not permitted.
ReadErrorFor errors that result when reading.
ResourceBusyFor errors that result when a resource is busy.
ResourceExistsFor errors that result when a resource already exists.
ResourceUnavailableFor errors that result when a resource is unavailable.
SecurityError
SyntaxErrorFor errors that result when MSH detects an error in the MSH language syntax.
WriteErrorFor errors that result when attempting to write to the pipeline.

参照:ErrorCategory Enumeration

2005-12-03

[]S2JavelinとArrowVision近日リリース

S2JavelinとArrowVision。

Seasar2を利用して開発したアプリケーションデバッグを効率化するツールです。


S2RMI開発者であり先輩の村田さんのブログでも紹介されています。



S2JavelinとArrowVisionを利用すると、ソースコードに全く手を入れずにS2の動作をグラフィカルなシーケンスで表示できます。

が一目で把握できます。また、スレッド別のシーケンスを表示/非表示も設定可能です。


デッドロックなどは即座に問題箇所の特定ができますね。

便利〜♪(^^)

2005-12-02

[]コンソール出力内容をファイルに出力する(start-transcript/stop-transcript)

「start-transcript」はコンソール出力内容をファイルに出力するCmdletです。

コンソールの内容はリアルタイムにファイルに出力されます。


コンソール>ファイル出力の開始:「start-transcript」

このCmdletは使い甲斐がありそうです。

例えば「start-transcript」を利用して、サービスの死活監視系のシェルを「start-transcript」でファイル出力し、ログを定期的に巡回するシェルで障害の検知/報告を行うなどは便利でしょう。

「start-transcript」は通常通りコンソールにも標準出力するため、コンソールの目視でも監視状態を確認できますしね。


コンソール>ファイル出力の中止:「stop-transcript」

ファイル出力は「stop-transcript」を実行するまで続行されます。


実行方法

引数に何も指定しない場合は日付と時刻を含むファイル名で出力されます。

出力フォルダは<マイドキュメント>です。

引数に何も指定しない場合
MSH C:\> start-transcript
Transcript started, output file is D:\Doc\msh_transcript.20051202000404.txt
  • 「msh_transcript.20051202000404.txt」に出力されます。
引数にファイル名を指定した場合(ファイル上書き)
MSH C:\> start-transcript console.txt
Transcript started, output file is console.txt
MSH C:\> write-host newpops
newpops
MSH C:\> stop-transcript
Transcript stopped, output file is C:\console.txt
  • 既存の「C:\console.txt」は上書きされます。

「C:\console.txt」は以下のような内容です。

**********************
MSH Transcript Start
Start time: 20051202000729
Username  : XXXXXXXXXXXXXXXXXX 
Machine	  : XXXXXXXXXXXXXXXXXX
**********************
Transcript started, output file is console.txt
MSH C:\> write-host newpops
newpops
MSH C:\> stop-transcript
**********************
MSH Transcript End
End time: 20051202000749
**********************

引数にファイル名を指定した場合(ファイル追加)

「-append」オプションを指定するとファイルに追加書き込みを行います。

MSH C:\> start-transcript console.txt -append
Transcript started, output file is console.txt
MSH C:\> write-host MSH Memo
MSH Memo
MSH C:\> stop-transcript
Transcript stopped, output file is C:\console.txt

「C:\console.txt」は以下のような内容です。

**********************
MSH Transcript Start
Start time: 20051202000729
Username  : XXXXXXXXXXXXXXXXXX
Machine	  : XXXXXXXXXXXXXXXXXX
**********************
Transcript started, output file is console.txt
MSH C:\> write-host newpops
newpops
MSH C:\> stop-transcript
**********************
MSH Transcript End
End time: 20051202000749
**********************
**********************
MSH Transcript Start
Start time: 20051202001049
Username  : XXXXXXXXXXXXXXXXXX
Machine	  : XXXXXXXXXXXXXXXXXX
**********************
Transcript started, output file is console.txt
MSH C:\> write-host MSH Memo
MSH Memo
MSH C:\> stop-transcript
**********************
MSH Transcript End
End time: 20051202001103
**********************

2005-12-01

[]jaMSH status update

リリースは近い?

"jaMSH" : Interactive Shell for Monad/MSH - PowerShell Memoで紹介したjaMSHの次バージョンの開発が進んでいるようです。

参照:jaMSH status update


現バージョンで必須コンポーネントであった「The GnuWin32 Readline port」は不要となり、jaMSH内部に「libedit port」が組み込まれるそうです。

また「jamsh.exe.config」というファイル(XML)に各種設定を記述するようになります。