59269


お世話になります。

C#(.Net4.7.1)で、Accessを間接的に開き、C#のコードからCSVファイルをインポートしようする  
コードを組んでいます。

実際に取り込む部分はできたのですが、終了した後のAccessの終了の仕方、解放の仕方がわかりません。  
理由は、サイト様などからVBで行っている記述を見つけ、コピーしてきてC#に書き直しているのですが、終了間際に『Util.MRComObject(DirectCast(mAccessApp,
Object))』といった、C#では見慣れない部分が出てきてしまい、どう書き直せばいいのか迷っています。

ずばり答えをそのままお尋ねする形になってしまいますが、ご教授いただければ幸いです。

下記がコードです。

[code]

                public static void Import(
                    string mdbFilePath,
                    string csvPath,
                    string tableName,
                    string schemaFile,
                    bool hasFieldNames
                )
                {
                    ' ファイル存在チェック
                    if (!File.Exists(mdbFilePath))
                    {
                        return;
                    }
                    if (!File.Exists(csvPath))
                    {
                        return;
                    }
    
                    try
                    {
    
                        mAccessApp = new Microsoft.Office.Interop.Access.Application();
                        mAccessApp.AutomationSecurity =
                            Microsoft.Office.Core.MsoAutomationSecurity.msoAutomationSecurityLow;  //マクロを有効にして開くように設定
                        mAccessApp.OpenCurrentDatabase(mdbFilePath, false);
    
                        mAccessApp.DoCmd.TransferText(
                            Microsoft.Office.Interop.Access.AcTextTransferType.acImportDelim,
                            schemaFile,
                            tableName,
                            csvPath,
                            hasFieldNames);
    
                        }
                    }
                    catch
                    {
                    }
                    finally
                    {
    
                        if (mAccessApp != null)
                        {
                            mAccessApp.CloseCurrentDatabase();
    
     mAccessApp.Quit(Microsoft.Office.Interop.Access.AcQuitOption.acQuitSaveNone);
    
        　　　　　　　　　　　// ここで行っています。
                            Util.MRComObject(DirectCast(mAccessApp, Object))  
                        }
                    }
                }
    
[/code]

よろしくお願いいたします。


CC BY-SA 4.0
2019-09-25T07:56:10.223
59257
2019-09-26T08:31:10.340
2019-09-25T08:27:24.727
9374
9374
question
c# ms-access
C#でAccessを使用した後の終了方法について


**改訂**  
1つの処理の中で生成から終了まで完結しているなら、メインの処理も含めてもっと簡単に出来ます、という記事を見つけました。(相変わらずExcelがテーマですが)  
`try catch finally` ではなく、`using` を使う方が良いようです。

[アンマネージドリソースをDisposeパターンで管理する](https://days-of-
programming.blogspot.com/2018/04/dispose.html)

>
> ときどき[System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);](https://docs.microsoft.com/ja-
> jp/dotnet/api/system.runtime.interopservices.marshal.releasecomobject?redirectedfrom=MSDN&view=netframework-4.8)の必要性やについての議論や、ひどい場合は「これを書かないからEXCEL.EXEプロセスが残ってしまう」といった誤った記述がされているサイトがありますが注意してください。  
>  [Workbook.Close()](https://docs.microsoft.com/ja-
> jp/dotnet/api/microsoft.office.tools.excel.workbook.close?view=vsto-2017)でワークブックを閉じて、Application.Quit()でアプリケーションを閉じさえすればEXCEL.EXEプロセスは正常に終了されます。Marshal.ReleaseComObjectは、.NETからのCOMオブジェクト（＝Excelを操作するためのインターフェイス）を解放するためのメソッドで、これの有無にかかわらずExcelはしっかりと終了してくれます。  
>  リソースの解放をしたらそれ以降はExcelの操作をしないわけですから、COMオブジェクトを解放しておくべきでしょう。
>
> こうすることで
[code]

>     using(var excel = new ExcelApp(@"test.xlsx")) {
>  
>     }
>  
[/code]

>
>
> このように書くだけで、usingブロックを抜けたときにExcelがしっかりと終了されます。この場合はDispose()メソッドが呼ばれることによりExcelの終了処理が行われていることがわかります。
>
>
> 他にも、敢えてDispose()を呼び出さないようなコードを書いても、ちゃんとアプリケーション終了時にGCがファイナライザを呼び出してExcelが終了されることが分かります。
> このDisposeパターンは確実にアンマネージドリソースを解放する方法として有効でしょう。
>
>
> ※上記のDisposeパターンのプログラムは、Disposeパターンの説明をするために書いているものでExcelを終了させるうえで完璧ではない点に注意してください。例えば、Excelを開いている間にファイルに変更を加え、保存せずにDisposeメソッドが呼ばれるとExcelのメッセージボックスで終了処理がブロックされます。  
>  利用者は、各自アレンジして使ってください。

