C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[6]: タスクマネージャーに「EXCEL.EXE」が残ってしまいます


(過去ログ 103 を表示中)

[トピック内 12 記事 (1 - 12 表示)]  << 0 >>

■61669 / inTopicNo.1)  タスクマネージャーに「EXCEL.EXE」が残ってしまいます
  
□投稿者/ kaorin (4回)-(2011/08/26(Fri) 13:01:08)

分類:[C#] 

題記の件は「も〜うんざり」って思われる方は多いと思われますが、
私も非常に恐縮しております。
何卒宜しくお願い致します。
【環境:XP_SP3, Excel2003, Visual C# 2010】

大まかな流れ
1.プログラムより対象のエクセルファイルを立ち上げる。
2.立ち上げたエクセルファイルの終了処理をせずにプログラムを終了する。
  (何らかのエラーでプログラムがフリーズし終了した時を想定)
3.再びプログラムを起動
4.プログラム内の「エクセル二重起動チェック」メソッドにて二重起動しようとしている事を検出
5.下の強制終了ソースにてエクセルを終了
6.プログラム終了
と、考えてます。

現在の所、5項により下の強制終了ソースを実行すれば、
1.ブックの終了、アプリケーションの終了は出来ています。
2.しかしタスクマネージャーのプロセスに「EXCEL.EXE」が残ってしまいます。
  (プログラムを終了しても残ります)

その他、
C:\ExcelFile.xlsを手動で開いておいて、プログラムを起動し強制終了メソッドを
実行した場合、正常にブック、アプリの終了およびプロセスからも「EXCEL.EXE」は消えます。

どうぞ、ご教示お願い致します。


//XXXXXXXXXXXXXXXXXXX 強制終了Source XXXXXXXXXXXXXXXXXXX

//開いてるファイルをctrlBookにセットする
Excel.Workbook ctrBook = (Excel.Workbook)Microsoft.VisualBasic.Interaction.GetObject(@"C:\ExcelFile.xls", null);
                
//開いてるファイルのAppをctrAppにセットする
Excel.Application ctrApp = ctrBook.Application;

//ブックを閉じる
ctrBook.Close();

//App終了
ctrApp.Quit();

//COMオブジェクトの開放
Marshal.ReleaseComObject(ctrBook);
ctrBook = null;
Marshal.ReleaseComObject(ctrApp);
ctrApp = null;

//終了
Application.Exit();

//XXXXXXXXXXXXXXXXXXX 強制終了Source XXXXXXXXXXXXXXXXXXX

引用返信 編集キー/
■61674 / inTopicNo.2)  Re[1]: タスクマネージャーに「EXCEL.EXE」が残ってしまいます
□投稿者/ Mira (60回)-(2011/08/26(Fri) 14:11:07)
2.の部分で使用しているExcellのオブジェクトを全部開放しないとタスクから消えないのではないでしょうか?

ソースを見る限りctrBookとctrAppしか開放してないようですが
引用返信 編集キー/
■61675 / inTopicNo.3)  Re[1]: タスクマネージャーに「EXCEL.EXE」が残ってしまいます
□投稿者/ 魔界の仮面弁士 (2335回)-(2011/08/26(Fri) 14:14:58)
No61669 (kaorin さん) に返信
> 題記の件は「も〜うんざり」って思われる方は多いと思われますが、
(^^;

>(何らかのエラーでプログラムがフリーズし終了した時を想定)
try-catch 等を用い、エラー時も極力解放されるようにするのが望ましいのですけれどね。


> 5.下の強制終了ソースにてエクセルを終了
複数の Excel が起動していた場合の対応は十分ですか?
終了させるべき Excel と、そうでない Excel とが混在する可能性はありますか?

> Excel.Workbook ctrBook = (Excel.Workbook)Microsoft.VisualBasic.Interaction.GetObject(@"C:\ExcelFile.xls", null);
GetObject が例外を発生させた場合に備え try-catch は行われていますか?

なお、GetObject を使う代わりに、System.Runtime.InteropServices.ComTypes.IRunningObjectTable で
起動済みの Excel を列挙するという方法もあります。

> ctrBook.Close();
> ctrApp.Quit();
Workbook の解放は、この 2 つの間に配置した方が良いと思います。


> Marshal.ReleaseComObject(ctrBook);
このメソッドの戻り値が 0 であることを確認してみてください。
引用返信 編集キー/
■61679 / inTopicNo.4)  Re[2]: タスクマネージャーに「EXCEL.EXE」が残ってしまいます
□投稿者/ kaorin (5回)-(2011/08/27(Sat) 11:36:04)
2011/08/27(Sat) 11:44:44 編集(投稿者)
2011/08/27(Sat) 11:38:22 編集(投稿者)
2011/08/27(Sat) 11:38:13 編集(投稿者)

