Возможна ли активация без регистрации для COM (вне процесса) COM-серверов? - PullRequest
7 голосов
/ 09 июля 2010

Я знаю, что мы можем использовать CoLoadLibrary и DllGetClassObject, чтобы получить интерфейс IClassFactory и получить интерфейс компонента COM без регистрации DLL.

Но как насчет компонента COM в EXE-файле?Есть ли способ получить интерфейс COM-компонента с COM-сервера EXE-типа, просто указав другой путь к файлу?

Ответы [ 3 ]

3 голосов
/ 10 июля 2010

Если вы используете real без регистрации COM , вы сможете получить это как для внутренних, так и для внешних объектов COM.

Как указал Sharptooth, вы на самом деле не используете бесплатную регистрацию COM.Вместо этого вы по-настоящему раскручиваете свои собственные, подделывая вызовы, которые COM использует во время активации.Ваше решение МОЖЕТ работать, если вы управляете как своим приложением, так и COM-сервером, который активируете, но в противном случае оно может дать сбой.

2 голосов
/ 09 июля 2010

Нет, вы не можете. Вам нужно настроить COM-соединение между вашей программой и COM-сервером out-proc. Для этого вам нужно позвонить CoInitialize(), а затем либо CoCreateInstance(), либо CoGetClassObject().

Путь, который вы описываете с внутрипроцессным сервером - вызов CoLoadLibrary(), а затем DllGetClassObject() - на самом деле является грязным хаком - он обходит обычные механизмы COM и поэтому, например, никакой маршаллинг не сработает, даже если это необходимо удовлетворить требования модели потоков (материал STA / MTA). Такой грязный хак возможен, потому что внутрипроцессный сервер - это обычная DLL с несколькими хорошо известными функциями. То же самое невозможно для COM-сервера out-proc - в этом случае вам нужно полагаться на COM.

1 голос
/ 09 июля 2010

Вы можете передать COM-компонент в вызове функции в качестве указателя.

Итак, предположим, что вы внедрили объект в свой EXE-файл, и который загружает другой COM-объект из DLL, вы можете передать EXE-файл.основанный объект на объект из DLL.Загруженный объект должен поддерживать интерфейс, который имеет функцию, которая принимает указатель, например

interface ILoadedObject
{
    HRESULT GiveObject(IUnknown *pObj);
};

Если объект на основе DLL реализует это, вы можете вызвать его из вашего EXE и передать ему объект , который нигде не зарегистрирован , поэтому нет необходимости регистрировать объекты в EXE-файле для достижения этого.

Единственные требования касаются правильной реализации IUnknown: не уничтожайтеобъект до тех пор, пока Release не будет вызван нужное количество раз, и убедитесь, что QueryInterface может использоваться для перемещения между фиксированным набором интерфейсов на объекте и что запрос для IUnknown всегда возвращает один и тот же адрес.

С другой стороны, вы можете зарегистрировать EXE в качестве сервера объектов, но это представляет большую сложность;COM должен запустить исполняемый файл EXE и затем отправить ему сообщения через очередь сообщений Windows.Это широко используется только для OLE;это может быть довольно хрупким.

Обновление

Более полное решение состоит в том, чтобы определить стандартный способ создания экземпляра типа объекта, но разрешить EXEопределить, как это работает.EXE будет реализовывать:

interface IComponent;

interface IEnvironment : IUnknown
{
    HRESULT CreateInstance(REFCLSID clsid, IComponent **ppNew);
}

Каждый компонент должен поддерживать этот интерфейс:

interface IComponent : IUnknown
{
    HRESULT SetEnvironment(IEnvironment *pEnv);
}

Теперь, чтобы получить стандартное поведение, когда EXE хочет использовать реестр для поиска компонентов,Можно реализовать метод CreateInstance следующим образом:

HRESULT Env::CreateInstance(REFCLSID clsid, IComponent **ppNew)
{
    HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER,
                     __uuidof(IComponent), (void **)&ppNew);
    if (FAILED(hr))
        return hr;

    (*ppNew)->SetEnvironment(this);
    return S_OK;
}

Но, конечно, он может изменить это и «внедрить» некоторые компоненты.Таким образом, вместо (или в дополнение к) реестра может использоваться файл конфигурации.Или (как вы просили) EXE может иметь встроенные реализации некоторых компонентов:

Поскольку каждый компонент уведомляется о среде при его создании, он может использовать эту среду для создания дополнительных компонентов:

// inside some component:
HRESULT Comp::SetEnvironment(IEnvironment *e)
{
    m_env = e; // using a smart pointer for ref-counting
    return S_OK;
}

// in some method of the component

ComPtr<IComponent> button;
m_env->CreateInstance(CLSID_Button, &button);

// now query button for more useful interface...

Таким образом, всякий раз, когда компонент создается, среда (определенная в EXE) может точно контролировать, как будет найдена реализация компонента.Каждое творение проходит через EXE-файл.

Это иногда называют «внедрением зависимости» или «инверсией управления».

...