none
ProcessクラスのExitTimeプロパティが不正な値を返す RRS feed

  • 質問

  • OS:

    • Windows Vista Business(Ver.6.0.6000 ビルド 6000)

    開発環境:

    • VisualStudio2005(Ver.8.0.50727.867)
    • .NET 2.0.50727

    いくつかの実行ファイルを一定間隔で起動するプログラムを作成しています。そのプログラムで実行した実行ファイルの開始時間と終了時間を取得し、その差から実行ファイルの処理時間を計算しているのですが終了時間がまれにうまく取得できない場合があります。

     

    具体的には、ProcessStartInfoクラスを使用して実行ファイルの起動する情報を記述し、Process.Start()で実行ファイルを起動しています。その戻り値はArrayListクラスのインスタンスに格納し、ProcessクラスのHasExitedプロパティでプロセスの終了確認を行った後にExitTimeプロパティで終了時間を取得しています。

     

    しかし、まれにExitTimeプロパティが返す値が"1601/01/01 9:00:00"となってしまう事があります。

    Web上で同じような事例があるかと思い調べてみたのですが見つかりませんでした。

    人力検索サービスも利用しましたが、同じような事例はないとの事でした。

     

    この現象についてご存知の方がいらっしゃいましたら、ご教授お願い致します。

     

    #コードは以下です。

     

    起動部分:

     

    try {

    System.Diagnostics.ProcessStartInfo psi =

    new System.Diagnotics.ProcessStartInfo();

     

    // この"module.exe"は引数に関係なく、ただ 0 を返すだけの実行ファイルです

    psi.FileName = "module.exe";

    psi.Arguments = "ip=127.0.0.1 port=7777";

    psi.WorkingDirectory = Application.StartupPath;

    psi.WindowStyle = System.Diagnotics.ProcessWindowStyle.Hidden;

     

    // このインスタンスをArrayListクラスのインスタンス al に格納しています

    System.Diagnostics.Process p =

    System.Diagnotics.Process.Start(psi);

    } catch (Exception ex) {

    ...例外時の処理

    }

     

     

    終了時間を取得している部分:

     

    /*--------------------------------------------------

    起動時に格納したProcessクラスのインスタンスはArrayListクラスの al 内にあります。

    al には私が作成したCParaTaskListクラスのインスタンスが予め入っており、

    そのインスタンスの Instance プロパティにProcessクラスのインスタンスが格納されています。

    --------------------------------------------------*/

    if (tl.Instance.HasExited) {

    // tl はCParaTaskListクラスのインスタンスです

    TimeSpan diff = tl.Instance.ExitTime.SubStract(tl.Instance.StartTime);

     

    // 終了時間が"1601/01/01 9:00:00"の時は結果がマイナスの値なので 0 を表示しています

    Textbox1.Text = diff.TotalSeconds < 0 ? 0 : diff.TotalSeconds;

    }

    2008年6月30日 6:30

回答

  • 気持ち悪い動作ですねぇ。

    Exited イベント時点でも ExitTime の取り損ねは普通に発生するようです。

    // ExitCode は問題なく取れました。

    WaitForExit メソッドを呼び出して終了を待機することで取りあえず問題なさそうに見えます。

    2008年7月1日 15:08
  • Exited状態に移行してから時刻が設定されるまでに隙が見えるんですね…、これはこれは。

     

    参考情報として付記しておきます。

    ExitTimeプロパティは内部で値をキャッシュする仕組みがあり、初回に取得した値をずっと返すようになっています。(.NET 2.0 SP1 on XP)

    このため、ExitTimeプロパティが不正値ならという判定はNGです。

     

    Hongliangさんが提示されている手法で待ってから処理するしかないかと思われます。

    2008年7月1日 15:17
    モデレータ

