1

実行中の COM インスタンスにバインドする必要があります (探しているもののインスタンスが多数存在する可能性があるため、実行中のオブジェクト テーブルを調べてどれが適切かを判断する必要があります) CoClassCreate またはnewクラスでの演算子を使用すると、私には選択肢がありません。

私が持っているコードは、例外セーフではないことを除いて、ほとんど機能します。

Revoke以下のコードのように例外がスローされた場合、舞台裏で発生する自動を回避する方法はありますか? アプリケーションが終了すると、それを登録したアプリケーションがまだ実行されている間に、COM オブジェクトは ROT から削除されます。Release() が自動的に呼び出され、それが COM を参照する最後のオブジェクトであったため、ROT エントリが消えていることは確かです。

アトミックで例外セーフな方法で、ROT 内のオブジェクトへの強い参照を取得したいと考えています。

メソッドと組み合わせてモニカを使用しようとする試みはすべてBindToObject失敗しました。.NET 4.0 での実装に問題はありますか? 最初の呼び出しは機能しているように見えますが、IUnknown の Guid を使用している場合でも、後続の呼び出しはすべて Argument または invalidCast 例外で失敗します。私の知る限り、これは常に成功するはずですか、それとも何かを見落としていますか?

これは、これまでに作成できた最高の作業コードです。例外の安全性が恋しいだけです。このプログラムは、単独で実行することを意図しており、割り込み可能です (例外をスローして、いつでもトレッドを中断できます)。この未完の仕事を放っておくと、きれいに解決できなければ、確かに問題が発生します。

    [DllImport("ole32.dll")]
    static extern int CreateBindCtx(uint reserved, out IBindCtx ppbc);

    // Returns the contents of the Running Object Table (ROT), where
    // open Microsoft applications and their documents are registered.
    private IEnumerable<T> GetRunningObjects<T>()
    {
        // Get the table.
        IBindCtx bc;
        if (CreateBindCtx(0, out bc) != 0 || bc == null)
            throw new ApplicationException("Can't create COM binding context in GetRunningObjects<T>");

        IRunningObjectTable runningObjectTable;
        bc.GetRunningObjectTable(out runningObjectTable);

        IEnumMoniker monikerEnumerator;
        runningObjectTable.EnumRunning(out monikerEnumerator);
        monikerEnumerator.Reset();

        // Enumerate and fill our nice dictionary.
        IMoniker[] monikers = new IMoniker[1];
        IntPtr numFetched = IntPtr.Zero;
        while (monikerEnumerator.Next(1, monikers, numFetched) == 0)
        {
            object o = null;
            if (runningObjectTable.GetObject(monikers[0], out o) == 0 && o != null)
            {
                if (o is T)
                {
                    // TODO: If an exception is thrown here, then COM object gets revoked from ROT...
                    throw new Exception("Test");

                    // monikers[0].BindToObject does not work...
                    // there seems to be a weakness here.

                    // if found, create a strong reference to avoid auto-revokation in the ROT
                    IntPtr ptr = Marshal.GetIUnknownForObject(o);
                    Marshal.AddRef(ptr);

                    yield return (T)o;
                }
            }
        }
        Marshal.ReleaseComObject(bc);
    }

追記: これは、OutProc サーバーがアクティブなオブジェクトを弱参照のみとして登録した場合に発生する可能性があります。私はこれに影響を与えません。私はサーバー側の作成者ではありません...オブジェクトが実行中のオブジェクトテーブルから取り消されるリスクを冒さずに、実行中のオブジェクトにバインドする必要があります。

4

0 に答える 0