しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

Runtime Callable Wrapper (RCW) を使う時の注意点

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 されていないオブジェクトがあると終了時に警告する。