我知道我们可以使用CoLoadLibrary和DllGetClassObject来获取IClassFactory接口并获取COM组件接口,而无需注册DLL。

但是 EXE 中的 COM 组件又如何呢?有没有一种方法可以通过提供不同的文件路径来从 EXE 类型的 COM 服务器获取 COM 组件接口?

有帮助吗?

解决方案

如果使用真实 注册免费com,您应该能够为in-proc和out-proc的com对象提供此工作。

作为日星形指向,您真的不使用注册免费com。相反,您可以通过伪造COM在激活过程中使用的呼叫来滚动自己。如果您控制您的应用程序和您正在激活的COM服务器,则您的解决方案可以工作,但它可能会失败。

其他提示

你不能。您需要在程序和进程外 COM 服务器之间进行 COM 设置编组。要实现此目的,您必须致电 CoInitialize() 然后要么 CoCreateInstance() 或者 CoGetClassObject().

您使用进程内服务器描述的路径 - 调用 CoLoadLibrary() 进而 DllGetClassObject() - 实际上是一个肮脏的黑客 - 它绕过了正常的 COM 机制,因此即使需要满足线程模型要求(STA/MTA 的东西),也不会进行编组。这种肮脏的黑客行为是可能的,因为进程内服务器是一个常规的 DLL,暴露了几个众所周知的函数。对于进程外 COM 服务器来说,这是不可能的 - 在这种情况下您需要依赖 COM。

您可以在函数调用中将 COM 组件作为指针传递。

因此,假设您在 EXE 中实现一个对象,并且从 DLL 加载另一个 COM 对象,您可以将基于 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 进行。

这有时称为“依赖注入”或“控制反转”。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top