PowerShellで進捗(しんちょく)をプログレスバーで表示する【Windows OS】Tech TIPS

処理時間の長いスクリプトを実行する場合、何も表示せずにユーザーを待たせるのは不親切である。処理中にプログレスバーを表示することで、スクリプトが確かに動作していることをユーザーは視覚的に確認できる。PowerShellの「Write-Progress」コマンドレットを利用すれば、視覚的なプログレスバーを簡単に作成できる。

» 2008年05月02日 05時00分 公開
[山田祥寛]
「Tech TIPS」のインデックス

連載目次

PowerShellで進捗(しんちょく)をプログレスバーで表示する【Windows OS】

対象OS:Windows PowerShell


 PowerShellで処理時間の長いスクリプトを実行する場合、何も表示せずに、ただユーザーを待たせるのは不親切だ。ユーザーは処理が実際に行われているのか不安に思うだろうし、短気なユーザーであれば、数秒間何も動作しない(ように見える)スクリプトは、クラッシュしていると思い込んで強制的に終了しようとするかもしれない。

 そこで、処理が数秒以上に及ぶようなスクリプトを実行する場合は、「プログレスバー」「進捗(しんちょく)バー」を表示するようにしておくのがよいだろう。これによって、エンドユーザーはスクリプトがクラッシュしておらず、確かに継続して実行されていることを確認できるし、処理が現時点で何割程度完了しているのか(あとどの程度の時間がかかりそうなのか)を把握できる。

 PowerShellではこのようなプログレスバーを生成するために、Write-Progressという専用コマンドレットを用意している。これを利用すれば、最低限のパラメータ指定だけで視覚的なプログレスバーをスクリプトに組み込むことができる。

 それではさっそく、具体的なサンプルコードを見ていくことにしよう。ここでは、Tech TIPS「PowerShellでテンプレートを使ってメールを一斉配信する」で紹介したMailTransfer.ps1スクリプトに対して、メールの送信状況を表すプログレスバーを追加してみよう。

[注意]

PowerShellを利用するには、あらかじめシステムにユーザー自身がインストールしておく必要があります。具体的なインストール方法については「PowerShellをインストールする」を参照してください。


手順1――テキストエディタでPowerShellのコードを入力する

 まずはテキストエディタ(メモ帳でも何でもよい)を開き、以下のコードを入力してほしい。なお「#」で始まる行は、コードの意味を解説するためのコメント部分なので、省略してもよい。コメントには、スクリプトの簡単な説明を入れておいた。

 なお、本稿ではプログレスバーにかかわる部分(リスト内の太字部分)のみを解説する。メール送信のロジックそのものについては、前出のTech TIPを参照していただきたい。

$smtp = "smtp.examples.com"
$from = "Xxxxxx@examples.com"
$subject = "WINGS NEWS[2008/05/05]PowerShell TIPS連載開始"

$db = New-Object Data.OleDb.OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\tmp\mail.mdb")
$comm = New-Object System.Data.OleDb.OleDbCommand("SELECT * FROM mail", $db)
# mailテーブル内のレコード件数(アドレス件数)を取得
$comm2 = New-Object System.Data.OleDb.OleDbCommand("SELECT COUNT(*) FROM mail", $db)
$db.Open()
$rs = $comm.ExecuteReader()
$num = $comm2.ExecuteScalar()

$cli = New-Object Net.Mail.SmtpClient($smtp)
$body = [String]::join("`r`n", (Get-Content mail.dat))

# 何通目のメールを送信しているのかをカウントするための変数$cntを定義
$cnt = 1;
while($rs.Read()){
  $mail = New-Object Net.Mail.MailMessage($from, $rs["email"])
  $mail.Subject = $subject
  $tmp = $body
  for($i=0; $i -lt $rs.FieldCount; $i++){
    $tmp = $tmp -replace ("{" + $rs.GetName($i) + "}"), $rs.GetString($i)
  }
  $mail.Body = $tmp
  $mail.SubjectEncoding = [System.Text.Encoding]::GetEncoding("ISO-2022-JP")
  $mail.BodyEncoding = [System.Text.Encoding]::GetEncoding("ISO-2022-JP")
  $cli.Send($mail)
 
# 進捗のパーセンテージを求める
    $p = $cnt / $num * 100;
# プログレス・バーを表示
    Write-Progress "Mail Transfer" ([String]$p + "%") -percentComplete $p
# 処理を500ミリ秒だけ休止(サンプルの動作を確認するためのダミー)
  Start-Sleep -milliseconds 500
# メール件数をカウントする変数$cntをカウントアップ
  $cnt++;
}
$db.Close()