<pre><pre>Miraさん、魔界の仮面弁士さん、おはようございます。
どうも返事ありがとうございました。


■Miraさんへ
> 2.の部分で使用しているExcellのオブジェクトを全部開放しないとタスクから消えないのではないでしょうか?

> ソースを見る限りctrBookとctrAppしか開放してないようですが

私の知識と経験では、このctrBookとctrAppの解放しか分かりませんでした。
具体的にご教示頂けたら幸いです。お願い致します。



■魔界の仮面弁士さんへ
> try-catch 等を用い、エラー時も極力解放されるようにするのが望ましいのですけれどね。

はい。行っていますが、そこでもctrBookとctrAppの解放しかやっていません(^^;A


>>5.下の強制終了ソースにてエクセルを終了
> 複数の Excel が起動していた場合の対応は十分ですか?
> 終了させるべき Excel と、そうでない Excel とが混在する可能性はありますか?

具体的にはまだ、他のファイルの複数起動下でのデバックは行っていないのですが、
対象のExcelと他Excelの起動混在はほぼ100%あります。


> なお、GetObject を使う代わりに、System.Runtime.InteropServices.ComTypes.IRunningObjectTable で
> 起動済みの Excel を列挙するという方法もあります。

勉強になります。やってみますね(*^▽^*)〃


>>ctrBook.Close();
>>ctrApp.Quit();
> Workbook の解放は、この 2 つの間に配置した方が良いと思います。

拝承m(_ _)m


>>Marshal.ReleaseComObject(ctrBook);
> このメソッドの戻り値が 0 であることを確認してみてください。

ブレイクポイントで止めて、下記を1行づつ確認しました。
int Ret = Marshal.ReleaseComObject(ctrBook);
Ret = Marshal.ReleaseComObject(ctrApp);
いづれもRetの値は0でした。

お二人方さま、返事ありがとうございました。
引き続き、ご教示頂けますことをお願いいたします。
もの凄く、申し訳なく恐縮しておりますm(_ _)m</pre></pre>
引用返信 編集キー/
■61684 / inTopicNo.5)  Re[3]: タスクマネージャーに「EXCEL.EXE」が残ってしまいます
□投稿者/ 魔界の仮面弁士 (2336回)-(2011/08/27(Sat) 15:26:06)
No61679 (kaorin さん) に返信
> 私の知識と経験では、このctrBookとctrAppの解放しか分かりませんでした。
> 具体的にご教示頂けたら幸いです。お願い致します。

解放の方法は一緒です。Marshal.ReleaseComObject を使います。

Excel を起動し、Alt+F11 で Excel VBA のウィンドウを開いてください。
さらに VBA 画面にて、F2 キーを押し、オブジェクトブラウザの画面を開いてみてください。

そこでクラスオブジェクトのアイコンが付いているものすべてが、解放対象となります。

Excel 制御で用いられるクラスの代表格は、
 Application
 Workbooks
 Workbook
 Sheets / Worksheets
 Worksheet
 Range
あたりです。大抵の場合、これらも利用されることになるはずで、それら全て解放せねばなりません。

