- PR -

DebugだとExcelが終了しない

1
投稿者投稿内容
らら
常連さん
会議室デビュー日: 2005/01/21
投稿数: 28
お住まい・勤務地: 埼玉県
投稿日時: 2005-12-16 18:13
いつも参考にさせていただいています。

ASP.netのVBでExcelファイルを作るプログラムを作成しています。
過去ログを参考にして作成し、無事にファイルが作成されることは確認できました。

しかし、Release版で実行すると問題ないのですが、
Debug版で1ステップづつ進めていきプログラムを終了すると
Excel.EXEがタスクに残ってしまい作成したExcelファイルを開くことができません。

Debug版だと動作が変わるのでしょうか?
ご存知の方、是非ご教授お願いします。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-12-16 18:29
引用:

ららさんの書き込み (2005-12-16 18:13) より:

Debug版で1ステップづつ進めていきプログラムを終了すると
Excel.EXEがタスクに残ってしまい作成したExcelファイルを開くことができません。


ソースを出して頂けませんか?

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
らら
常連さん
会議室デビュー日: 2005/01/21
投稿数: 28
お住まい・勤務地: 埼玉県
投稿日時: 2005-12-19 10:52
じゃんぬねっとさん
早速のご返信ありがとうございました。

ソースは以下となっております。
Public Class CMakeFile

Public Function NewEx(ByRef fileName As String)

Dim strNewFile As String

'================== 起動時の処理 ===================
Dim xlApp As New Excel.Application
Dim xlBooks As Excel.Workbooks = xlApp.Workbooks

Dim xlFilePath As String = "D:\test.xls"
Dim xlBook As Excel.Workbook = xlBooks.Open(xlFilePath)
Dim xlSheets As Excel.Sheets = xlBook.Worksheets
Dim xlSheet As Excel.Worksheet = xlSheets.Item(1)
xlApp.Visible = False

'================== データの入力処理 ==================
Dim xlCells As Excel.Range
Dim xlRange1 As Excel.Range
xlCells = xlSheet.Cells

xlRange1 = xlCells(1, 12)
xlRange1.Value = "テストデータ"
MRComObject(xlRange1)
MRComObject(xlCells)

'================== ファイルの保存処理 ==================
strNewFile = "D:\test_tmp.xls"
xlApp.DisplayAlerts = False
xlSheet.SaveAs(strNewFile)
xlApp.DisplayAlerts = True

'================== 終了処理 =====================
MRComObject(xlSheet) 'xlSheet の開放
MRComObject(xlSheets) 'xlSheets の開放
xlBook.Close(False) 'xlBook を閉じる
MRComObject(xlBook) 'xlBook の開放
MRComObject(xlBooks) 'xlBooks の開放
xlApp.Quit() 'Excelを閉じる
MRComObject(xlApp) 'xlApp を開放

fileName = strNewFile
End Function

Private Sub MRComObject(ByRef objCom As Object)
Try
System.Runtime.InteropServices.Marshal.ReleaseComObject(objCom)
Catch
Finally
objCom = Nothing
End Try
End Sub

End Class

呼出し元では、CMakeFileをNewしてNewExメソッドを呼び出しています。

じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-12-19 11:48
ソースを拝見しました。
正常動作時 "では" 問題なさそうですね。

引用:

ららさんの書き込み (2005-12-16 18:13) より:

Debug版で1ステップづつ進めていきプログラムを終了すると
Excel.EXEがタスクに残ってしまい作成したExcelファイルを開くことができません。


自動式ウォッチが働いて参照カウントが増えているせいだと思います。
ステップ実行時の自動式ウォッチ絡みをすべて非表示にしてみてください。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-12-19 12:02
現状のコードですと、途中で例外が発生した場合に解放できなくなります。

以下のように Try 〜 Finally による実装にすべきだと思います。
参照する必要がなくなった時点で参照を解放してください。

コード:

Public Class Form1
 _______________________
| Windows フォーム デザイナで生成されたコード |
  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
    Private Sub Button1_Click(...) Handles Button1.Click
        Dim stReturn As String = CMakeFile.NewEx()

        MessageBox.Show(stReturn)
    End Sub

End Class

