[リストへもどる]   [VBレスキュー(花ちゃん)]
一括表示

投稿時間:2005/11/14(Mon) 14:31
投稿者名:
Eメール:
URL :
タイトル:
起動したアプリが起動させたプログラムの終了を感知する方法
OS:Windows2000 Ver:VB6

お世話になります。
現在サンプルにある「Shell関数で起動したプログラムの終了を待つ」の方法を利用して
プログラムの起動・監視を行い、それが正常に終了したか否かをチェックしています。
(起動のタイミングはユーザの任意です)

ところが今回、起動したプログラムの終了時に別のプログラムが自動で起動される仕組みを
監視することになり困っています。
2つのプログラム(A、Bとします)の内容に手を入れることはできず、またBはAから起動されなけれ

正常に動作しない(連携しているようです)ため、こちらのプログラムではAを起動させるしかありま
せん。
Aを監視しているとAの終了に合わせてBが起動するため、その時点でチェック処理が走ってしまいます

当然Bはまだ実行中で、全体の処理は未完のため正常終了となりません。
Bはユーザインタフェースを持っており、入力をユーザに求めるため一定時間待てば良い訳でもありま
せん。

なんとかして「Aを起動した後、Aの終了時に起動されるBの終了を感知する」事はできないでしょうか

判りにくい文章かと思いますが、どうか知恵をお貸しください。

投稿時間:2005/11/14(Mon) 15:49
投稿者名:ダンボ
URL :
タイトル:
Re: 起動したアプリが起動させたプログラムの終了を感知する方法
> なんとかして「Aを起動した後、Aの終了時に起動されるBの終了を感知する」事はできないでしょうか

前提条件:
1.Bはシステムでは同時に一個しか動かない。
2.Bのキャプションは固定である(または決定できる)

ならば、
Aの終了後に定期的(数秒後or数ミリ秒後)にFindWindowでBのウィンドウハンドルを
見に行き、見つからなくなったらBが終了したと判断する。

でいかがでしょう。

投稿時間:2005/11/14(Mon) 17:31
投稿者名:
Eメール:
URL :
タイトル:
Re^2: 起動したアプリが起動させたプログラムの終了を感知する方法
回答ありがとうございます。

> 前提条件:
> 1.Bはシステムでは同時に一個しか動かない。
> 2.Bのキャプションは固定である(または決定できる)
>
前提条件2はOKとして1に関しては100%ありえないとは言えないまでも
ユーザがそう意図しない限り複数起動することはないはずですので
大丈夫だと思います。
ご指摘の方法でBの終了を感知できました。ありがとうございます。

Dim INST As Long
Dim PROCESS As Long
Dim Ret As Long
Dim ENDWORK As Long

' Aの起動
INST = Shell("Aのフルパス名", 1)

' Aのプロセスハンドルを取得する
PROCESS = OpenProcess(1024 Or 1048576, True, INST)

' Aの終了を監視
Do
    Ret = GetExitCodeProcess(PROCESS, ENDWORK)
    DoEvents
Loop While ENDWORK = 259

' Bが表示されるまでのタイムラグを回避
Call Sleep(1000000)

' Bの終了を監視
Do
    If FindWindowA(vbNullString, "Bのキャプション") = 0 Then
        Exit Do
    End If
    DoEvents
Loop
MsgBox "B終了!"

' 以下チェック処理へ

投稿時間:2005/11/15(Tue) 10:03
投稿者名:ダンボ
URL :
タイトル:
添削
そのコーディングだと監視プログラムのCPU負荷が高いですね。
また16分待っている間にBが終わってしまったら?ああそれはそれでもいいのか。

' Aの終了を監視
Do
    Ret = GetExitCodeProcess(PROCESS, ENDWORK)
    Call Sleep(1000)       '1秒位かな?無用なCPU負荷を回避する
Loop While ENDWORK = 259

' Bが表示されるまでのタイムラグを回避
Do
    If FindWindowA(vbNullString, "Bのキャプション") <> 0 Then
        Exit Do
    End If
    DoEvents               'ここはクリティカルだからCPU100%で待つ
Loop

' Bの終了を監視
Do
    If FindWindowA(vbNullString, "Bのキャプション") = 0 Then
        Exit Do
    End If
    Call Sleep(1000)       '1秒位かな?無用なCPU負荷を回避する
Loop
MsgBox "B終了!"

投稿時間:2005/11/15(Tue) 11:37
投稿者名: 
Eメール:
URL :
タイトル:
 
>     DoEvents               'ここはクリティカルだからCPU100%で待つ
Sleep(1000)などとしてもいいようなアプリケーション上なら、
UIが存在しないとしてDoEventsはいらないのでは?

投稿時間:2005/11/15(Tue) 12:19
投稿者名:ダンボ
URL :
タイトル:
Re:DoEventsはいらない?
> UIが存在しないとしてDoEventsはいらないのでは?

名無し様、どうも。
いや、拙案ではどうしてもDoEventsは譲れません。
いくらOSが強制的にタスク切り替えをするとは言っても、DoEventsなしの100%ループだと
タスクBがなかなか起動しないと思うのですよ。


#突っ込みはむしろこっちに来るかと思った。
' Aの終了を監視
Do
    Ret = GetExitCodeProcess(PROCESS, ENDWORK)
    Call Sleep(1000)       '1秒位かな?無用なCPU負荷を回避する
Loop While ENDWORK = 259

よりも、
Do
    Call Sleep(1000)       '1秒位かな?無用なCPU負荷を回避する
    Ret = GetExitCodeProcess(PROCESS, ENDWORK)
Loop While ENDWORK = 259

投稿時間:2005/11/14(Mon) 17:19
投稿者名:YK
Eメール:
URL :
タイトル:
Re: 起動したアプリが起動させたプログラムの終了を感知する方法
こんにちは。

>なんとかして「Aを起動した後、Aの終了時に起動されるBの終了を感知する」事はできないでしょうか
Aの終了後にBをFindWindowでハンドルを取得して
GetWindowThreadProcessIdでプロセスIDを取得すれば良いでしょう。
ShellのタスクIDとプロセスIDは同じものです。

投稿時間:2005/11/14(Mon) 17:35
投稿者名:
Eメール:
URL :
タイトル:
Re^2: 起動したアプリが起動させたプログラムの終了を感知する方法
回答ありがとうございます。

> Aの終了後にBをFindWindowでハンドルを取得して
> GetWindowThreadProcessIdでプロセスIDを取得すれば良いでしょう。
> ShellのタスクIDとプロセスIDは同じものです。

プロセスIDを使って監視すればAの監視を行っている部分を関数化させて
スマートなコードにできそうですね。
試してみることにします。 ありがとうございました。