【VB.NET】Excel作成でプロセスが残ってしまう場合


kuromaku  2004-09-16 00:12:21  No: 116310

いつも参考にさせていただきています。

VisualBasic.NETでExcelファイルを操作するプログラムを作っています。
.NETのCOM連携機能の仕様だからか、マメにMarshal.ReleaseComObject()をしないとExcelのプロセスが残っていまうようなのです。もう少し簡単に書くことはできないでしょうか?

具体的には下記コードで、①だけならプロセスは残らないのですが、続けて②も記述すると、プロセスが残ってしまいます。当然、別変数で扱って、Marshal.ReleaseComObject()すれば大丈夫なんですが、コード量が半端じゃなくなってしまいますので。。。

    Dim xlApp As Excel.Application
    Dim xlBooks As Excel.Workbooks
    Dim xlBook As Excel.Workbook
    Dim xlSheets As Object
    Dim xlSheet As Excel.Worksheet
    Dim xlCells As Object
    Dim xlCell As Object
    Dim xlVal As Object

    xlApp = CreateObject("Excel.Application")
    xlBooks = xlApp.Workbooks
    xlBook = xlBooks.Open("C:test.xls")
    xlSheets = xlBook.Worksheets
    xlSheet = xlSheets(1)
    xlCells = xlSheet.Cells

①-------------------------
    xlCell = xlCells(9, 18)
    xlVal = xlCell.Value
    xlVal = "2"
---------------------------

②--------------------------
    xlCell = xlCells(10, 10)
    xlVal = xlCell.Value
    xlVal = "3"
----------------------------

    System.Runtime.InteropServices.Marshal.ReleaseComObject(xlCell)
    System.Runtime.InteropServices.Marshal.ReleaseComObject(xlCells)
    System.Runtime.InteropServices.Marshal.ReleaseComObject(xlSheet)
    System.Runtime.InteropServices.Marshal.ReleaseComObject(xlSheets)
    System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBook.Worksheets)
    System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBook)
    System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBooks)


魔界の仮面弁士  2004-09-16 11:07:15  No: 116311

こんなblogがありました。最後に3通りのアドバイスがあります。
http://blogs.msdn.com/cbrumme/archive/2003/04/16/51355.aspx

Microsoft側でも、.NET Frameworkの今後のバージョンで、この点を
解決できるような仕組みを作れないか検討されているようですが、
少なくとも現在のバージョンでは、自分で解放処理を書く必要があるかと。

> もう少し簡単に書くことはできないでしょうか?
VBから直接制御するかわりに、VBAを埋め込んだ文書を
VB.NETから開くようにする………というのは駄目ですよね。

# もしくは、Visual Studio Tools for Officeを利用するとか。

> コード量が半端じゃなくなってしまいますので
For Eachの処理などは、特に、解放が面倒になったり…。
http://www.divakk.co.jp/aoyagi/csharp_tips_vssenum.html


kuromaku  2004-09-16 19:16:34  No: 116312

魔界の仮面弁士さん、ありがとうございます。

ラッパークラスを作成してその中で開放する処理を記述して、
コードの簡素化を図ろうかと考えていますが、
実は、他のオブジェクト指向言語では書いたことがあるのですが、
VB.NETでどうやってラッパークラスを作成して良いのか、
さっぱりわかりません。。。

VB.NETでラッパークラスを作成する場合はどうしたら良いでしょうか?

VB.NETの「Inherits」というのはJavaやC++で言う、「extends」宣言に当たるのでしょうか?

例えば、上記サンプルコード中のExcel.Workbooksクラス?のラッパークラスを作成する場合、

Inherits Excel.Workbooks
Public Class XlApp

End Class

と記述すると「名前空間のステートメントが無効」と言われてしまいます。


特攻隊長まるるう  2004-09-18 02:50:45  No: 116313

Inherits を使った継承に関しては過去ログ検索『Inherits』
で色々引っかかると思います。サンプルも載せてあります。
http://madia.world.coocan.jp/cgi-bin/VBBBS2/wwwlng.cgi?print+200408/04080006.txt

>名前空間のステートメントが無効
は書式が間違ってるので…書くとしたら
Public Class XlApp
    Inherits Excel.Workbooks
End Class
ですが、そもそもクラスでないと継承できませんので
Public Class XlApp
    Inherits Excel.ApplicationClass
End Class
ですかねぇ?。でもこの継承は…やった事無いので
何が起こるか予想が付きません。

同じような処理をクラスにして再利用するだけなら、
継承なんかしなくても、普通にクラスを作って関数で
対応できると思いますが?。


魔界の仮面弁士  2004-09-18 03:30:08  No: 116314

> ラッパークラスを作成してその中で開放する処理を記述して、
> コードの簡素化を図ろうかと考えていますが、

アンマネージリソースを解放させるためのラッパーを作る場合には、
『IDisposable インターフェイス』を実装させるのが一般的です。
(IDisposableには、Disposeというメソッドだけが定義されています)

Disposeメソッドに、アンマネージリソースの解放処理を書いておけば、
呼び出し側は、最後にDisposeメソッドを明示的に呼ぶだけで済みます。

また、IDisposableインターフェイスを実装する場合は、Disposeメソッドが
呼び出されなかった場合に備えて、Finalizeメソッドも実装するようにします。

なお、ラッパークラス側の実装としては、親オブジェクトがDisposeされたら、
子オブジェクトも連鎖的にDisposeさせるようにします。こうすれば、
オブジェクトが残ってしまうことはありません。

# ただ、それを実現させるためには、常に親階層のクラスが、
# 子階層のクラスを管理し続けなければなりませんけれどね。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加