Public Class CMakeFile 

    Public Shared Function NewEx() As String
        Dim xlApp As New Excel.Application()

        Try
            Dim xlBooks As Excel.Workbooks = xlApp.Workbooks

            Try
                Dim xlFilePath As String = "D:\\test.xls"
                Dim xlBook     As Excel.Workbook = xlBooks.Open(xlFilePath)

                Try
                    Dim xlSheets As Excel.Sheets = xlBook.Worksheets

                    Try
                        Dim xlSheet As Excel.Worksheet = DirectCast(xlSheets(1), Excel.Worksheet)

                        Try
                            Dim xlCells As Excel.Range = xlSheet.Cells                    

                            Try
                                Dim xlRange1 As Excel.Range = DirectCast(xlCells(1, 12), Excel.Range)

                                Try
                                    xlRange1.Value = "テストデータ"
                                Finally
                                    If Not xlRange1 Is Nothing Then
                                        System.Runtime.InteropServices.Marshal.ReleaseComObject(xlRange1)
                                    End If
                                End Try
                            Finally
                                If Not xlCells Is Nothing Then
                                    System.Runtime.InteropServices.Marshal.ReleaseComObject(xlCells)
                                End If
                            End Try

                            Dim strNewFile As String = "D:\\test_tmp.xls"

                            xlApp.DisplayAlerts = False
                            xlSheet.SaveAs(strNewFile)
                            xlApp.DisplayAlerts = True

                            Return strNewFile
                        Finally
                            If Not xlSheet Is Nothing Then
                                System.Runtime.InteropServices.Marshal.ReleaseComObject(xlSheet)
                            End If
                        End Try
                    Finally
                        If Not xlSheets Is Nothing Then
                            System.Runtime.InteropServices.Marshal.ReleaseComObject(xlSheets)
                        End If
                    End Try
                Finally
                    If Not xlBook Is Nothing Then
                        Try
                            xlBook.Close()
                        Finally
                            System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBook)
                        End Try
                    End If
                End Try
            Finally
                If Not xlBooks Is Nothing Then
                    Try
                        xlBooks.Close()
                    Finally
                        System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBooks)
                    End Try
                End If
            End Try
        Finally
            If Not xlApp Is Nothing Then
                Try
                    xlApp.Quit()
                Finally
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp)
                End Try
            End If
        End Try
    End Function

End Class

  • Try 〜 Finally で実装することにより、確実に解放が行われます。
    また、スコープが明確になるため、他のブロックで誤って参照してしまうことを防ぎます。
  • CMakeFile の構成を存じないのですが、
    この NewEx メソッドは、共有メソッドの方が良いと思います。
  • Function の使い方に誤りがあります。
    参照渡しを使って戻り値を返すのではありません。
  • Function の戻り値の型が宣言されていません。
    Option Strict を On にしておけば、戻り値の型宣言の忘れを防ぐことができます。
  • せっかく Function にしているのですから、メソッドから戻り値を返しましょう。
  • 変数は使う直前に宣言と初期化を同時に行いましょう。
# 長文すいません。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
らら
常連さん
会議室デビュー日: 2005/01/21
投稿数: 28
お住まい・勤務地: 埼玉県
投稿日時: 2005-12-19 12:14
じゃんぬねっとさん
ご丁寧に全てのご指摘ありがとうございます。

先ほどじゃんぬねっとさんのサイトを見させていただきました。
http://jeanne.wankuma.com/tips/programing/02-releasecom.html

とても参考になりました。今後も活用させていただきます。
1つ1つのご指摘事項を解消して、また結果を報告させていただきます。
ありがとうございます。
らら
常連さん
会議室デビュー日: 2005/01/21
投稿数: 28
お住まい・勤務地: 埼玉県
投稿日時: 2005-12-19 18:46
無事にDebugのときでもエクセルが終了することを確認することができました。

自動式ウォッチを全て閉じることで解決しました。

↑で解決できる理由は、
自動式ウォッチウィンドウが表示されている状態なので
オブジェクトへの参照が残ってしまっているという認識でエクセルが
終了できないでいるということなのでしょうか?

じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-12-19 18:58
引用:

ららさんの書き込み (2005-12-19 18:46) より:

自動式ウォッチウィンドウが表示されている状態なので
オブジェクトへの参照が残ってしまっているという認識でエクセルが
終了できないでいるということなのでしょうか?


「参照カウントが増えますのでプロセスに居座る」ということです。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
1

スキルアップ/キャリアアップ(JOB@IT)