任意のプロセスを終了する – プログラミング – Home

任意のプロセスを終了する
 
通知
すべてクリア

[解決済] 任意のプロセスを終了する


mac
 mac
(@mac)
ゲスト
結合: 22年前
投稿: 37
Topic starter  

いつもお世話になっております、macです。

VC++で作成した実行モジュールで、現在のプロセスをチェックして
ウィンドウは閉じているが、プロセスだけが残っているEXCELの
プロセスを強制終了するプログラムを作成しています。

以下にソースを載せます。

ここから ****
// ハンドルの取得
HANDLE hSnap;
if((hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) ==
INVALID_HANDLE_VALUE) {
return;
}

PROCESSENTRY32 pe;
pe.dwSize = sizeof(pe);
UINT len = 0;
TCHAR buf[4048];

// 全てのプロセスをチェックする
BOOL bResult = Process32First(hSnap, &pe);
while(bResult){
     // 次を取得
bResult = Process32Next(hSnap, &pe);
    // EXCELの場合
if (!strcmp(pe.szExeFile, EXCEL.EXE)) {
// プロセスIDからハンドルの取得
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE,
pe.th32ProcessID);

         // プロセスを閉じる
         DWORD dwExitCode = 0;
         GetExitCodeProcess(hProcess, &dwExitCode);
CloseHandle(hProcess);
}
}

CloseHandle(hSnap);
ここまで **********

ところが、ここの処理を通った後でもEXCELが終了しません。
プロセスIDからHANDLEは取得できていますが、違うHANDLEを取ってきて
しまっているのでしょうか?

過去ログを見て、「Knowledge Base JP175030」を調べてみましたが、
ちょっと違うようです。
どなたがご教授お願いします。

開発環境
WindowsXP VC++6.0 Excel 2000


引用未解決
トピックタグ
YuO
 YuO
(@YuO)
ゲスト
結合: 22年前
投稿: 320
 

Excelを終了させるという処理が入っていませんから当然です。

GetExitCodeProcessは該当プロセスの終了コードを(終了していれば)取得するAPIであっ
て,
プロセスを終了させるAPIではありません。
そして,安全にプロセスを終了させる方法は存在しません。

COMを使って終了させることができるかもしれませんが,
そもそもExcelがなぜそういう状態になったのかわからないのですから,
COMの制御を受け付けるとは限りません。

TerminateProcessを使えば,強制終了させることはできますが,
その場合,正常終了ではない以上,データの破損があるかもしれません。


返信引用
mac
 mac
(@mac)
ゲスト
結合: 22年前
投稿: 37
Topic starter  

YuO様、回答ありがとうございます。

TerminateProcessを追加したら、Excelのプロセスを消すことが出来ました。

なぜExcelのプロセスが残ってしまうかというと、以前このラウンジで
質問した通りです。
以下にURLを載せます。
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200512/05120046.txt

ところで、上記の方法で試してみたところ、Excelのプロセスは消えましたが、
対象以外のExcelが起動している場合、そちらも消えてしまいます。

ExcelApplicationから起動したExcelのプロセスIDまたはHANDLE等、他のExcel
と区別できるような値は取得できるのでしょうか?


返信引用
dairygoods
 dairygoods
(@dairygoods)
ゲスト
結合: 23年前
投稿: 1421
 

> ところで、上記の方法で試してみたところ、Excelのプロセスは消えましたが、
> 対象以外のExcelが起動している場合、そちらも消えてしまいます。

普通 Excel は複数のファイルを単一プロセスで開きます。
本当に複数の excel.exe が起動している状態でそうなりますか?


返信引用
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2660
 

上記のコードだと「EXCEL.EXE」という実行ファイル名のプロセスは
片っ端から終わらせるようなコードみたいなので全部終わらせてしまいそうですね。

ただ、dairygoodsさんが指摘されている部分もあると思うので
ちゃんと確認しないと何とも言えないような気がします。
ちなみに元々のプロセスが残ってしまうと言う問題は呼び出している
プログラム側に問題が無くても起こってしまうような話なんでしょうか。
残るからには何か問題があるような気がしてならないのですけれど。


返信引用
mac
 mac
(@mac)
ゲスト
結合: 22年前
投稿: 37
Topic starter  

dairygoods様、PATIO様、回答ありがとうございます。

>> ところで、上記の方法で試してみたところ、Excelのプロセスは消えましたが、
>> 対象以外のExcelが起動している場合、そちらも消えてしまいます。

