如何让CoCreateInstance创建一个新对象

发布于 2025-01-13 09:39:33 字数 864 浏览 3 评论 0原文

我编写了一个 exe(C++,MFC),它公开了一个用于创建 COM 对象的接口,即我的“com 服务器”。 COM 对象具有显示对话框的功能。我现在编写了第二个 exe 来创建这个 COM 对象并运行该函数,即我的“com 客户端”。

这是“com 客户端”中的代码:

MKS::IApplication*  pMKSApp = nullptr;   // the com object
CLSID id;
HRESULT hr0 = CoInitialize(NULL);
HRESULT hr1 = CLSIDFromProgID(OLESTR("MKS.Application"), &id);
HRESULT hr2 = CoCreateInstance(id, NULL, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&pMKSApp));
pMKSApp->ShowDialog();   // the function which displays the dialog
// at this point there is only one "com server" exe running
pMKSApp->Release();

当我运行客户端时,功能运行良好 - 对话框显示并且运行良好。但是,如果我运行“com 服务器”exe,然后运行“com 客户端”exe(两者同时运行),则会显示该对话框,但“com 服务器”变为非活动状态 - 该对话框显示为服务器作为其父级。如果我检查任务管理器,就会发现只有一个“com 服务器”实例正在运行。看起来 CoCreateInstance 并不是创建一个新的服务器,而是重用已经运行的服务器。

如何让“com客户端”创建“com服务器”的新实例? (我是 com 新手,所以如果我的术语不正确,我深表歉意。)

I have written an exe (C++, MFC) that exposes an interface for creating a COM object, i.e., my "com server". The COM object has a function that displays a dialog. I now wrote a second exe that creates this COM object and runs the function, i.e., my "com client".

Here is the code in the "com client":

MKS::IApplication*  pMKSApp = nullptr;   // the com object
CLSID id;
HRESULT hr0 = CoInitialize(NULL);
HRESULT hr1 = CLSIDFromProgID(OLESTR("MKS.Application"), &id);
HRESULT hr2 = CoCreateInstance(id, NULL, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&pMKSApp));
pMKSApp->ShowDialog();   // the function which displays the dialog
// at this point there is only one "com server" exe running
pMKSApp->Release();

When I run the client the functionality works fine - the dialog is displayed and works well. However, if I am running the "com server" exe and then run the "com client" exe (both running at the same time), the dialog is displayed but the "com server" becomes inactive - the dialog is being displayed with the server as its parent. If I check task manager, there is only one instance of the "com server" running. It seems that CoCreateInstance is not creating a new server but reusing the one that is already running.

How, can I get the "com client" to create a new instance of the "com server"? (I am new to com so I apologize if my terminology is incorrect.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

眉目亦如画i 2025-01-20 09:39:33

西蒙,谢谢你的指导。正如您所说,问题是“服务器问题”而不是“客户端问题”。而且,当我深入研究代码时,我发现这更多是 MFC 问题。

在我的代码中,我使用 MFC 的 IMPLMENT_OLECREATE_FLAGS 宏来实例化一个 COleObjectFactory 对象,该对象负责创建类工厂。查看 COleObjectFactory (olefact.cpp) 的 MFC 源代码,调用 CoRegisterClassObject 函数:

SCODE sc = ::CoRegisterClassObject(m_clsid, &m_xClassFactory,
    CLSCTX_LOCAL_SERVER,
    m_bMultiInstance ? REGCLS_SINGLEUSE : REGCLS_MULTIPLEUSE,
    &m_dwRegister);

m_bMultiInstance 变量的值决定使用哪个 REGCLS 值。不幸的是,该值是在 IMPLMENT_OLECREATE_FLAGS 宏中设置的。以下是宏定义:

#define IMPLEMENT_OLECREATE_FLAGS(class_name, external_name, nFlags, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
    COleObjectFactory class_name::factory(class_name::guid, \
        RUNTIME_CLASS(class_name), FALSE, nFlags, _T(external_name)); \
    AFX_COMDAT const GUID class_name::guid = \
        { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }; \

构造的第三个参数为 FALSE - 这是 m_bMultiInstance 变量的值。因此,我想出的解决方案是重新定义宏,并将第三个参数设置为 TRUE。

/// Redefine macro with argument set to true - create new instance for every client
#undef IMPLEMENT_OLECREATE_FLAGS
#define IMPLEMENT_OLECREATE_FLAGS(class_name, external_name, nFlags, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
    COleObjectFactory class_name::factory(class_name::guid, \
        RUNTIME_CLASS(class_name), TRUE, nFlags, _T(external_name)); \
    AFX_COMDAT const GUID class_name::guid = \
        { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }; \

现在看来它正在按预期工作。在任务管理器中,我现在可以看到当客户端发出请求时,会创建服务器应用程序的新实例。再次感谢您的帮助。

Simon, thank you for the guidance. As you said, the issue was a "server issue" rather than a "client issue". And, as I dug into the code, I found it was more of a MFC issue.

Within my code, I use MFC's IMPLEMENT_OLECREATE_FLAGS macro which instantiates a COleObjectFactory object which takes care of creating the class factory. Looking at the MFC source code for COleObjectFactory (olefact.cpp) the CoRegisterClassObject function is called:

SCODE sc = ::CoRegisterClassObject(m_clsid, &m_xClassFactory,
    CLSCTX_LOCAL_SERVER,
    m_bMultiInstance ? REGCLS_SINGLEUSE : REGCLS_MULTIPLEUSE,
    &m_dwRegister);

The value of the m_bMultiInstance variable decides which REGCLS value to use. Unfortunately, this value is set from within the IMPLEMENT_OLECREATE_FLAGS macro. Here is the macro definition:

#define IMPLEMENT_OLECREATE_FLAGS(class_name, external_name, nFlags, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
    COleObjectFactory class_name::factory(class_name::guid, \
        RUNTIME_CLASS(class_name), FALSE, nFlags, _T(external_name)); \
    AFX_COMDAT const GUID class_name::guid = \
        { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }; \

The third argument to the construction is FALSE - this is the value of the m_bMultiInstance variable. So, the solution I came up with was to redefine the macro with the third argument set to TRUE.

/// Redefine macro with argument set to true - create new instance for every client
#undef IMPLEMENT_OLECREATE_FLAGS
#define IMPLEMENT_OLECREATE_FLAGS(class_name, external_name, nFlags, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
    COleObjectFactory class_name::factory(class_name::guid, \
        RUNTIME_CLASS(class_name), TRUE, nFlags, _T(external_name)); \
    AFX_COMDAT const GUID class_name::guid = \
        { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }; \

It now seems to be working as desired. In task manager I can now see that a new instance of the server application is created when a request is made by the client. Thanks again for the help.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文