Создание сильной ссылки на COM-объект в ROT с C#

Мне нужно привязать к работающему экземпляру COM (может быть много экземпляров того, что я ищу, поэтому мне нужно выяснить, какой из них правильный, изучив таблицу запущенных объектов) Используя CoClassCreate или new Оператор с классом не вариант для меня.

Код, который у меня есть, почти работает, за исключением того, что он не является безопасным исключением

Есть ли способ избежать автоматического Revoke что происходит за кулисами, если исключение выдается, как в коде ниже? Как только приложение заканчивается, COM-объект удаляется из ROT, пока приложение, которое зарегистрировало его, все еще работает. Я уверен, что Release() вызывается автоматически, и, поскольку это был последний объект, ссылающийся на COM, запись ROT исчезает.

Я хотел бы получить сильную ссылку на объект в ROT атомарным и исключительным способом.

Все мои попытки использовать моникер в сочетании с методом BindToObject были неудачными. Есть ли проблема с реализацией в.NET 4.0? Первый вызов, кажется, работает, но все последующие вызовы терпят неудачу с исключением Argument или invalidCast, даже при использовании Guid of IUnknown. Насколько мне известно, это всегда должно быть успехом или я что-то упускаю?

Вот лучший рабочий код, который я мог сделать до сих пор. Я просто скучаю по безопасности исключений. Программа предназначена для запуска сама по себе и может быть прервана (может быть выдано исключение для прерывания шага в любое время). Выход из этого незаконченного бизнеса наверняка вызовет у меня некоторые проблемы, если я не смогу решить его чисто.

    [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 регистрирует активный объект только как слабую ссылку. Я не имею никакого влияния на это, я не являюсь автором серверной части... Мне нужно привязать к работающему объекту, не рискуя отозвать объект из Таблицы запущенных объектов.

0 ответов

Другие вопросы по тегам