> 普通 Excel は複数のファイルを単一プロセスで開きます。
> 本当に複数の excel.exe が起動している状態でそうなりますか?

起動中のExcelにBookを追加するのではなく、新しくExcelを起動すると、
起動した分のプロセスが存在します。

> ちなみに元々のプロセスが残ってしまうと言う問題は呼び出している
> プログラム側に問題が無くても起こってしまうような話なんでしょうか。
> 残るからには何か問題があるような気がしてならないのですけれど。

確かにその通りです。
ですが、いろいろ試してみましたが変化はありませんでした。
そのためこのような強制終了の手段をとるようにしようと考えました。


返信引用
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2660
 

潜在的な不具合を抱えていると言うことは無いですか?
気がついていないだけでメモリは壊しているようなパターンと言うのもありえると思うの
ですが。
正しく処理しているのにプロセスが終了しないと言う前例でもあればわかるんですが、
そうでない場合は対処療法を考えるよりも呼び出し側のプログラムをチェックしなおした方が
良いのではないかと言う気がします。

どなたか、呼び出し側に問題が無いのにEXCELのプロセスが残ると言うような例を
ご存知の方はいらっしゃいますか?


返信引用
pseudo
 pseudo
(@pseudo)
ゲスト
結合: 19年前
投稿: 3
 

Excelのプロセスが消えない現象についてですが
私の現在の仕事でも、とあるソースコードの中でそんな事を訴えながら
 1. 処理開始前のプロセスを列挙する。
 2. 処理。 (この中でExcelを起動したりする)
 3. 終了処理。処理開始前に列挙したプロセスと現在のプロセスを比較し
   増えちゃってるExcelプロセスをkillする。
という、なんだかなぁな処理を行っています。

殆どの原因はオブジェクトの解放がうまく行えていないからで、
たとえば下記ページ(「Visual Basic 中学校」さん)などが参考になります。
http://homepage1.nifty.com/rucio/main/technique/teq_15.htm
Excelは多少クセが強いのか?意外な操作で意外なオブジェクトを生成してしまい
それを解放しそこなう、といったパターンについて警告されています。
「呼び出し側に問題は無い」というよりは
「呼び出し側の問題に、なかなか気付きにくい」という感じでしょうか。

# おふとぴ:
# ご多分にもれず、私の仕事の件でもやはりオブジェクトの解放が
# うまく行えていなかったのですが、それを上司に報告すると
# 「……見なかった事にしてくれ」と。
# 実際に業務で使用されるコードでは無いし
# 上位の上位くらいに居る大会社様から下賜されたコードなので
# 立場的に ダメ出し できないようで。。。うちの会社、弱ぇ。。。


返信引用
mac
 mac
(@mac)
ゲスト
結合: 22年前
投稿: 37
Topic starter  

PATIO様、pseudo様回答ありがとうございます。

とりあえず、今のところはExcelの保存後プロセスが残っているようなら
強制終了するようにしました。

以下にソースを記述します。

// Excelを判別するCaptionをセット
m_excel.SetCaption(SetCaptionSample);

// BOOK・BOOKS・アプリケーションを閉じる
:
:

// Excelのハンドルを取得
// シートオープン時にFindWindowを使用すると、キャプションにシート名が
// 入ってしまい、不安定になるので、シートを閉じた後で行う
HWND hWnd = ::FindWindow(XLMAIN, SetCaptionSample);
if (hWnd == NULL) {
return;
}

// プロセスIDを取得
DWORD dwProcessId;
GetWindowThreadProcessId(hWnd , &dwProcessId);

// ハンドルの取得
HANDLE hSnap;
hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
// ハンドルがエラー値の場合
if (hSnap == INVALID_HANDLE_VALUE) {
return;
}

// 全てのプロセスをチェックする
BOOL bResult = Process32First(hSnap, &pe);
while(bResult){
// 次を取得
bResult = Process32Next(hSnap, &pe);
// EXCELでプロセスIDが同じ場合
if (!strcmp(pe.szExeFile, EXCEL.EXE)
         && dwProcessId ==pe.th32ProcessID) {
// プロセスIDからハンドルの取得
HANDLE hProcess = OpenProcess(
PROCESS_ALL_ACCESS,
FALSE,
pe.th32ProcessID);

// EXCELを破棄
TerminateProcess(hProcess, 0);

// プロセスを閉じる
DWORD dwExitCode = 0;
GetExitCodeProcess(hProcess, &dwExitCode);
CloseHandle(hProcess);
}
}

CloseHandle(hSnap);


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました