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

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

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

COMオブジェクトの解放について


(過去ログ 5 を表示中)

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

■5507 / inTopicNo.1)  COMオブジェクトの解放について
  
□投稿者/ fuji 二等兵(1回)-(2006/08/15(Tue) 15:16:39)

分類:[C#] 


分類:[C#] 

xlBooks.Add()なら問題なくプロセスが終了するのですが、
既存ファイルをオープンするとプロセスが残ります。
思いついたこと(解放し忘れや順番など)は大体試したのですが
解決しません。また、ここのサンプル(下のもの)をそのままコピーしても
同様の問題が発生します。どのような原因が考えられるでしょうか。
よろしくおねがいします。
http://jeanne.wankuma.com/tips/excel/openbook.html

0
引用返信 編集キー/
■5508 / inTopicNo.2)  Re[1]: COMオブジェクトの解放について
□投稿者/ fuji 二等兵(2回)-(2006/08/15(Tue) 15:18:19)

分類:[C#] 

分類はvb.net(2003)でした。すいません。

0
引用返信 編集キー/
■5509 / inTopicNo.3)  Re[1]: COMオブジェクトの解放について
□投稿者/ 通りすがり 二等兵(5回)-(2006/08/15(Tue) 15:59:46)

分類:[C#] 

No5507に返信(fujiさんの記事)
> xlBooks.Add()なら問題なくプロセスが終了するのですが、
> 既存ファイルをオープンするとプロセスが残ります。
> 思いついたこと(解放し忘れや順番など)は大体試したのですが解決しません。
実際に何をやったのか書かないと超能力者じゃない限りわかんないよね。
とりあえずコードもでてないので答えられようがないかと。

> また、ここのサンプル(下のもの)をそのままコピーしても
> 同様の問題が発生します。どのような原因が考えられるでしょうか。
> よろしくおねがいします。
それは変だ。他のところでリークしてるんじゃないのかな。

0
引用返信 編集キー/
■5510 / inTopicNo.4)  Re[2]: COMオブジェクトの解放について
□投稿者/ fuji 二等兵(3回)-(2006/08/15(Tue) 16:17:25)

分類:[C#] 

コードを載せます。
やったことはtry-finalyの使用、毎回nothingにする、object型を使わない
です。
よろしくお願いします。*killp は苦肉の策です。



Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim filepath As String = Application.StartupPath & "\test.xls"
Dim objExcelApp As Excel.Application
Dim objBooks As Excel.Workbooks
Dim objBook As Excel.Workbook
Dim objSheet As Excel.Worksheet
Dim objSheets As Excel.Sheets
Dim xlRng As Excel.Range
Dim xlCells As Excel.Range

objExcelApp = DirectCast(CreateObject("Excel.Application"), Excel.Application)

Dim dr As DataRow
Dim k As Long 'ループカウンタ
Dim drlength As Long = DS().Rows.Count() - 1 'ループカウンタ終点
Dim d As Long = 3

Try
With objExcelApp
.Visible = True
.DisplayAlerts = False
objBooks = .Workbooks
objBook = objBooks.Open(filepath)
'objBook = objBooks.Add
objSheets = objBook.Sheets
objSheet = DirectCast(objSheets("test1"),excel.Worksheet)
'objSheet = objSheets.Item(1)
With objSheet

For k = 0 To drlength
dr = DS().Rows(k)
xlCells = objSheet.Cells

xlRng = xlCells(d, 2)
xlRng.Value = dr.Item("testID")
MarshalOBJ(xlRng)

xlRng = xlCells(d, 4)
xlRng.Value = dr.Item("testtext")
MarshalOBJ(xlRng)

xlRng = xlCells(d, 6)
xlRng.Value = dr.Item("createdt")
MarshalOBJ(xlRng)
MarshalOBJ(xlCells)

'.Cells(d, 2) = dr.Item("testID")
'.Cells(d, 4) = dr.Item("testtext")
'.Cells(d, 6) = dr.Item("createdt")
d = d + 1
Next
.SaveAs(fileName:="C:\" & Me.Name & ".xls")
End With
.DisplayAlerts = True
End With
Finally

If Not xlRng Is Nothing Then
MarshalOBJ(xlRng)
End If

If Not xlCells Is Nothing Then
MarshalOBJ(xlCells)
End If

Try
objExcelApp.Quit()
Marshal.ReleaseComObject(objExcelApp)

objBook.Close(False)
MarshalOBJ(objBook)
objBooks.Close()
MarshalOBJ(objBooks)
MarshalOBJ(objSheet)
MarshalOBJ(objSheets)
Catch
'killp()
Finally
GC.Collect()
End Try
MessageBox.Show("ファイルを作成し、保存しました。")

End Sub
'データテーブル作成
Function DS() As DataTable
Dim mysql As String
Dim mydataset As DataSet
mysql = "select testID,testtext,createdt,updatedt,userID from tabletest100"
mydataset = websvc1.TestDataSet(mysql)
Return mydataset.Tables("table")
End Function
'COMオブジェクト解放
Private Sub MarshalOBJ(ByRef objCom As Object)
Try
Marshal.ReleaseComObject(objCom)
Finally
objCom = Nothing
End Try
End Sub
'プロセス強制終了
Sub killp()
Dim localByName As Process() = Process.GetProcessesByName("Excel")
Dim p As Process
Dim fn As String = ""
For Each p In localByName
If System.String.Compare(p.MainWindowTitle, fn) = 0 Then
p.Kill()
End If
Next
End Sub

0
引用返信 編集キー/
■5512 / inTopicNo.5)  Re[3]: COMオブジェクトの解放について
□投稿者/ 通りすがり 二等兵(6回)-(2006/08/15(Tue) 17:04:22)

分類:[C#] 

コンパイルエラー。正しく転記しようよ。
Sub killp()とかって何?

COMなだけにWithとか使用しないほうがいいなあ。

0
引用返信 編集キー/
■5516 / inTopicNo.6)  Re[4]: COMオブジェクトの解放について
□投稿者/ fuji 二等兵(4回)-(2006/08/15(Tue) 17:21:43)

分類:[C#] 

webserviceを使っているのをそのまま載せてしまいました。
Dim drlength As Long = DS().Rows.Count() - 1 'ループカウンタ終点
を削除して
for-next文を以下のように上書きコピーしてください。
killp()は気にしないでください・・・

withのところは修正してみます
For k = 0 To 2
xlCells = objSheet.Cells

xlRng = xlCells(d, 2)
xlRng.Value = "1"
MarshalOBJ(xlRng)

xlRng = xlCells(d, 4)
xlRng.Value = "2"
MarshalOBJ(xlRng)

xlRng = xlCells(d, 6)
xlRng.Value = "3"
MarshalOBJ(xlRng)
MarshalOBJ(xlCells)

d = d + 1
Next

0
引用返信 編集キー/
■5528 / inTopicNo.7)  Re[5]: COMオブジェクトの解放について
□投稿者/ 通りすがり 二等兵(7回)-(2006/08/15(Tue) 21:05:57)

分類:[C#] 

No5516に返信(fujiさんの記事)
> For k = 0 To 2
> xlCells = objSheet.Cells
>
> xlRng = xlCells(d, 2)
> xlRng.Value = "1"
> MarshalOBJ(xlRng)
>
> xlRng = xlCells(d, 4)
> xlRng.Value = "2"
> MarshalOBJ(xlRng)
>
> xlRng = xlCells(d, 6)
> xlRng.Value = "3"
> MarshalOBJ(xlRng)
> MarshalOBJ(xlCells)
>
> d = d + 1
> Next

返事遅くなってごめんね。
本当にこの部分が原因かなぁ。
この部分だけコメントアウトして実行とかしてみて、ここだとわかったわけ?
だとすると、MarshalOBJメソッドが怪しいなぁ。

0
引用返信 編集キー/
■5536 / inTopicNo.8)  Re[6]: COMオブジェクトの解放について
□投稿者/ fuji 二等兵(5回)-(2006/08/16(Wed) 09:09:57)

分類:[C#] 

返信ありがとうございました
ここが原因なのは間違いないです。
ひょっとしてEXCELが原因ということはあり得るのでしょうか。

0
引用返信 編集キー/
■5537 / inTopicNo.9)  Re[3]: COMオブジェクトの解放について
□投稿者/ 魔界の仮面弁士 少尉(124回)-(2006/08/16(Wed) 09:16:47)

分類:[C#] 

2006/08/16(Wed) 09:17:10 編集(投稿者)

# とりあえず、机上デバッグのみで回答。実際に試してはいません。m(_ _)m


現時点では、暗黙型変換による解放漏れの可能性を防ぐためにも、
問題点を特定できるまでは Option Strict On を指定しておいたほうが
良いかと思います。ただし On にすると、現状のコードでは
MarshalOBJ メソッドの部分でコンパイルエラーが予想されますけれども。


> objExcelApp = DirectCast(CreateObject("Excel.Application"), Excel.Application)

あれ。なぜ、あえて CreateObject を使用しているのでしょう?


> For k = 0 To drlength
>  xlCells = objSheet.Cells
>   :
>   :
>  MarshalOBJ(xlCells)
> Next

ループ中で何度も Cells を取り直さずとも、
xlCells = objSheet.Cells
For k = 0 To drlength
  :
Next
MarshalOBJ(xlCells)
で十分なのでは。


> .SaveAs(fileName:="C:\" & Me.Name & ".xls")

ここで使っているのは、objBook.SaveAs ではなく objSheet.SaveAs なのですね。


> Try
>  objExcelApp.Quit()
>  Marshal.ReleaseComObject(objExcelApp)
>  objBook.Close(False)
>  MarshalOBJ(objBook)
>  objBooks.Close()
>  MarshalOBJ(objBooks)
>  MarshalOBJ(objSheet)
>  MarshalOBJ(objSheets)
> Catch

解放するのであれば、下位のオブジェクトから順に行った方が良いでしょう。
つまり、Sheet → Sheets → Workbook → Workbooks → Application の順で。

0
引用返信 編集キー/
■5539 / inTopicNo.10)  Re[4]: COMオブジェクトの解放について
□投稿者/ 中博俊 神(646回)-(2006/08/16(Wed) 09:33:12)
中博俊 さんの Web サイト

分類:[C#] 

>ひょっとしてEXCELが原因ということはあり得るのでしょうか。

ありえません。

とりあえず該当部分をコメントアウトしたら消えるのは確かですか?

0
引用返信 編集キー/
■5540 / inTopicNo.11)  Re[5]: COMオブジェクトの解放について
□投稿者/ fuji 二等兵(6回)-(2006/08/16(Wed) 09:47:46)

分類:[C#] 

魔界の仮面弁士様
解放の順番を変えるのとxlcellsの解放を一回にするのとブックを保存するように
変更をしてみましたがだめでした。
明示的型変換をするように変更してみます。

中博俊様
間違いありません。また現状のコードでも新規ブックに書き込むようにすると
プロセスは残りません。

0
引用返信 編集キー/
■5541 / inTopicNo.12)  Re[6]: COMオブジェクトの解放について
□投稿者/ 魔界の仮面弁士 少尉(125回)-(2006/08/16(Wed) 10:32:23)

分類:[C#] 

うーん。先に書いたように、細かい点で気になる所はありますが、
今のところ、大きな問題は見当たらないですね。

MarshalOBJ(foo) を呼ぶのではなく、そのまま素直に
Marshal.RelaseComObject(foo) を呼んだ場合も駄目ですか?

> 明示的型変換をするように変更してみます。

Private Sub MarshalOBJ(ByRef objCom As Object) の部分について気になる点。

1. 引数自体は、ByVal でも十分だと思います。
2. というより、ByRef Object だと、Option Strict On の場合にエラーです。
3. Nothing 代入は必ずしも必要ではありません。RelaseComObject の方が大事。
4. 念のため、Try 部でエラーを捕らえていないか確認しておきましょう。
5. どうせなら、IsNothing 判定と IsComObject 判定も行うとベターかも。
6. 特定条件下においては、暗黙の参照カウント増加が発生する場合があるので、
RelaseComObject の戻り値が 0 か否かもついでに判定してみましょう。


今回のケースで、6. に相当する状況が発生しているかは不明ですが、以前、

 'アーリーバインディング
 Dim oRange As Excel.Range = 〜〜
 Dim Hs As Excel.HPageBreaks = oWorksheet.HPageBreaks
 Dim H As Excel.HPageBreak = Hs.Add(oRange) '改ページ挿入

 'レイトバインディング
 Dim oRange As Object = 〜〜
 Dim Hs As Object = oWorksheet.HPageBreaks
 Dim H As Object = Hs.Add(oRange) '改ページ挿入

の 2 種の同等なコードにおいて、後者の場合のみ、Add メソッドの実行後に
Marshal.ReleaseComObject(oRange) の戻り値が 1 になってしまい、結果、
oRange を 2 回 ReleaseComObject しないと終了しなかった経験があります。
http://hpcgi1.nifty.com/MADIA/VBBBS2/wwwlng.cgi?print+200512/05120042.txt


> 間違いありません。また現状のコードでも新規ブックに書き込むようにすると
> プロセスは残りません。
聞いた話では、VBA コードや Excel アドインその他の理由によって、
オブジェクトの解放が即座に行われない(あるいは阻害される)という現象が
おきる事があるらしいですが、当方には該当のブックが無いので検証できません。

もし、公開して差し支えない物であれば、問題の test.xls と、その検証用の
最小限のコードを zip/lzh 圧縮して、ここに載せてみては如何でしょう。

0
引用返信 編集キー/
■5548 / inTopicNo.13)  Re[7]: COMオブジェクトの解放について
□投稿者/ fuji 二等兵(7回)-(2006/08/16(Wed) 11:22:24)

分類:[C#] 

魔界の仮面弁士様。
もしやと思い、test.xlsを作り直したところ、正常に動作しました。
(原因が何だったのかよく分からないのですが・・)

お答えいただいた皆様ありがとうございました。

解決済み
引用返信 編集キー/
■5550 / inTopicNo.14)  Re[7]: COMオブジェクトの解放について
□投稿者/ じゃんぬ @ 管理人 少将(253回)-(2006/08/16(Wed) 11:28:12)

分類:[C#] 

皆さま、こんにちは。
じゃんぬ @ 一応管理人です。

完全に出遅れましたけども...

No5541に返信(魔界の仮面弁士さんの記事)
> 今回のケースで、6. に相当する状況が発生しているかは不明ですが、以前、
> 'アーリーバインディング
> 'レイトバインディング
> の 2 種の同等なコードにおいて、後者の場合のみ、Add メソッドの実行後に
> Marshal.ReleaseComObject(oRange) の戻り値が 1 になってしまい、結果、
> oRange を 2 回 ReleaseComObject しないと終了しなかった経験があります。

これなんかもそうですね。
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=32241&forum=7

だから、事前バインディングを推奨しているんですけども。

No5548に返信(fujiさんの記事)
> もしやと思い、test.xlsを作り直したところ、正常に動作しました。
> (原因が何だったのかよく分からないのですが・・)

こんなことは私の経験上ありえないです。
何かもともと誤解があったか、何かの拍子に改善したかのどちらかでしょう。

解決済み
引用返信 編集キー/
■5551 / inTopicNo.15)  Re[8]: COMオブジェクトの解放について
□投稿者/ fuji 二等兵(8回)-(2006/08/16(Wed) 11:47:45)

分類:[C#] 

じゃんぬ @ 管人理人様
実際に作り直したtest.xlsは単純なコピーではなく
新規ブックに旧test.xlsのシートを移動しただけの代物で、
実質同じものです。
きっと何か原因があったのだと思います。
もし分かればまた報告しようと思います。
ありがとうございました。

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


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

このトピックに書きこむ

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

管理者用

- Child Tree -