上記の他にも、Windows/Window、Names/Name、Borders/Border、Areas、Interior、PageSetup 等々、
数多くのCOMオブジェクトがあります。どれも解放手順は一緒なのですが(Marshal.ReleaseComObject等)、
実際のコードを見てみないことには、何が使われていて、どのオブジェクトを解放し忘れているのか、
どのように修正すればよいのかを指摘することはできません。


> int Ret = Marshal.ReleaseComObject(ctrBook);
> Ret = Marshal.ReleaseComObject(ctrApp);
> いづれもRetの値は0でした。
ということは、Application と Workbook の解放は完了しています。それでも残るのであれば、
Mira さんが指摘されたように、それ以外のオブジェクトについて解放漏れがあるのでしょうね。
引用返信 編集キー/
■61690 / inTopicNo.6)  Re[4]: タスクマネージャーに「EXCEL.EXE」が残ってしまいます
□投稿者/ やじゅ (1951回)-(2011/08/28(Sun) 18:22:03)
やじゅ さんの Web サイト
> ■No61679 (kaorin さん) に返信

将来的に参考になる資料だと思います。

わんくま名古屋#18LT資料「IDisposable を成敗する」
http://blogs.wankuma.com/rudicast/archive/2011/07/10/200902.aspx

引用返信 編集キー/
■61691 / inTopicNo.7)  Re[1]: タスクマネージャーに「EXCEL.EXE」が残ってしまいます
□投稿者/ shu (957回)-(2011/08/28(Sun) 21:15:08)
2011/08/29(Mon) 07:51:26 編集(投稿者)

Application.Quitを実行しているのでたのExcelファイルには影響がないという
前提の上で参照を解放する手段がない場合のみ可能な方法ですが、

Application.Hwndを取得して

[DllImport("user32.dll")]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, ref uint lpdw)
で対応するExcelのProcessIDを取得して

Process.Kill

とかどうでしょう?


# No61695 Azulean さんのご指摘部を追記しました。

引用返信 編集キー/
■61692 / inTopicNo.8)  Re[2]: タスクマネージャーに「EXCEL.EXE」が残ってしまいます
□投稿者/ Azulean (830回)-(2011/08/28(Sun) 22:23:30)
No61691 (shu さん) に返信
> Application.Hwndを取得して
(略)
> Process.Kill
> とかどうでしょう?

ちょっと邪道過ぎませんか?
もし、ユーザーが開いている Excel で開かれるようなことがあったら、巻き込んで殺してしまいます。
本質的な改善が不可能か、相当に困難なら、要件や前提次第ではその手を取ることもできるかもしれませんが、現段階でその手を取るのはやめるべきだと思います。
引用返信 編集キー/
■61693 / inTopicNo.9)  Re[3]: タスクマネージャーに「EXCEL.EXE」が残ってしまいます
□投稿者/ shu (958回)-(2011/08/28(Sun) 22:45:10)
No61692 (Azulean さん) に返信
> ■No61691 (shu さん) に返信
>>Application.Hwndを取得して
> (略)
>>Process.Kill
>>とかどうでしょう?
>
> ちょっと邪道過ぎませんか?
> もし、ユーザーが開いている Excel で開かれるようなことがあったら、巻き込んで殺してしまいます。
Application.Quitしているからその判断は済んでいるものと仮定しています。その判断に間違いがあるのなら
確かにこの処理は駄目かなと思います。Marshal.ReleaseComObject出来なかった参照を探すのは大変かなと思いました。
引用返信 編集キー/
■61695 / inTopicNo.10)  Re[4]: タスクマネージャーに「EXCEL.EXE」が残ってしまいます
□投稿者/ Azulean (831回)-(2011/08/29(Mon) 00:59:12)
No61693 (shu さん) に返信
> Application.Quitしているからその判断は済んでいるものと仮定しています。その判断に間違いがあるのなら
> 確かにこの処理は駄目かなと思います。

なるほど、そういう前提に立っていたわけですね。気づけてませんでした。
できれば、その前提(制約)を明示しておいていただきたいなと思います。鵜呑みにして使い回される恐れがあるためです。


> Marshal.ReleaseComObject出来なかった参照を探すのは大変かなと思いました。

