PowerShell Memo

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

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

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


2006-01-31

[]最近はMonadよりW-ZERO3で遊んでいます

高価なおもちゃ

率直な感想として、初期状態では使い勝手が悪いですね。

×ボタンを押してもWindowが隠れるだけでプロセスは終了しない。

プロセスを落とすには、タスクマネージャに相当するツールからのみ。

この点はWindows使いとして違和感ありありですね〜。

プロセスの起動時間でユーザをイライラさせないために、という仕様なのでしょうか。


で、×ボタンでプロセスを落とせるカスタマイズツールを探していたのですが、

やはりありました。「GSPocketMagic++」。

スタートメニューも使いやすくなりますし、お勧めです。


.NET Compact Framework 2.0

W-ZERO3は.NET Compact Framework 2.0が動きます。

詳しく調べていませんが、VS2005+開発キットで、ZERO3用のツールを開発できるようです。

興味あり。(^^)

2006-01-26

[]「Monad Hacks」のスクリプト募集

「Monad Hacks」

O'Reillyから「Monad Hacks」を刊行する予定があるようです。

Page not found | Precision Computing


上記Blogで、Lee Holmes氏が掲載するサンプルを募集しています。

サンプル掲載される場合は、名前が載るとのことです。

ぜひ、Monad使いの方はサンプルを送りましょう。

#私も送ります。選ばれるかは分かりませんが。(^^;

2006-01-24

[]Monad Beta3の謎

なぜかBeta3で動作しない

文字列をIEに出力する(out-ie) - PowerShell Memoで紹介した「out-ie」は、文字列をIEに出力するScriptです。このScriptは、Beta2では問題なく動作していたのですが、Beta3ではエラーが出て正しく動作しません。


なぜ?

out-ie
param()

#パイプでオブジェクトが渡されたかチェック
$test = $input.clone()
if($test.MoveNext() -eq $False){return}

#パイプで渡されたのが「文字列」かどうかチェック
$html = @($input)
if(($html[0] -is [System.String]) -eq $False){}

$ie = new-object -com internetexplorer.application
$ie.visible = $true
[void]$ie.navigate2("about:blank")

while($ie.ReadyState -ne 4){}

for($i=0; $i -lt $html.length; $i++)
{
    [void]$ie.document.writeln([String]$html[$i])
}
[void]$ie.refresh()
return $ie
Sample(Beta3)

MSH C:\> get-date | convert-HTML | out-ie

Exception calling "writeln" with "1" argument(s): "種類が一致しません。

"

At D:\Doc\MSH\custom_cmdlet\out-ie.msh:19 char:31

  1. [void]$ie.document.writeln( <<<< [String]$html[$i])

あれ、「writeln」メソッドでエラーが出ているようです。

「writeln」メソッドの仕様or解釈の仕方が変更されたのでしょうか?

比較のため、Beta2、Beta3それぞれで、「writeln」メソッドの定義を調べてみましょう。


Writeln test on Beta2
MSH C:\> $ie = new-object -com internetexplorer.application
MSH C:\> $ie.visible = $true
MSH C:\> [void]$ie.navigate2("about:blank")
MSH C:\>  $ie.document.writeln


MemberType          : Method
OverloadDefinitions : {void writeln (SAFEARRAY(Variant))}
TypeOfValue         : System.Management.Automation.MshMethod
Value               : void writeln (SAFEARRAY(Variant))
Name                : writeln
IsInstance          : True

Writeln test on Beta3
MSH C:\> $ie = new-object -com internetexplorer.application
MSH C:\> $ie.visible = $true
MSH C:\> [void]$ie.navigate2("about:blank")
MSH C:\> $ie.document.writeln


MemberType          : Method
OverloadDefinitions : {System.Void writeln(Params Object[] psarray)}
TypeOfValue         : System.Management.Automation.MshMethod
Value               : System.Void writeln(Params Object[] psarray)
Name                : writeln
IsInstance          : True

なんと、引数の定義が変わっていますね。

  • Beta2
    • {void writeln (SAFEARRAY(Variant))}
  • Beta3
    • {System.Void writeln(Params Object[] psarray)}