ファイル:Progress.ps1
サンプルファイルProgress.ps1およびサンプルデータファイルをダウンロードするには、ここをクリックしてください。

 PowerShellスクリプトの実行ファイルは拡張子を「.ps1」とする必要がある。ファイル名自体は何でも構わないが、ここでは「Progress.ps1」という名前で保存しておこう。

 コード全体の流れについてはリスト内のコメントをご覧いただくとして、ここで注目してほしいのは次の2点だ。

1.プログレスバーを表示するのは「Write-Progress」コマンドレット

  冒頭で述べたように、PowerShell上でプログレスバーを表示するのは、「Write-Progress」コマンドレットの役割だ。プログレスバーを表示するために最低限必要な構文は次のとおりである(利用可能な全パラメータについては、PowerShellのヘルプを参照していただきたい)。

Write-Progress [-activity] <動作状況を表す文字列> [-status] <現在の状態を表す文字列> [-percentComplete <進捗パーセンテージ>] [-secondsRemaining <残り時間>]


 「-activity」「-status」パラメータは、それぞれプログレスバーの先頭行と2行目に表示する文字列である。ここでは、「-status」プロパティに進捗状況に応じてパーセンテージ表示用の文字列をセットしている。また、サンプルのリストではこれらパラメータ名は省略しているが、もちろん、構文のように明示的に「-activity」「-status」と指定してもよい。

 「-percentComplete」パラメータはプログレスバーの進捗割合を示すためのパラメータである。リストではこちらのパラメータを使用しているが、処理の残り時間を表したい場合には「-secondRemaining」パラメータを指定することもできる。

2.処理を休止するのは「Start-Sleep」コマンドレット

  プログレスバーの表示には直接関係はないが、本サンプルでは進捗状況の変化について確認しやすいように、スクリプト内にダミーの休止処理を挟んでいる。実際のスクリプトでは(もちろん)この処理はカットすべきであるが、その場合、処理が一瞬で終わってしまい、プログレスバーが表示されない可能性もあるので、注意すること。

 PowerShellで処理を一時的に休止するのは、「Start-Sleep」コマンドレットの役割である。「Start-Sleep」コマンドレットの基本的な構文は次のとおりだ(利用可能な全パラメータについては、PowerShellのヘルプを参照していただきたい)。

Start-Sleep {[-seconds] <休止する秒数>|-milliseconds <休止するミリ秒数>}


 処理を休止する時間は、「-seconds」パラメータか「-milliseconds」パラメータのいずれかで指定できる。「-seconds」パラメータはパラメータ名を省略可能であるが、「-milliseconds」パラメータはパラメータ名まで明示する必要があるので、注意すること。

手順2――PowerShellのスクリプトコードを実行する

 Progress.ps1を実行するには、PowerShellのプロンプトを開いたうえで、以下のようにコマンドを実行すればよい(カレントフォルダにスクリプトが保存されているものとする*1)。

PS > ./Progress.ps1


*1 PowerShellでスクリプトファイルを実行する場合には、あらかじめいくつかの設定を行っておく必要がある。詳細については、「Windows PowerShellコマンド&スクリプティング入門(後編)」を参照していただきたい。


 その際、先のTech TIPS記事で紹介したmail.datがProgress.ps1と同一のフォルダ中に存在しない場合や、指定したSMTPサーバやデータベースファイルへのパスなどが間違っている場合などには、スクリプトが正しく動作しない可能性があるので、注意すること。Progress.ps1を実行して、次のようなプログレスバーが表示されれば成功である。

プログレスバーの使用例 プログレスバーの使用例
スクリプト実行時に、処理進行に従ってプログレスバーが表示され、進捗状況や残り時間などを把握しやすくなる。
  (1)動作状況のタイトル文字列。
  (2)進捗状況の%表示。
  (3)進捗状況のバー表示。

「Tech TIPS」のインデックス

Tech TIPS

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

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

メールマガジン登録

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