すべての返信

  • 回答ではありませんが、気になった点を。

     

     DDrop さんからの引用

    Windows Vista Business(Ver.6.0.6000 ビルド 6000)

    UACは有効ですか?

    管理者権限のプロセスですか?(起動する側、起動される側)

    立ち上げる実行ファイルは1つだけですか?

     

     DDrop さんからの引用

    しかし、まれにExitTimeプロパティが返す値が"1601/01/01 9:00:00"となってしまう事があります。

    その「まれ」とは、どのくらいの発生率なんでしょうか?(何千回やって一回とか?)

    そのときに同時に取得しているStartTimeは正常なんでしょうか?

    2008年6月30日 14:58
    モデレータ
  • Azulean 様

    お返事ありがとうございます。

     

     Azulean さんからの引用

    UACは有効ですか?

     

    UACは有効な状態です。

     

     Azulean さんからの引用

    管理者権限のプロセスですか?(起動する側、起動される側)

     

    ExitTimeを取得しているのは起動する側のプログラムです。

    管理者権限のプロセスかどうかは分からないのですが(私が理解していない為)、私はAdministrator権限をもったユーザでWindowsにログインしていて、起動する側のプログラムを実行すると、タスクマネージャのプロセス一覧上でそのプロセスのユーザ名は私のユーザの名前が表示されています。(UACが有効な場合に確認画面が出るものが管理者権限のプロセスなのでしょうか(^^;?。)

    また、同様の理由から起動される側の実行ファイルも管理者権限かどうかが分かりません。

     

     Azulean さんからの引用

    立ち上げる実行ファイルは1つだけですか?

     

    立ち上げる実行ファイル自体は1つですが、複数回起動をしています。

     

     Azulean さんからの引用

    その「まれ」とは、どのくらいの発生率なんでしょうか?(何千回やって一回とか?)

    そのときに同時に取得しているStartTimeは正常なんでしょうか?

     

    1分間におよそ400回ほど起動を行い、5秒間隔を空けるといった事を1時間動かし続けると、1~2回でるかでないかといった感じです。不正な値が取得されてしまうのはExitTimeだけで、StartTimeは全て意図した値でした。

     

    宜しくお願い致します。

    2008年7月1日 1:49
  • あれから、実行ファイルを起動後に HasExited で終了確認を行い StartTime と ExitTime を表示するプログラムを作成して挙動を調べてみました。なんとなく分かった事がありましたので書き記します。

     

    コードは以下です。

     

    実行処理:

    ------------------------------------------------------------------------------------------------------------------------

     

    // 実行中を判断するためのフラグ

    private bool m_bRunning = false;

     

    // 起動処理

    private Process Run()

    {

    ProcessStartInfo psi = new ProcessStartInfo();

     

    // Module.exe はランダムな時間でSleepを行い、0 を返します

    psi.FileName = Application.StartupPath + @"\Module.exe";

    psi.WindowStyle = ProcessWindowStyle.Hidden;

     

    return Process.Start(psi);

    }

     

    // 開始ボタン押下の処理

    private void btnStart_Click(object sender, EventArgs e)

    {

    this.m_bRunning = true;

     

    // 画面のテキストボックスからSleepの時間を取得

    int iWait = this.txtWait.Text;

     

    while (m_bRunning) {

    Application.DoEvents();

    using (Process p = this.Run()) {

    try {

    while (!p.HasExited) {

    System.Threading.Thread.Sleep(iWait);

    Application.DoEvents();

    }

     

    this.txtLog.Text += string.Format("[{0}] StartTime:{1} ExitTime:{2}"

    , DateTime.Now, p.StartTime, p.ExitTime);

    } finally {

    if (p != null) {

    p.Close();

    }

    }

    }

    }

    }

     

    // 停止ボタン押下の処理

    private void btnStop_Click(object sender, EventArgs e)

    {

    this.m_bRunning = false;

    }

     

    ------------------------------------------------------------------------------------------------------------------------

     

    このプログラムを実行して iWait の値に 0 ~ 10 を入れて試したところ、0ms の時に ExitTime が不正な値を取得する事が頻繁に起きて、1ms 以上だと途端にその回数が減りました(正確には 1 以外の時は発生しませんでした)

     

    HasExited が true になった直後だと ExitTime は Process クラスによって初期化された値のままで正しい終了時間が取得できないのでは?と思いました。

     

    引き続き調べてみたいと思います。

     

    ※補足

    上記の結果になった環境は以下です。

    CPU:Intel Core2Duo 6400 2.13GHz

    Memory:1GB

    OS:WindowsVista Business

     

    下記の環境では iWait が 0ms であっても不正な ExitTime を取得する事はありませんでした。

    CPU:Pentium4 3.4GHz

    Memory:512MB

    OS:WindowsXP sp2

    2008年7月1日 8:22
  • 参考までにExitTimeプロパティが不正な時のExitCodeプロパティはどうなっていますか?

    ExitTimeプロパティより前に取得してみて下さい。

     

     

    #類似例がないのは瞬間的に多数のプロセスを立ち上げるという需要があまりないからかなぁ。

    2008年7月1日 14:52
    モデレータ
  • 気持ち悪い動作ですねぇ。

    Exited イベント時点でも ExitTime の取り損ねは普通に発生するようです。

    // ExitCode は問題なく取れました。

    WaitForExit メソッドを呼び出して終了を待機することで取りあえず問題なさそうに見えます。

    2008年7月1日 15:08
  • Exited状態に移行してから時刻が設定されるまでに隙が見えるんですね…、これはこれは。

     

    参考情報として付記しておきます。

    ExitTimeプロパティは内部で値をキャッシュする仕組みがあり、初回に取得した値をずっと返すようになっています。(.NET 2.0 SP1 on XP)

    このため、ExitTimeプロパティが不正値ならという判定はNGです。

     

    Hongliangさんが提示されている手法で待ってから処理するしかないかと思われます。

    2008年7月1日 15:17
    モデレータ
  • Azulean 様、Hongliang 様

     

    お二方が提示される WaitForExit メソッドを使用したところ、 ExitTime プロパティが不正な値を返す現象は見られなくなりました。

     

    私一人ではこのような明確な答えに辿り着くことは出来なかったと思います。

    深夜に貴重なお時間を使ってまでお力添えをして頂き、感謝の気持ちで一杯です。

    本当にありがとうございます!!!

     

    この件に関してまた何か分かったことや疑問がでた際はこのスレッドにて報告致します。

     

    P.S.

     Azulean さんからの引用

    ExitTimeプロパティは内部で値をキャッシュする仕組みがあり、初回に取得した値をずっと返すようになっています。(.NET 2.0 SP1 on XP)

     

    この情報なのですが、どのようにしてお調べになったのでしょうか。 Process クラスのソースを読まれたのですか?

    もし、今後同じような事があった際に自分で調べられるようになりたいので教えて頂けないでしょうか?

    2008年7月2日 1:42
  •  DDrop さんからの引用

    この情報なのですが、どのようにしてお調べになったのでしょうか。 Process クラスのソースを読まれたのですか?

    もし、今後同じような事があった際に自分で調べられるようになりたいので教えて頂けないでしょうか?

    Visual Studio 2008(Express Editionを除く)からは.NET Frameworkのベースクラスライブラリのソースコードが公開されています。

    Visual Studio 2008を利用するか、何らかのツールを利用すれば、Processクラスのソースコードを参照することができます。

     

    詳しくはGoogle検索などで情報を集めてみて下さい。

    http://www.google.co.jp/search?hl=ja&q=.NET+Framework+%E3%82%BD%E3%83%BC%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%89&lr=lang_ja

     

    なお、SP1を適用する前の.NET Frameworkのソースコードは閲覧することができません。

    2008年7月2日 14:13
    モデレータ
  • Azulean 様

     

    情報を提供して頂きありがとうございます。

     

    私もソースコードを読んでみたいと思います。

    2008年7月3日 6:42