プログラムを終了するには?

解決


未来  2006-06-07 13:46:41  No: 22103  IP: 192.*.*.*

プログラムの終了方法を教えてください。

タスクマネージャーのプロセス表示で
イメージ名を右クリックした時の
「プロセスツリーの終了」を実現したいのですが
どうすればよいのでしょうか?

現在、作成しているアプリケーション(A)から他のプログラム(B)を
CreateProcessで呼び出すと、呼び出したプログラム(B)から
別のプログラム(C)が呼び出されています。
中止ボタンをクリックすると、
TerminateProcess で (A)から呼び出したプログラム(B)の
プロセスを終了するところまではできるのですが、
プログラム(C)は動作したままで終了できません。
どうすればよいのでしょうか?

編集 削除
deldel  2006-06-07 15:01:15  No: 22104  IP: 192.*.*.*

h := FindWindow(nil, '対象アプリのタイトル');
if h <> 0 then SendMessage(h, WM_CLOSE, 0, 0);
はどうですか?

編集 削除
未来  2006-06-07 15:10:02  No: 22105  IP: 192.*.*.*

'対象アプリのタイトル'がわかりません。
コンソールアプリケーションだと思いますが、
アプリケーションには表示されてこないのです。

編集 削除
deldel  2006-06-07 16:05:30  No: 22106  IP: 192.*.*.*

WinSightやスパイなどで判りませんかねぇ・・・

編集 削除
Fusa  2006-06-08 00:43:16  No: 22107  IP: 192.*.*.*

プロセスを列挙して、プロセスIDを得てから
次のコードで終了してください。
var
  ProcessID: Cardinal;
  hProcess: THandle;
begin
  //ProcessIDを得ておく
  //ProcessID := xx;

  hProcess := OpenProcess(PROCESS_TERMINATE, False, ProcessID);
  TerminateProcess(hProcess , 0 );
  CloseHandle(hProcess);
end;
プロセス列挙コードは
http://delfusa.main.jp/delfusalibrary/20060527212010/SystemUnit/SystemUnit.pas
のGetProcExeNameList関数になります。 


(A)から呼び出した(C)なのかどうかを
特定する処理はちょっとわかりませんが。
呼び出す前にプロセス列挙して、終了したいときにプロセス列挙して
その差分を求めるとかですかな?

お任せします。

編集 削除
未来  2006-06-08 11:26:57  No: 22108  IP: 192.*.*.*

みなさん、どうもありがとうございます。

>Fusaさん
http://delfusa.main.jp/delfusalibrary/20060527212010/SystemUnit/SystemUnit.pas
これはインターネットアドレスでしょうか?
開くことができませんでした。

ProcessID はクリエイトプロセスで起動したときの
ProcessInformation.hProcess を使ってはだめなのでしょうか?
これを使って OpenProcess を呼び出すと
hProcess が 0になります。


>deldel さん
EnumWindows を使ってウィンドウハンドルをキャッチできす。
ただ、ウィンドウがなければキャッチできません。
つまり、CreateProcess 起動時の StartupInfo.wShowWindow が
SW_SHOW の場合には動作するようにはなりましたが、
SW_HIDE の場合にはハンドルが取れなくなります。



それから・・・
作成しているプログラムAからバッチファイルBを非表示で
実行します。また、BからはプログラムCが呼ばれています。
現在以下のことがわかっています。
実現したいのは2番または3番です。
宜しくお願いします。

1.Bを起動して、タスクマネージャのプロセスで
    Bを[プロセスの終了]で終了すると、
    Bが残る==>NG
    <CreateProcess で起動時の プロセスID を使って
    TerminateProcess を呼び出すと同じ症状になる>
2.Bを起動して、タスクマネージャのプロセスで
    C を[プロセスの終了]で終了すると、
    A,Bが消える==>OK
    <Cを特定することができれば可能ですが、
    現状ではその方法がわかりません>
3.Bを起動して、タスクマネージャのプロセスで
    Bを[プロセスツリーの終了]で終了すると、
    A,Bが消える==>OK
    <実現方法がわかりません>
4.Bのウィンドウが表示するようにするとEnumWindowsを使って
    ハンドルを取得して SendMessage(h, WM_CLOSE, 0, 0); で
    クローズする==>OK(ただし、目的は非表示で動作)
    <CreateProcess で起動時に StartupInfo.wShowWindow        := SW_SHOW
    で起動して、EnumWindows でハンドルを取得し、SendMessage で
    WM_CLOSE を送ることで実現可能>

編集 削除
WH00  2006-06-08 11:39:39  No: 22109  IP: 192.*.*.*

>4.Bのウィンドウが表示するようにするとEnumWindowsを使って
>    ハンドルを取得して SendMessage(h, WM_CLOSE, 0, 0); で
>    クローズする==>OK(ただし、目的は非表示で動作)

Form1.Width := 0;
Form1.Height := 0;
Form1.Top := 3333;

・・・でダメですか?

編集 削除
未来  2006-06-08 11:48:34  No: 22110  IP: 192.*.*.*

みなさん、すみませんでした。

私の認識不足でした。
EnumWindows で呼び出された コールバック関数に
IsWindowVisible が入っていました。
これがはいっているので
StartupInfo.wShowWindow が SW_HIDE のときにハンドルが
取れなかったようです。

おさわがせしてすみませんでした。

編集 削除
Fusa  2006-06-08 13:07:48  No: 22111  IP: 192.*.*.*

HTTPの最初の文字を全角のHにしてますが....

> ProcessID はクリエイトプロセスで起動したときの
> ProcessInformation.hProcess を使ってはだめなのでしょうか?
わかりませんが、
タスクマネージャの列の選択で表示できるPIDと同じものなら
OpenProcessでプロセス終了できるはずですよ。

こちらも参考ください。

編集 削除