PowerShellのバージョン

今このブログを書いている時点ではバージョン2のCTP3が出ている状態です。もし書いたスクリプトがどうしてもV2の機能を必要とするという場合は次のようにコメントをスクリプトの一番最初の行に入れておくといいそうです。元ネタはMSのWindows PowerShell Blogから

#requires -version 2

そうすればスクリプトを実行した時点で「おんどりゃあ、Windows PowerShellの2.0必要なんじゃい!」とお叱り頂けるそうです。w

 

PowerShellスクリプトでバルーンお知らせ

仕事でいろいろなことをスクリプトで自動化することがある。「これやらなきゃ」と思ってスクリプトを実行して、そのスクリプトがしばらくかかるものならメールをチェックしたり、他の作業を同時進行することが多いのだ。そんな状況でよくあるのが、そのスクリプトを実行したことさえも忘れてしまい、いろいろなウィンドウの後ろにコンソールウィンドウがひっそりと我慢強く待っていてくれたのを一時間ぐらい後に発見する。

こんなことが起きるのはスクリプトにはあまり目立ったお知らせ機能がないからだ。Outlookだと「ダディディン!」という音と共にポップアップウィンドウで会議があと何分後にあることを知らせてくれる。スクリプトだってそのプロセスが終わったことを知らせてくれるもっと目立つ機能があってもいいのではないかと考えてPowerShellでやってみた。次に紹介するのも.NET Frameworkのおかげなのだ。

まずはバルーン機能からやってみる。そもそもバルーンとは何か。下の画像を見ていただければ一目瞭然だ。

image

Windowsを使いなら一度は見たことがあるだろう。

まず最初に、矢印のアイコンに注目する。標準のアイコンというものはなく自分で指定してやらなければいけない。スクリプトが自分のコンピュータのみで動作するのだったらいいが、そのスクリプトが他のコンピュータにも配布されるということを想定して、アイコンをBase64の文字列に変換しスクリプト内に埋め込んでみる。まずはBase64文字列に変換する作業から。

まずはファイルをByte配列としてメモリに読み込む。それをBase64文字列に変換。ちなみに今回の記事でPowerShellらしいところといえばGet-Contentのみだろう。あとは.NET Frameworkを直接使っている。

image

このBase64文字列をスクリプト内に埋め込むことにする。

もう一度確認するが、このスクリプトの目的はバルーンを使ってスクリプトの実行が終了することをより視覚的に知らせることである。それをするために次のようなスクリプトを書いてみた。

#デフォルトではSystem.Windows.Formsは読み込まれていないので、それを初めに読み込む。
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
 
#NotifyIconクラスを使うので、インスタンスを作成。
$NotifyIcon = New-Object System.Windows.Forms.NotifyIcon
 
# アイコンを表すBase64文字列を変数に格納しておく。このようにしてアイコンやいろいろなバイナ
# リデータをBase64文字列としてスクリプト内に格納することも可能だが、データのサイズが大きい
# と文字列も長くなってしまうので注意。
$iconString = "AAABAAIAEBAAAAAAAABoAwAAJgAAABAQEAAAAAAAKAEAAI4DAAAoAAAAEAAAACAAA(HTMLの関係上略)"
 
# Base64文字列をByte配列に変換。
$binaryData = [System.Convert]::FromBase64String($iconString)
 
# 次の4行でByte配列に格納されていたアイコンをSystem.Drawing.Iconにして使えるようにする。
$memStream = New-Object System.IO.MemoryStream
$memStream.Write($binaryData, 0, $binaryData.Length)
$memStream.Position = 0
$icon = New-Object System.Drawing.Icon($memStream)
 
$memStream.Close()
 
# 最終的にIconプロパティを上で作ったIconオブジェクトにセットし、ShowballoonTipメソッドを
# 実行する。
$NotifyIcon.Icon = $icon
$NotifyIcon.Visible = $true
$NotifyIcon.ShowBalloonTip(100000, "俺のスクリプト", "スクリプトは終了しましたよ!", "Info")
 

