2012年11月5日月曜日

【Visual Studio C#】[Windows サービスでバッチファイル起動]


Windows サービスの作成手順
1.「Windows サービス」プロジェクトの作成
2.「Windows サービス」プロジェクトへの「インストーラの追加」
3.「Windows サービス」のインストール/デバック

1.「Windows サービス」プロジェクトの作成
 (1)「Microsoft Visual Studio 2008」を起動
 (2)「ファイル」-「新規作成」-「プロジェクト」を実行
 (3)「Visual c#」-「Windows」-「Windows サービス」を選択して「OK」をクリック
 (4)「ツールボックス」の下の方の空いている場所でマウス右クリックして「アイテムの選択」を実行
 (5)「.Net Framework コンポーネント」の名前=「Timer」、名前空間=「System.Timers.Timer」をチェックして「OK」をクリック
    ↑のコンポーネントでないとTimerの「Elapsed」イベントが発生しない....
 (6)「System.Timers.Timer」を「Service1.cs」へドラッグ&ドロップ
 (7)「Timer1」のプロパティを確認
    「Enabled」を「False」に設定
    「Interval」を適当に設定(設定はミリ秒)
 (8)「Timer1」をダブルクリック....「Service1.cs」のコードを以下のように編集
    public partial class Service1 : ServiceBase
    {
      // バッチファイルパス
      private const string sBatPath = "c:\hoge.bat";
      // 実行間隔(....new TimeSpan(時, 分, 秒))
      private readonly TimeSpan tsExecuteInterval = new TimeSpan(24, 0, 0);

      // 実行日時....初期値:本日(yyyy/MM/dd)+時間(hh:mm:ss)....バッチ実行完了時に実行間隔を加算して次回実行日時とする
      private DateTime dtExecuteDateTime =
        DateTime.Parse(DateTime.Now.ToShortDateString() + " 23:30:00");

      protected override void OnStart(string[] args)
      {
        // デバック(「ツール」-「プロセスにアタッチ」)開始操作する間スリープさせる....これがあるとOnStartのでバックが可能....
        System.Threading.Thread.Sleep(20000);
        // タイマ開始
        timer1.Enabled = true;
      }
      protected override void OnStop()
      {
        // タイマ停止
        timer1.Enabled = false;
      }
      private void timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
      {
        if (DateTime.Now > dtExecuteDateTime)
        {
          // ProcessStartInfoを使用
          System.Diagnostics.ProcessStartInfo processStartInfo =
            new System.Diagnostics.ProcessStartInfo();
          // ComSpecのパスを取得
          processStartInfo.FileName = System.Environment.GetEnvironmentVariable("ComSpec");
          // 出力を読取可能
          processStartInfo.RedirectStandardInput = false;
          processStartInfo.RedirectStandardOutput = true;
          processStartInfo.UseShellExecute = false;
          // ウィンドウを表示しない
          processStartInfo.CreateNoWindow = true;
          // コマンドラインを指定("/c"は実行後閉じるために必要)
          processStartInfo.Arguments = @"/c " + sBatPath;

          // バッチファイル起動
          System.Diagnostics.Process process = System.Diagnostics.Process.Start(processStartInfo);
          // 出力を読み取る
          string sResults = process.StandardOutput.ReadToEnd();
          // WaitForExitはReadToEndの後である必要がある(親プロセス、子プロセスでブロック防止のため)
          process.WaitForExit();

          // 出力結果を表示
          Console.WriteLine(sResults);

          // 実行日時に実行間隔を加算して次回実行日時とする
          dtExecuteDateTime = DateTime.Parse(dtExecuteDateTime.Add(tsExecuteInterval).ToString());
        }
      }
    }

2.「Windows サービス」プロジェクトへの「インストーラの追加」
 (1)「Service1.cs」の「デザイン」画面をマウス右クリックして「インストーラの追加」を実行
 (2)「ServiceInstaller1」のプロパティを確認
    「Description」:サービス一覧画面に表示する説明
    「DisplayName」:サービス一覧画面に表示する名前
    「ServiceName」:サービスの識別名....とりあえずサービスのクラス名と合わせる方がよさげ
    「StartType」 :インストール直後の「スタートアップの種類」....とりあえず「Manual」に設定
 (3)「ServiceProcessInstaller1」のプロパティを確認
    「Account」 :サービスの実行アカウント....「LocalSystem」に設定

3.「Windows サービス」のインストール/デバック
 (1)(Windows)\Microsoft.NET\Framework\(バージョン)\installutil.exeを使用してインストール
    >installutil.exe (サービスプログラム名).exe
  アンインストール
    >installutil.exe /u (サービスプログラム名).exe
 (2)「コントロールパネル」-「管理ツール」-「サービス」を実行して(サービスプログラム)を開始する
 (3)「ツール」-「プロセスにアタッチ」を実行
    「すべてのユーザからのプロセスを表示する」をチェックする
    「すべてのセッションのプロセスを表示する」をチェックする
    「(サービスプログラム名).exe」を選択して「アタッチ」をクリックする

元ネタ:
http://ameblo.jp/dakishimetai-com/entry-10494391310.html

0 件のコメント:

コメントを投稿