QA@IT
この質問・回答は、@IT会議室からインポートされたものです。

VB.NETからEXCELファイルの起動と終了について

0 PV

VB.NETからExcelファイルの起動,終了を行うプログラムを
インターネット上の情報を元に作成を行っています。
下記のソースを実行すると、見た目はExcelは終了しているのですが
タスクマネジャーを見るとEXCEL.EXEがプロセスとして残っています。
何処が悪く、プロセスが消えないのか良く分かりません。
何方か原因,対策を御願いします。

Sub TestExcRunEnd()
Dim xlApplication As New Excel.Application
Dim xlBooks As Excel.Workbooks = xlApplication.Workbooks
xlBooks.Open("C:\test\VBNET.xls")
xlApplication.Visible = True
System.Threading.Thread.Sleep(1000)
'
xlApplication.Quit()
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBooks)
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApplication)
End Sub

投稿者: morimori

回答

>>15
> 原因は、デバッグモードで実行していた為と思われます

少なくとも私の環境はデバッグモードかどうかに寄らず、
morimoriさんのNo.7の投稿のコードでExcelのプロセスは残りませんでした。

環境は、Windows Vista SP1、Excel2007(Microsoft Excel 12.0 Object Library)です。

ところで、No.7のコードでは、
xlBooksのCloseメソッドが呼ばれていないようですが、この辺が影響していたりしないでしょうか。

投稿者: よねKEN

編集 履歴 (0)

EXCEL.EXEが消えました。

原因は、デバッグモードで実行していた為と思われます。
紹介されたC#の事例の中にデバッグモードという言葉があったもので
もしやと思い、デバッグ無しで実行してみましたら、上手くいきました。

この現象は、常識の内容なのでしょうか?
自分では、デバッグで動かし、1行1行確認を行っていく動作が普通だったもので。

アドバイス、有り難う御座いました

投稿者: morimori

編集 履歴 (0)

上記手順を、Visual Studio 2002で行っても同様の結果が出ました。

投稿者: King

編集 履歴 (0)

EXCEL.EXE が消えないというのは、良く聞く現象なのですが、同じコードでも起きる環境と起きない環境があるらしく、なぜこのような違いがあるのかが不思議です。

ちなみに C# ですが最近の似たような事例を紹介します。
http://ap.atmarkit.co.jp/bbs/core/fdotnet/14962
http://ap.atmarkit.co.jp/bbs/core/fdotnet/13832

推理ですが、Excel に限らずソフトウェア関連の話題で環境によって挙動が異なることを掲示板でいろいろ話していると、最後にはウィルス対策ソフトウェア(やウィルスそのもの)による影響だと分かった、というのが最近増えてきました。ウィルス対策ソフトウェアが空気のようになっていて、なかなかその存在に気付きにくくなってきています。
もしかしたら EXCEL.EXE の件もそういうことなのかな?と最近思うようになりました。

投稿者: unibon

編集 履歴 (0)

詳細にはどのように確認しましたか。
こちらでは下記のように確認しました。
同じ操作をして同様の現象が起こるか試してください。

【環境】
Windows XP SP2
Visual Studio 2005 SP1
Microsoft Excel 2002 SP3

1.VS2005で「Windowsアプリケーション」のプロジェクトを新規作成する。

2.「参照の追加」で「COM」タブの「Microsoft Excel 10.0 Object Library」を追加する。

3.フォームにボタンを貼り付けて、イベントハンドラに下記の定義をする。

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim xlApplication As New Excel.Application
    Dim xlBooks As Excel.Workbooks = xlApplication.Workbooks
    xlApplication.Visible = True
    System.Threading.Thread.Sleep(1000)
    xlApplication.Quit()
    System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBooks)
    System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApplication)
End Sub

4.タスクマネージャを開き「プロセス」タブで「イメージ名」でソートし「EXCEL.EXE」のプロセスが無いことを確認する。

5.プロジェクトをデバッグ実行し、先ほど張り付けたボタンをクリックする。

6.実行中はタスクマネージャに「EXCEL.EXE」が表示されるが、実行終了時には消えている。

投稿者: King

編集 履歴 (0)

>こちらではxlBooksを追加したコードでもプロセスは消えています。
私の環境では、EXCEL.EXEが残ってしまいます。

>まさか実行する前からプロセスが残っていたからって事はないですよね。
私も、何かゴミが考えられると思い、PCのリブート後直ぐに実行してみましたが
状況に変わりません。

私の環境に問題があるのでしょうか?
VB.NETは2002,EXCELは2003です。

どの様にして良いのか、分からなくなってしまいました。

投稿者: morimori

編集 履歴 (0)

こちらではxlBooksを追加したコードでもプロセスは消えています。
まさか実行する前からプロセスが残っていたからって事はないですよね。

投稿者: King