これをファイルに格納してPowerShell上で実行すると、下のようにPowerShellからバルーンを使うことができる。

image

ちなみにSystem.Media.SoundPlayerを使えば音を鳴らすことだって可能だ。音を使えばより効果的であることは容易に想像できる。あまり詳しく説明しないが次のように音を鳴らすこともできるのだ。

$SoundPlayer = New-Object System.Media.SoundPlayer("$env:SystemRoot\Media\chimes.wav")
1..3 | foreach{$SoundPlayer.Play();[System.Threading.Thread]::Sleep(1000)}

PowerShell用秀丸強調表示定義ファイル

PowerShellのスクリプトをPowerGUIで編集していたらコピペができない事態が生じたので、秀丸で編集しようと思ったら強調表示定義ファイルがない・・・ということで作ってみました。キーワードが文字列内で強調されないようにしたかったけど、正規表現がちょっとめんどかったのでそのままにしてしまいました。

ファイルはここからダウンロードできます。

一応秀丸サイトにも投稿しておきます。

PowerShellで最新コードをダウンロード

Team Foundation Serverを使うようになってからもうかれこれ2年ぐらいが経つ。その間にだんだんソリューションファイルが多くなってきたり、一つの製品の開発環境を作るのにあっちをいじったりこっちをいじったりしなきゃいけなくなってきたので、自動化を試みている。その一環としてPowerShellを使ってTeam Foundation Serverから最新バージョンのコードをダウンロードするコードを書いてみた。

param
(
    $tfsServerName = $(Throw "TFSのサーバ名を入力してください。"),
    $localFolderPath = $(Throw "ローカルのフォルダパスを入力してください。"),
    $Domain = "",
    $Username = "",
    $Password = "",
    [String[]] $getPaths = $(Throw "サーバ側から最新コードをダウンロードするパスを配列として渡してください。")
)
 
[void] [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.TeamFoundation.Client")
[void] [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.TeamFoundation.VersionControl.Client")
 
$credential = $null
 
if (($Username -eq "") -or ($Password -eq ""))
{
    $credential = Get-Credential
}
else
{
    $credential = New-Object System.Net.NetworkCredential($Username, $Password, $Domain)
}
 
#TeamFoundationServerオブジェクトを作成。
$tfs = New-Object Microsoft.TeamFoundation.Client.TeamFoundationServer($tfsServerName, $credential)
$tfs.Authenticate()
 
# VersionControlServerを使ってWorkspaceオブジェクトを取得。
$vcs = $tfs.GetService([Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer])
$ws = $vcs.GetWorkspace($localFolderPath)
 
$ws.Get($getPaths, [Microsoft.TeamFoundation.VersionControl.Client.VersionSpec]::Latest, "Full", "GetAll")
 

Measure-Object

これは以前にdevslife.comに書いた記事です。

Get-CommandでCmdletを眺めていたらMeasure-ObjectというCmdletに出くわした。なかなか面白いCmdletで使えそうである。例えば・・・

 

上のコマンドを解説すると、10,11,12…100までの配列がMeasure-Objectによって処理されてデフォルトでCountつまり配列がいくつあるかというのを表示してくれた。他にもAverage(平均)やSum(合計)やMaximum(最大値)そしてMinimum(最小値)も計算させることができそうだ。パラメータを追加すると他の値も計算してくれる。

 

日本語のテキスト(文字列)についても使える。下の例は-charのパラメータを使うことで変数内にある文字数を数えてくれるのだ。

 

テキストファイルに入っている文字列に関しても同じように使える。

 

さらに、他のオブジェクトに関しても-Propertyパラメータを使えばこんなことができる。

 

上のコマンドはどういうことかというと、Get-Processのコマンドレットで返されたプロセスのVMつまりバーチャルメモリに関しての統計である。つまりこのマシン上には50のプロセスが存在していて平均、合計、最大、最小がそれぞれの値であるということを表している。

Measure-Objectはちょっと統計を見てみたいというときに使えるコマンドレットだ。