連載

プロフェッショナルVB.NETプログラミング

第22回 コンソール・アプリケーションの開発と活用(後編)

(株)ピーデー
川俣 晶
2002/10/26

Page1 Page2 Page3

スケジュールして無人実行

 バッチのようにコマンドを自動的に実行する仕組みがあると、ついもっと贅沢な願望を抱いてしまう。バッチ・ファイルを実行する手間も惜しいな、何もしなくても勝手に実行を開始してくれる仕組みはないだろうか? それは、Windowsのタスク・スケジューラとして存在している。バッチも一種の実行ファイルなので、タスク・スケジューラで指定すれば、あらかじめ指定したスケジュールでそれを実行してくれるのである。

 そうなると、次に気になるのは、バッチの実行結果をユーザーに伝達する方法である。ログ・ファイルを残す、イベント・ログに記録する、といった方法も考えられるが、ここでは電子メールで通知する方法を試してみよう。

 電子メールで結果を通知するには、電子メールを送信するコンソール・アプリケーションがあると便利である。以下は、それを記述した例である。技術的な詳細は、第20回のサンプル・プログラムですでに説明済みなので繰り返さない。第1引数に送信者のメール・アドレスを、第2引数に宛先電子メール・アドレスを、第3引数にSubjectを、標準入力から送信する内容のテキストを入力する。なお、これはあくまでサンプルなので、エラー発生時の対応などが不十分である。実用システムでは使わないようにお願いしたい。

  1: Module Module1
  2:
  3:   Sub Main(ByVal CmdArgs() As String)
  4:     If CmdArgs.Length <> 3 Then
  5:       Console.WriteLine("usage: Sample005n from mailto subject")
  6:       Return
  7:     End If
  8:     Dim sb As New System.Text.StringBuilder()
  9:     Do
 10:       Dim s As String
 11:       s = Console.ReadLine()
 12:       If s Is Nothing Then
 13:         Exit Do
 14:       End If
 15:       sb.Append(s)
 16:       sb.Append(Chr(13))
 17:       sb.Append(Chr(10))
 18:     Loop
 19:
 20:     System.Web.Mail.SmtpMail.Send(CmdArgs(0), CmdArgs(1), CmdArgs(2), sb.ToString())
 21:   End Sub
 22:
 23: End Module
標準入力から読み取ったファイルを電子メールで送信するサンプル・プログラム3

 それではこれを使って、ドライブCの残り容量を電子メールで報告するバッチを組んでみよう。まず、残り容量を知る方法を考えてみる。取りあえずdirコマンドで表示されることは分かっているので、そこから残り容量の情報を抜き出すことを考えてみよう。「バイトの空き領域」という文字列のある行に空き容量のバイト数が表示されているので、findコマンドでその行を抜き出すようにしてみる。それには、「dir c:\|find "バイトの空き領域"」とすればよい。さらに、これを上記の電子メール送信プログラムに流し込めばよい。これをまとめると以下のようになる。なお電子メール送信プログラムは完全な絶対パスで書いてあるが、ここは読者が試す場合は変更する必要がある。また報告先の電子メール・アドレスも変更の必要がある。

dir c:\|find "バイトの空き領域"|Q:\aWrite\@it\vbn\019\smpl\Sample005n\bin\Sample005n.exe hitomi@piedey.co.jp hitomi@piedey.co.jp "Drive C 残り容量レポート"
サンプル・プログラム3を使用して、ドライブCの残り容量をメールで送信するためのコマンド例

 この内容をsample002.batのようなファイル名で保存したらまず実行してみよう。指定した電子メール・アドレスに、以下のような内容のメールが届いていれば成功である。

 1:          6 個のディレクトリ   9,722,691,584 バイトの空き領域
上記のコマンドを実行した場合に送信されるメールの例

 「6 個のディレクトリ」という文字列は不要なものなのだが、dirコマンドでは残り容量と同じ行に表示されるので仕方がない。これを取り除くには、sed(ストリーム・エディタ)のようなコンソール・アプリケーションを使用することができるが、高度な応用の範疇に入るので、本稿では割愛する。

 最後に、タスク・スケジューラに登録しよう。タスクの追加は、[コントロール パネル]の[タスク]から行うことができる。

タスクとして実行されるファイルのファイル名と、それを実行するときに使用されるアカウント名を指定する
 
例として毎日午前2時に実行されるようにスケジュールする

 この例では毎日午前2時にこのバッチは実行され、指定されたメール・ボックスにドライブCの空き容量を報告してくれることになる。ただし、ログオンしていない状態でも走ることになるので、ログオンしているときにのみ有効な資源(仮想ドライブなど)を利用しないように注意しよう。