編集 履歴 (0)

下記の最小のソースの場合は、実行後にEXCEL.EXEは消えました。
Dim xlApplication As New Excel.Application
xlApplication.Visible = True
System.Threading.Thread.Sleep(1000)
xlApplication.Quit()
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApplication)

但し、xlBooksをソースに追加すると、実行後にEXCEL.EXEは消えなくなります。
Dim xlApplication As New Excel.Application
Dim xlBooks As Excel.Workbooks = xlApplication.Workbooks
xlApplication.Visible = True
System.Threading.Thread.Sleep(1000)
xlApplication.Quit()
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBooks)
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApplication)

因みに、このソースの実行以外は何も行っていません。
何故、この様な現象になるのか分かりません。

宜しく御願いします

投稿者: morimori

編集 履歴 (0)

提示されているコードで、希望する動作はできますよ
こちらのほうでも確認できました

必要最低限のコードで試されたらどうでしょう?

Imports Microsoft.Office.Interop

Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim xlApplication As New Excel.Application

        xlApplication.Visible = True
        System.Threading.Thread.Sleep(1000)

        xlApplication.Quit()
        System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApplication)
    End Sub

End Class

#あと気になるのは、ファイルを開いてから何か操作していませんか?

投稿者: AlexSuns

編集 履歴 (0)

申し訳ありません。
私の勘違いで、xlBooks = xlApplication.Workbooks が抜けてしまったようです。
行の追加でエラーは発生しなくなりましたが、
下記のソースを実行してもEXCEL.EXEが残ったままとなります。
何故残るのかお分かりでしょうか。

Dim xlApplication As New Excel.Application
Dim xlBooks As Excel.Workbooks
Dim xlBook As Excel.Workbook
xlBooks = xlApplication.Workbooks
xlBook = xlBooks.Open("C:\VBNET.xls")

xlApplication.Visible = True
System.Threading.Thread.Sleep(1000)
'
xlBook.Close(False)
xlApplication.Quit()
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBook)
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBooks)
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApplication)
GC.Collect()

宜しく御願いします

投稿者: morimori

編集 履歴 (0)

該当箇所以外もコードが色々変わってませんか?

xlBooks = xlApplication.Workbooks

が消えているのがとりあえず原因だと思いますが。

投稿者: King

編集 履歴 (0)

'System.NullReferenceException'のハンドルされていない例外が発生しました。
追加情報:オブジャクト参照がオブジェクトインスタンスに設定されていません

エラー内容のとおり、「xlBooks」がインスタンス化されていないとおもわれます

投稿者: AlexSuns

編集 履歴 (0)

'System.NullReferenceException'のハンドルされていない例外が発生しました。
追加情報:オブジャクト参照がオブジェクトインスタンスに設定されていません
とのエラーが、下記の○行で発生します。
何故、エラーが出るのか教えていただけませんでしょうか。

Dim xlApplication As New Excel.Application
Dim xlBooks As Excel.Workbooks
Dim xlBook As Excel.Workbook
○xlBook = xlBooks.Open("C:\nexus_test\VBNET.xls")

xlApplication.Visible = True
System.Threading.Thread.Sleep(1000)
'
xlApplication.Quit()
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBook)
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBooks)
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApplication)
GC.Collect()

投稿者: morimori

編集 履歴 (0)
xlBooks.Open("C:\VBNET.xls")

で開いたものを代入して開放して無いのがなんとなく怪しいと思ったので、

Dim xlTest As Excel.Workbook

と宣言し

xlTest = xlBooks.Open("C:\VBNET.xls")

と書き換え、Sleepの直後に

xlTest.Close(False)
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlTest)

とするとプロセスが消えました。

投稿者: King

編集 履歴 (0)

>Workbooks.Open から返される Workbook オブジェクトに対する Marshal.Release>ComObject が不足しているからでしょう。

下記のソースに修正を行ってみましたが、現象は変わりませんでした。
Hongliangさんの言われている内容と私が行った内容は違うのでしょうか?

Dim xlApplication As New Excel.Application
Dim xlBooks As Excel.Workbooks
Dim xlbook As Excel.Workbook

xlBooks = xlApplication.Workbooks
xlBooks.Open("C:\VBNET.xls")
xlApplication.Visible = True
System.Threading.Thread.Sleep(1000)
'
For Each xlbook In xlBooks
xlbook.Close(False)
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlbook)
xlbook = Nothing
Next
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBooks)
xlBooks = Nothing
xlApplication.Quit()
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApplication)
xlApplication = Nothing
GC.Collect()

投稿者: morimori

編集 履歴 (0)

Workbooks.Open から返される Workbook オブジェクトに対する Marshal.ReleaseComObject が不足しているからでしょう。

投稿者: Hongliang

編集 履歴 (0)
ウォッチ

この質問への回答やコメントをメールでお知らせします。