むむむ・・・?

2006-01-22

[]「Shell.Application」の活用(2)

フォルダ選択ダイアログを利用する
(Use the Dialog of browsing folder)

$app = new-object -com Shell.Application
$app.BrowseForFolder(0,"Select Folder", 1, 0)
  • BrowseForFolderメソッドは「フォルダ選択ダイアログ」を表示します
  • 参照:Microsoft API and Reference Catalog
  • 引数
    • 1:Hwnd:親Windowのハンドル。0で構いません。
    • 2:sTitle:タイトル文字列
    • 3:iOptions:ダイアログのタイプ
    • 4:vRootFolder:ルートフォルダを指定します。
結果

2006-01-18

[]「Shell.Application」の活用(1)

「Shell.Application」はWindowsシェル機能を利用できるCOMオブジェクトです。


URLに任意文字列を含むIEを終了させる
(Quit the IE with URL that contains specified string)

URLに「google」を含むIEを終了する
function quitIE()
{
    PARAM([String]$urlKeyword)
    $app = new-object -com Shell.Application
    $app.Windows() | where{$_.Document.URL -match $urlKeyword} | foreach{$_.quit()}
}
quitIE "google"

2006-01-16

[]プロパティの値を素早く調べる(Quick search of property value)

全てのプロパティに対して名前と値を同時に確認する

オブジェクトが持つプロパティの名前は「get-member」で簡単に調べられますが、各プロパティの値はすぐには調べられません。

PropertyGridの活用 - PowerShell Memoで紹介した「ObjectViewer」は、プロパティの名前と値が同時に確認できて非常に便利です。


今回紹介するのは、コンソールでプロパティの名前と値を同時に確認するスクリプトです。

引数として渡したオブジェクトが持つ全てのプロパティに対して、「名前」と「値」の両方を表示します。

get-PropertyValue.msh
PARAM([Object]$obj)

