Runtime Callable Wrapper (RCW) のおかげで、COM を簡単に C# などから使うことが出来ますが、今回素晴らしくその挙動ではまったので忘れないうちにメモ。
Marshal.ReleaseComObject の呼び出し
Marshal.ReleaseComObject を呼び出す必要がないのは、キャストで得られたオブジェクトだけなので、コレクションを for でぐりぐり回した時とかに泣きを見ます。というか見ました。iTunes COM を使う時に
iTunesAppClass iTunes = new iTunesAppClass(); for (int i = 1; i <= iTunes.Sources.Count; ++i) { Console.WriteLine(iTunes.Sources[i].Name); }
といったように、添え字で各要素にアクセスするようなコードを書いてました。これでは、iTunes が正常に終了しなくなります。*1
実は、Sources は配列やコレクションのように見えても、実際は以下のメソッドを呼んでるからなんですね。
HRESULT get_Item ([in] long index,[out, retval] IITSource **iSource)
なのでこっちが正解。配列やコレクションのように見えると忘れがちなので注意です。
iTunesAppClass iTunes = new iTunesAppClass(); for (int i = 1; i <= iTunes.Sources.Count; ++i) { IITSource source = iTunes.Sources[i]; Console.WriteLine(source.Name); Marshal.ReleaseComObject(source); }
関係ないけど、iTunes COM のコレクションは 1 オリジンです。これもはまる原因になるので注意。
*1:iTunes は Release されてないオブジェクトがあると終了時に警告する。