プロセスの終了コード

 前項のバッチでは、エラーの発生があってもなくてもそのまま終了する。しかし、それは実用システムではちょっと困った動作である。例えば電子メールを送信するコンソール・アプリケーションがエラーになったときは、ファイルで情報を残す、といったバッチは組めないだろうか。

 これを実現するためには、プログラムがプロセスの終了コードを返すようにすればよい。バッチの中で、このコードを調べて動作を変更する機能が用意されているので、コンソール・アプリケーションからは、正常終了時と、異常終了時では異なる値を終了コードとするように記述しておけば、条件次第で動作を変えることができる。以下は、終了コードを返すように前項のサンプル・プログラム3を変更したものである。

  1: Module Module1
  2:
  3:   Function Main(ByVal CmdArgs() As String) As Integer
  4:     Try
  5:       If CmdArgs.Length <> 3 Then
  6:         Console.WriteLine("usage: Sample005n from mailto subject")
  7:         Return 4
  8:       End If
  9:       Dim sb As New System.Text.StringBuilder()
 10:       Do
 11:         Dim s As String
 12:         s = Console.ReadLine()
 13:         If s Is Nothing Then
 14:           Exit Do
 15:         End If
 16:         sb.Append(s)
 17:         sb.Append(Chr(13))
 18:         sb.Append(Chr(10))
 19:       Loop
 20:
 21:       System.Web.Mail.SmtpMail.Send(CmdArgs(0), CmdArgs(1), CmdArgs(2), sb.ToString())
 22:       Return 0
 23:     Catch ex As Exception
 24:       Return 2
 25:     End Try
 26:   End Function
 27:
 28: End Module
プログラムの終了時に終了コードを返すようにサンプル・プログラム3を書き換えたサンプル・プログラム4

 変更点のポイントは、3行目がSub Mainではなく、Integer値を返すFunctionに変わっている点である。これにより、このFunctionが返す数値が終了コードとなる。次に4行目にTry文を記述して、23行目のCatch文ですべての例外を受けている点である。例外を受けた場合は、24行目でReturn 2で「2」という値を返している。そうでなければ、22行目のReturn 0で「0」を返している。正常終了なら終了コードは「0」で、異常終了なら終了コードは「2」ということである。

 このコマンドを活用するバッチは以下のようになる。

 1: dir c:\|find "バイトの空き領域" >last_report.txt
 2: Q:\aWrite\@it\vbn\019\smpl\Sample006n\bin\Sample006n.exe hitomi@piedey.co.jp hitomi@piedey.co.jp "Drive C 残り容量レポート" <last_report.txt
 3: if errorlevel 2 goto error
 4: del last_report.txt
 5: exit
 6: :error
サンプル・プログラム4を利用するバッチ・ファイルの記述例

 ポイントは3行目のifコマンドである。このコマンドで、直前のコマンドの終了コードの値を調べることができる。ここでは終了コードが2以上なら、後半のコマンド、つまりgoto errorを実行する。goto errorとはラベル“error”にジャンプせよということで、終了コードが2以上のときは6行目に処理がジャンプする。そうでないときは、4行目以降が実行される。4行目のdelコマンドはファイルを消去する。5行目のexitコマンドは、コマンド・プロンプトを閉じる働きがある。

 つまり、このバッチは、電子メールの送信が成功した場合(終了コード0のとき)は、電子メールで送信する内容を含むlast_report.txtファイルを消去してそのまま終了するが、何か異常があったとき(終了コード2以上のとき)は、ファイルを消さないで終了し、ログ・ファイルを残す。実用的に使われるプログラムでは、終了コードは2種類だけで終わらせるのではなく、条件によってさまざまな値を返すように作成するとよいだろう。そうすれば、発生した異常な状態の種類によって、バッチの動作を変えることもできる。

次回予告

 前回および今回で解説したことは、コマンド・プロンプトとコンソール・アプリケーションのほんのさわりにすぎない。興味のある方は、いろいろ調べてみるとよいだろう。

 次回は、まったく新しい機能であるデリゲートに関する解説を予定している。End of Article


 INDEX
  連載 プロフェッショナルVB.NETプログラミング
  第22回 コンソール・アプリケーションの開発と活用(後編)
    1.コンソール・アプリケーションと入出力
    2.パイプの活用
  3.スケジュールして無人実行
 
「プロフェッショナルVB.NETプログラミング」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間