if($obj -ne $null)
{
    $obj | gm -MemberType Properties | `
        foreach {">>" + $_.Name + " : " + $obj.($_.Name)}
}

Exsample
MSH C:\> (ps)[15]

Handles  NPM(K)    PM(K)      WS(K) VS(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    490      31     7964       9080   108    10.70   1572 explorer

(ps)[15]は「Explorer」のプロセスです。

Explorer」のプロセスのプロパティを調べてみましょう。

MSH C:\> get-PropertyValue (ps)[15]
>>Handles : 490
>>Name : explorer
>>NPM : 31912
>>PM : 8155136
>>VS : 113668096
>>WS : 9297920
>>__NounName : Process
>>BasePriority : 8
>>Container :
>>EnableRaisingEvents : False
>>ExitCode :
>>ExitTime :
>>Handle : 2864
>>HandleCount : 490
>>HasExited : False
>>Id : 1572
>>MachineName : .
>>MainModule : System.Diagnostics.ProcessModule (Explorer.EXE)
>>MainWindowHandle : 131132
>>MainWindowTitle :
>>MaxWorkingSet : 1413120
>>MinWorkingSet : 204800
(省略)

プロパティの値が一望できて便利です。

2006-01-14

[]イベントログを取得する(Get EventLog)(1)

サーバの運用管理でイベントログを参照することがあります。

例えば、サービスの開始/終了やログオン時刻の取得などです。

Monadでは簡単にイベントログを取得できるCmdletが用意されているため、

VBScriptに比べてイベントログ周りの処理は非常に簡単です。

イベントログの取得(get-eventlog)

イベントログの種類

イベントログにはアプリケーションセキュリティなどの種類があります。

その種類を取得するには「get-eventlog」に「-list」オプションを指定します。

MSH C:\> get-eventlog -list

  Max(K) Retain OverflowAction        Entries Name
  ------ ------ --------------        ------- ----
     512      7 OverwriteOlder            181 アプリケーション
  15,360      0 OverwriteAsNeeded         928 MonadLog
     512      7 OverwriteOlder              0 セキュリティ
     512      7 OverwriteOlder            248 システム

一覧表示されるのは「System.Diagnostics.EventLog」オブジェクトです。

MSH C:\> $(get-eventlog -list)[0].getType().fullname
System.Diagnostics.EventLog

「get-eventlog」はEventLogオブジェクトのLogプロパティを指定してイベントログにアクセスします。

「-AsString」オプションを指定すると簡易にLogプロパティを取得可能です。

MSH C:\> get-eventlog -list -AsString
Application
MonadLog
Security
System

イベントログの取得

「get-eventlog」でイベントログにアクセスするには以下の構文を利用します。

get-eventlog [-LogName] System.String [-Newest System.Int32]

では、MonadLogのイベントログを取得してみましょう。

MSH C:\> get-eventlog MonadLog

Index Time        Type Source EventID Message
----- ----        ---- ------ ------- -------
  928 1 14 10:01  Info msh        400 Engine state is changed from None ...
  927 1 14 10:01  Info msh        600 Provider "Certificate" is Started.
  926 1 14 10:01  Info msh        600 Provider "Variable" is Started.
  925 1 14 10:01  Info msh        600 Provider "Registry" is Started.
  924 1 14 10:01  Info msh        600 Provider "Function" is Started.
(省略)

これでは、延々ログエントリを表示し続けてしまいます。

このような際は、最新の指定件数のみ表示する「-Newest」オプションが便利です。

MSH C:\> get-eventlog MonadLog -Newest 3

Index Time          Type Source                EventID Message
----- ----          ---- ------                ------- -------
  928 1 14 10:01  Info msh        400 Engine state is changed from None ...
  927 1 14 10:01  Info msh        600 Provider "Certificate" is Started.
  926 1 14 10:01  Info msh        600 Provider "Variable" is Started.

2006-01-12

[]Monad Beta3 Release

Monad Beta3がリリースされました。

Beta3のインストール

Beta3をインストールするには古いバージョンのMonadをアンインストールする必要があります。

今回は、Beta2をアンインストールし、Beta3はインストールしました。


インストール時、デフォルトインストールパスは以下になっていました。

C:\Program Files\Microsoft Command Shell\v1.0


Beta2までは

C:\Program Files\Microsoft Command Shell\

でしたから、フォルダ構成を変更したようですね。

実行ポリシー

.NET2.0(RTM)用の「Monad Beta2」以降は、Monadにはレジストリに書かれた実行ポリシーの元でスクリプトが実行されます。インストールフォルダと同様、実行ポリシーが書かれたレジストリの場所も変更になっていました。

Beta2の場合のレジストリの場所

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSH

\Microsoft.Management.Automation.msh\ExecutionPolicy

Beta3の場合のレジストリの場所

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSH\1\ShellIds\Microsoft.Management.Automation.msh\ExecutionPolicy

実行ポリシーについては、Random thoughts on my interestが詳しくまとまっているので参照下さい。


実行ポリシーの変更

Monad Beta3をインストールすると、Beta2インストール時と同様、実行ポリシーはデフォルトで「Restricted」になっています。

「Restricted」では制限が厳しすぎるいので「RemoteSigned」に変更します。


以下をMonadで実行。

set-property `
HKLM:\SOFTWARE\Microsoft\MSH\1\ShellIds\Microsoft.Management.Automation.msh `
-property ExecutionPolicy -value RemoteSigned

これで利用準備が整いました。

2006-01-10

[][]Use of IronPython in Monad, Part 2

We can call IronPython in Monad.

See MSH Memo - Use of IronPython in Monad

Additionally, we can use the function of IronPython script in Monad.

Use the function of IronPython script in Monad

1.

Load IronPython.dll.

Create ScriptEngine Object of IronPython by new-object Cmdlet.

ex)

[void] [Reflection.Assembly]::LoadFrom("C:\IronPython\IronPython.dll")

$pe = new-object ironpython.hosting.pythonengine

2.

Call Execute method, Arg is the string that contains functions.

The following example is that $code contains "printStr" function.

ex)

$code=@"

def printStr(str):

print str

"@

$pe.Execute($code)

3.

Get the reference of function by GetVariable method.

ex)

$pPrintStr = $pe.GetVariable("printStr")

4.

Exectute function by Call method.

ex)

$pPrintStr.Call("Hello Monad!")

Sample Script
[void] [Reflection.Assembly]::LoadFrom("C:\IronPython\IronPython.dll")
$pe = new-object ironpython.hosting.pythonengine

$code=@"
def add(x, y):
    return x + y
"@

$pe.Execute($code)

$pAdd = $pe.GetVariable("add")

$pAdd.Call(5,20)
Sample Result
MSH C:\> [void] [Reflection.Assembly]::LoadFrom("C:\IronPython\IronPython.dll")
MSH C:\>
MSH C:\> $pe = new-object ironpython.hosting.pythonengine
MSH C:\>
MSH C:\> $code=@"
>> def add(x, y):
>>     return x + y
>> "@
>>
MSH C:\> $pe.Execute($code)
MSH C:\>
MSH C:\> $pAdd = $pe.GetVariable("add")
MSH C:\>
MSH C:\> $pAdd.Call(5,20)
25

2006-01-08

[][]Use of IronPython in Monad

STEP1 Install of IronPython 1.0 Beta1

Last month IronPython 1.0 Beta was released.

http://www.gotdotnet.com/workspaces/workspace.aspx?id=ad7acff7-ab1e-4bcb-99c0-57ac5a3a9742


The install of IronPython is very easy.

1. Download IronPython 1.0 Beta1 from Here

2. Files created by decompression of [IronPython-1.0-Beta1.zip] put your favorite folder.

STEP2 Call IronPython in Monad

1.

Load IronPython.dll.

ex)

[void][Reflection.Assembly]::LoadFrom("C:\IronPython\IronPython.dll")

2.

Create ScriptEngine Object of IronPython by new-object Cmdlet.

ex)

$pe = new-object ironpython.hosting.pythonengine

3.

Call Execute method.

ex)

$code="print 'Hello IronPython'"

$pe.Execute($code)

IronPython Sample

GUI Sample
[void] [Reflection.Assembly]::LoadFrom("C:\IronPython\IronPython.dll")
$pe = new-object ironpython.hosting.pythonengine

$code=@"
import clr
clr.AddReference("System.Windows.Forms")
from System.Windows.Forms import *
f = Form(Text="IronPython Sample")
f.ShowDialog()
"@

$pe.Execute($code)
Sample Result

2006-01-07

[]Mr. /\/\o\/\/ got a MVP award !

Monad Beta3も楽しみですが、それよりも素晴らしいニュースが・・・。

/¥/¥o¥/¥/ PowerShelled: Monad Beta 3 is Coming soon and I got a MVP award


Link from the Blog of /¥/¥o¥/¥/ - PowerShell Memoで紹介した

/\/\o\/\/氏がMVP Windows Server - Admin Frameworksを受賞したそうです。


Congratulations !


microsoft.public.windows.server.scriptingでの活発な投稿や、本人のBlogで紹介している多数の有用サンプルが決め手でしょうか?

2006-01-06

[]ランダムなパスワードの生成(1)

CodezineCodeZine(コードジン)という記事が紹介されています。

Monadに移植してみました。


GUIDを使った手っ取り早いランダムなパスワードの生成
function GetRandomPasswordUsingGUID
{
    PARAM([int]$length)
    
    #Get the GUID
    $guid = [System.Guid]::NewGuid().ToString()
    
    #Remove the hyphens
    $guid = $guid.replace("-",[String]::Empty)

    #Make sure length is valid
    if ($length -lt 0 -OR $length -gt $guid.length )
    {
        throw "Length must be between 1 and " + $guid.length

    }

    #Return the first length bytes
    return $guid.substring(0, $length)
}
利用サンプル
MSH C:\> GetRandomPasswordUsingGUID 10
96055361f3
MSH C:\> GetRandomPasswordUsingGUID 30
8dada0c027884eb3b34da049e8a75c

2006-01-05

[]Link from the Blog of /\/\o\/\/

Joyful News

This Blog had linked from the Blog of /¥/¥o¥/¥/, better-known in microsoft.public.windows.server.scripting

His blog that has many monad samples is worth seeing.

I think that he is one of good Monad Script Presenter, and the link to my blog are joyful.

2006-01-04

[]get-memberのパイプ入力の処理

あけましておめでとうごうざいます。

2006年はMonadが正式リリース・・・されるはずです、多分。(^^;

楽しいScriptingライフが送れることを期待しています。


さて、今年最初の記事は「get-member」にパイプでオブジェクトを渡した際の挙動についてです。

「get-member」について

利用頻度の高いCmdletである「get-member」。

もうお馴染みだと思いますが、オブジェクトのメンバ(プロパティやメソッド)などを一覧表示します。

標準のプロパティやメソッドだけでなく、ユーザが任意に追加した「NoteProperty」「ScriptProperty」「ScriptMethod」なども表示することができます。


表示可能なメンバは以下です。

  • AliasProperty
  • CodeMethod
  • CodeProperty
  • MemberSet
  • Method
  • NoteProperty
  • ParameterizedProperty
  • Property
  • PropertySet
  • ScriptMethod
  • ScriptProperty

「get-member」にパイプでオブジェクト配列を渡すと・・・

「get-member」にパイプでオブジェクト配列を渡すと、「get-member」は配列の各要素を処理します。

配列(System.Array)自体のメンバは表示しません。

その際「get-member」は要素の型に関してユニークなものだけを処理します。

つまり、同じ型の要素が配列に複数個含まれていても、その型のメンバは一度だけしか処理しません。


通常、配列には同じ型の要素のみが詰まっている事が多いため「get-member」は配列の先頭しか処理しないように見えますが、実際は、同じ型の処理をスキップしているだけです。

例えば、配列に2種類の型が含まれている場合、「get-member」は計2回処理されます。


サンプルで確認してみましょう。

オブジェクト配列内にユニークな型が1つしかない場合

以下は「get-process」の例です。

「get-process」の結果、61個の「Process」オブジェクトが$aに取得されますが、「get-member」にパイプで$a(配列)を渡しても1度しか処理されません。

MSH C:\> $a = get-process
MSH C:\> $a.getType().fullname
System.Object[]
MSH C:\> $a.count
61
MSH C:\> $a[0].getType().fullname
System.Diagnostics.Process
MSH C:\> $a | get-member


    TypeName: System.Diagnostics.Process

Name                           MemberType     Definition
----                           ----------     ----------
Handles                        AliasProperty  Handles = Handlecount
Name                           AliasProperty  Name = ProcessName
NPM                            AliasProperty  NPM = NonpagedSystemMemorySize
PM                             AliasProperty  PM = PagedMemorySize
VS                             AliasProperty  VS = VirtualMemorySize
WS                             AliasProperty  WS = WorkingSet
(中略)

オブジェクト配列内にユニークな型が2つあるの場合

「get-childitem」は子アイテムを取得するCmdletです。

アイテムがファイルの場合は「System.IO.FileInfo」オブジェクトを、

アイテムがディレクトリの場合は「System.IO.DirectoryInfo」オブジェクトを取得します。

MSH C:\> get-childitem | foreach{$_.getType().fullname} | get-unique
System.IO.FileInfo
System.IO.DirectoryInfo

確かに2種類のオブジェクトが含まれていますね。

ですから、「get-childitem」を「get-member」に渡すと2回処理されるはずです。

MSH C:\> get-childitem | get-member

    TypeName: System.IO.FileInfo

Name        MemberType     Definition
----        ----------     ----------
AppendText  Method         System.IO.StreamWriter AppendText()
(中略)

    TypeName: System.IO.DirectoryInfo

Name        MemberType     Definition
----        ----------     ----------
Create      Method         System.Void Create(), System.Void Create(...
(中略)
  • 予想通り「FileInfo」と「DirectoryInfo」が処理されました。

補足

「get-childitem」は様々なものを取得します。

Aliasの場合→System.Management.Automation.AliasInfo

Functionの場合→System.Management.Automation.FunctionInfo

Filterの場合→System.Management.Automation.FilterInfo

レジストリの場合→Microsoft.Win32.RegistryKey

証明書の場合→System.Management.Automation.Commands.X509StoreLocation

を取得します。

※他にも変数環境変数なども取得できます。

Connection: close