類似の記事がこれです。  
[確保したリソースを忘れずに解放するには？［C#／VB］](https://www.atmarkit.co.jp/ait/articles/1710/18/news022.html)

* * *

一応マイクロソフトの中の人が、using
とかを使わない素のコーディングの時にはどうすれば良いかを解説した記事があります。それらではしっかりReleaseComObject、nothing/null代入、GC.Collect等も使うように、と書いてあります。  
[Office オートメーションで割り当てたオブジェクトを解放する –
Part1](https://social.msdn.microsoft.com/Forums/ja-
JP/5deec897-a897-404b-a610-f7d894fde1b3/office?forum=officesupportteamja)  
[Office オートメーションで割り当てたオブジェクトを解放する -
Part2](https://social.msdn.microsoft.com/Forums/ja-
JP/0d9c6273-bade-4f6a-a0de-5adb748d15eb/office?forum=officesupportteamja)  
こちらは C# 2005の古い記事です。少し違う形のNAR()も記述されています。  
[完全なサンプル Visual c# 2005 または Visual C# .NET
プロジェクトを作成する](https://docs.microsoft.com/ja-jp/office/troubleshoot/office-
developer/automate-access-using-visual-c#create-the-complete-sample-
visual-c-2005-or-visual-c-net-project)

こうした記事も関連しているでしょう。  
[C# Excel 操作 EXEが残り続ける](https://social.msdn.microsoft.com/Forums/ja-
JP/0f210f52-3667-4e66-9dd6-4480eede48de/c-excel-2580520316-exe123642753112426321541236912427?forum=csharpgeneralja)

英語版StackOverflowだと、想定する使い方の違いか、using への言及は無いようですね。  
[Why use FinalReleaseComObject instead of
ReleaseComObject?](https://stackoverflow.com/q/1827059/9014308)  
[When to use ReleaseComObject vs FinalReleaseComObject?
duplicate](https://stackoverflow.com/q/3937181/9014308)  
[Marshal.ReleaseComObject Considered
Dangerous](https://devblogs.microsoft.com/visualstudio/marshal-
releasecomobject-considered-dangerous/)  
[Understanding garbage collection in
.NET](https://stackoverflow.com/q/17130382/9014308)  
[.NET and COM Interoperability : release COM from .NET
client](https://stackoverflow.com/q/9709141/9014308)  
[How to dispose of Excel.Application class correctly
duplicate](https://stackoverflow.com/q/40359174/9014308)

* * *

以下は最初に **MRComObject** に関して調べた情報です。残しておきます。

色々とたどっていくと、[Marshal.ReleaseComObject(Object)
Method](https://docs.microsoft.com/ja-
jp/dotnet/api/system.runtime.interopservices.marshal.releasecomobject?view=netframework-4.8)を使ったサブルーチンのようです。
`MRComObject`は`Marshal.ReleaseComObject`の短縮形として名付けたのではないでしょうか。

ただし、実際に使うのは [Marshal.FinalReleaseComObject(Object)
Method](https://docs.microsoft.com/ja-
jp/dotnet/api/system.runtime.interopservices.marshal.finalreleasecomobject?view=netframework-4.8)
の方が良いかもしれません。 ReleaseComObject自身の注釈に以下の記述があります。

> したがって、が[ReleaseComObject](https://docs.microsoft.com/ja-
> jp/dotnet/api/system.runtime.interopservices.marshal.releasecomobject?view=netframework-4.8)絶対に必要な場合にのみ、を使用してください。
> このメソッドを呼び出して、特定の時刻に COM
> コンポーネントが解放されるようにするには、代わりに[FinalReleaseComObject](https://docs.microsoft.com/ja-
> jp/dotnet/api/system.runtime.interopservices.marshal.finalreleasecomobject?view=netframework-4.8)メソッドを使用することを検討してください。

同様に以下の記事の解決マーク付き回答のコメントにも記述があります。  
[When am I required to call Marshal.ReleaseComObject on an interface queried
through COM in C#](https://stackoverflow.com/q/5086162/9014308)

> If you're trying to manage the reference count (AddRef/Release) of a COM
> object you should not do that, and if you want to deterministically release
> a COM object you should most likely be using FinalReleaseComObject.
>
> COMオブジェクトの参照カウント（AddRef /
> Release）を管理しようとしている場合は、それを行うべきではありません。また、COMオブジェクトを確定的に解放する場合は、おそらくFinalReleaseComObjectを使用する必要があります。

たどっていった先のVBの記事ではオプション指定で両方を使い分けています。

* * *

ReleaseComObject関連で一番古そうなのがこの記事

[Office application does not exit after automation from Visual Studio .NET
client](https://support.microsoft.com/ja-jp/help/317109/office-application-
does-not-exit-after-automation-from-visual-studio-n)

> If you are using Visual C# .NET, reference the code for the NAR() function:
[code]

>     private void NAR(object o)
>     {
>         try
>         {
>             while
> (System.Runtime.InteropServices.Marshal.ReleaseComObject(o) > 0) ;
>         }
>         catch {}
>         finally
>         {
>             o = null;
>         }
>     }
>  
[/code]

>
> Note Starting in .NET Framework 2.0, you can use
> System.Runtime.InteropServices.Marshal.FinalReleaseComObject instead of the
> while loop calling System.Runtime.InteropServices.Marshal.ReleaseComObject
> to achieve the same result.

* * *

次の応用らしそうなのが、対象はExcelですが、この記事

[VBからExcelを立ち上げた際の、解放処理について](http://bbs.wankuma.com/index.cgi?mode=al2&namber=36324&KLOG=63)

> > MRComObject の実装が書かれていないので(推測はつきますが)、
>
> こちらが、ソースになります。
[code]

>     ''' <summary>
>     ''' COMオブジェクト開放処理
>     ''' </summary>
>     ''' <remarks>
>     ''' 使用したCOMオブジェクトの開放を行う
>     ''' </remarks>
>     Private Sub MRComObject(Of T As Class)(ByRef objCom As T, Optional ByVal
> force As Boolean = False)
>         If objCom Is Nothing Then
>             Return
>         End If
>         Try
>             If System.Runtime.InteropServices.Marshal.IsComObject(objCom)
> Then
>                 If force Then
>
> System.Runtime.InteropServices.Marshal.FinalReleaseComObject(objCom)
>                 Else
>                     Dim count As Integer =
> System.Runtime.InteropServices.Marshal.ReleaseComObject(objCom)
>                 End If
>             End If
>         Finally
>             objCom = Nothing
>         End Try
>     End Sub
>  
[/code]

>
> ただ、このソースも自分で書いたわけではないので、具体的な説明ができません。  
>  すみません、一応

* * *

そして、同じく対象はExcelですが、この辺の記事の記載がより新しくなっているようです。

[VB .NETからエクセル出力](http://ace-taka.hatenablog.com/entry/2014/08/19/095913)  
[Excel関係のフレーム - VBレスキュー(花ちゃん) VS,VB.NET
...](http://hanatyan.sakura.ne.jp/dotnet/Excelflm.htm)

ただし、上記2番目記事の最後に以下のような注意があるので、そのソースは引用しません。  
紹介先を参照してください。

> **注意！**
>
> MRComObject は、元々 <http://support.microsoft.com/kb/317109/ja> の NAR
> の実装を元に私が少し変更して使っていたのですが、今まで使っていた方法では、Option Strict On の時にエラーとなったので、当サイトの掲示板の
> 魔界の仮面弁士さん の投稿を使用させて頂いたものなので、そう言った経緯を無視して、転載・引用されると、魔界の仮面弁士さん
> 等にもご迷惑をおかけする事にもなりますので、絶対に転載されないようにお願い致します。  
>  又、MRComObject
> の名前は、変更しておりませんが中身が何度となく変更しておりますので、転載先まで変更する事ができず、問題があっても困りますので、必要ならリンクを貼るようにして下さい。
>
> 又、[Excelのプロセスが正常に終了しない理由](http://hanatyan.sakura.ne.jp/dotnet/Excel08.htm)
> 等をよく理解しないまま、MRComObject
> を使用すれば、全て解放されるかのように誤解されて使用されている場合もあるので、よく読んでからご使用下さい。

記事の最初の方にも、以下のように繰り返し注意が書いてあります。  
記事の対象がExcelなので、それで書いてありますが、Office全般に応用できるのでは？

>
> ご使用にあたっては、[Excelのプロセスが正常に終了しない理由](http://hanatyan.sakura.ne.jp/dotnet/Excel08.htm)
> をよく読んでから実行願います。
>
> 又、Excel
> の起動・終了に関する設定は、実行環境用とテスト環境用の両方を掲載しておりますので。できれば、開発時は、テスト環境用の起動・終了に関する設定を使って頂いた方がプロセスの解放状況がよく解りますので便利かと思います。
>
> これらのサンプルをご使用になられる場合は、必ず、下記の **Excelのプロセスが正常に終了しない理由** をご覧になってから試すようにして下さい。  
>
> [Excelのプロセスが正常に終了しない理由(その１)](http://hanatyan.sakura.ne.jp/dotnet/Excel08.htm)  
>
> [Excelのプロセスが正常に終了しない理由(その２)](http://hanatyan.sakura.ne.jp/dotnet/Excel09.htm)


CC BY-SA 4.0
2019-09-25T11:19:50.783
59269
2019-09-26T08:31:10.340
2019-09-26T08:31:10.340
26370
26370
59257
answer