確かに大変かもしれませんが、これはやるべきことだと思います。
大変なのは適当に作ったツケかもしれません。ただ、リークしても後でアプリ終わらせれば OK というやり口は気持ちのよいものではありませんし、場合によってはほかの悪影響があるかもしれませんので。

# Out-process COM のオブジェクトで対象プロセスが殺された場合の参照ってどうなるか調べてないなぁ。
引用返信 編集キー/
■61696 / inTopicNo.11)  Re[5]: タスクマネージャーに「EXCEL.EXE」が残ってしまいます
□投稿者/ shu (959回)-(2011/08/29(Mon) 07:43:48)
No61695 (Azulean さん) に返信

> なるほど、そういう前提に立っていたわけですね。気づけてませんでした。
> できれば、その前提(制約)を明示しておいていただきたいなと思います。鵜呑みにして使い回される恐れがあるためです。
失礼しましたmm No61691 に追記しておきました。



>>Marshal.ReleaseComObject出来なかった参照を探すのは大変かなと思いました。
>
> 確かに大変かもしれませんが、これはやるべきことだと思います。
> 大変なのは適当に作ったツケかもしれません。ただ、リークしても後でアプリ終わらせれば OK というやり口は気持ちのよいものではありませんし、場合によってはほかの悪影響があるかもしれませんので。
>
> # Out-process COM のオブジェクトで対象プロセスが殺された場合の参照ってどうなるか調べてないなぁ。
正直、プロセスがダウンして浮いた参照を取得するの無理なんじゃないかなと思っていたりする。各参照とProcessとの関連付けがあるなら可能かも。


引用返信 編集キー/
■61697 / inTopicNo.12)  Re[6]: タスクマネージャーに「EXCEL.EXE」が残ってしまいます
□投稿者/ kaorin (6回)-(2011/08/29(Mon) 09:32:54)
おはようございます。
みな様、沢山のご意見、ヒントをありがとうございました。
頭をリフレッシュし、冷静に皆さんのアドバイスを踏まえ考えてみると、

そもそも全体の流れは次の通りですが
@ if(エクセルブックの二重起動はあるか?)
{
  @’エクセルブック強制終了
}
AエクセルApp起動
BBooks、Bookをセット
CSheets、Sheetをセット
D何らかのExcel操作
ESheet、Sheets解放
FBook.Close
GBook、Books解放
HApp.Quit
IApplication.Exit

魔界の仮面弁士さんの
>>いづれもRetの値は0でした。
> ということは、Application と Workbook の解放は完了しています。それでも残るのであれば、
> Mira さんが指摘されたように、それ以外のオブジェクトについて解放漏れがあるのでしょうね。

この言葉でハッ!!としました。
当初、強制終了メソッドは、Excelを起動する前に、一番先に実行するメソッドなので、
「ctrBook」と「ctrApp」以外には無いと思っていました。
(結果、ご指摘通り、エラー発生前にセットしたオブジェクトの解放漏れがあります。)

そして私のデバッグ方法に問題があることに気づきました。
それは、
> 2.立ち上げたエクセルファイルの終了処理をせずにプログラムを終了する。
>   (何らかのエラーでプログラムがフリーズし終了した時を想定)

私は、Eの「Sheetの解放」にブレイクポイントを設定した後、デバッグを開始(F5押下)
しばらくすると当然ブレイクポイントで止まります。
そこで、私は「(何らかのエラーでプログラムがフリーズし終了した時を想定)」の為、
デバッグの終了(■ボタン押下)を押し、プログラムを停止、そしてまたデバッグを開始(F5押下)し
二重起動検出〜と言った流れでデバッグしていました。
(当然try-catchに流れ込んで行かず、解放漏れオブジェクトが残っていました)

対策、全てのエクセル操作メソッドを見直しtry-catchで
Sheet、Sheets、Book、Books、Appの解放を行うように記述しました。
これにより、恐らく「強制終了」と言うメソッドはもう必要ないかもしれませんね!!
PS:Renge、Cellsに対しての解放処理を今から追記して行きます。

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -