你能有 2 个相同的 COM 对象吗?

Posted

技术标签:

【中文标题】你能有 2 个相同的 COM 对象吗?【英文标题】:Can you have 2 identical COM objects? 【发布时间】:2021-09-09 04:37:21 【问题描述】:

一个可以帮助回答我之前提出的另一个问题的一般性问题。我相信 COM 对象只返回一个指向创建对象的指针。所以当我尝试初始化一个 COM 对象两次时,我是在我的应用程序中创建两个 COM 对象,还是创建两个指向同一个对象的不同指针?或者指针指向它们各自的对象的对象可能有两个副本?

// Pointer to WebViewController
static wil::com_ptr<ICoreWebView2Controller> webviewController;

// Pointer to WebView window
static wil::com_ptr<ICoreWebView2> webviewWindow;


// Locate the browser and set up the environment for WebView
CreateCoreWebView2EnvironmentWithOptions(nullptr, nullptr, nullptr,
    Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
        [hWnd, url](HRESULT result, ICoreWebView2Environment* env) -> HRESULT 

    // Create a CoreWebView2Controller and get the associated CoreWebView2 whose parent is the main window hWnd
    env->CreateCoreWebView2Controller(hWnd, Callback<ICoreWebView2CreateCoreWebView2ControllerCompletedHandler>(
        [hWnd, url](HRESULT result, ICoreWebView2Controller* controller) -> HRESULT 

        _com_error err4(result);
        MessageBoxW(hWnd, L"Controller setup", 0, MB_OK);
        MessageBoxW(hWnd, err4.ErrorMessage(), 0, MB_OK);

        if (controller != nullptr) 
            webviewController = controller;
            webviewController->get_CoreWebView2(&webviewWindow);
        

        // Add a few settings for the webview
        // The demo step is redundant since the values are the default settings
        ICoreWebView2Settings* Settings;
        webviewWindow->get_Settings(&Settings);
        Settings->put_IsScriptEnabled(TRUE);
        Settings->put_AreDefaultScriptDialogsEnabled(TRUE);
        Settings->put_IsWebMessageEnabled(TRUE);

        // Resize WebView to fit the bounds of the parent window
        RECT bounds;
        GetClientRect(hWnd, &bounds);
        webviewController->put_Bounds(bounds);

        // Schedule an async task to navigate to Bing
        webviewWindow->Navigate(url);
        if (GetWindow(hWnd, GW_CHILD) != NULL) 
            MessageBoxW(hWnd, L"not a NULL child window", 0, MB_OK);
        ;

        // Step 4 - Navigation events

        // Step 5 - Scripting

        // Step 6 - Communication between host and web content

        return S_OK;
    ).Get());
    return S_OK;
).Get());

我打过电话 CoInitialize(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); 前面的代码只有一次。我的问题是当我运行这个块两次时会发生什么?

【问题讨论】:

您可以通过两次调用函数并比较返回的两个指针来凭经验确定这一点。 @jon 这不是比较 COM 对象的身份的方式。所有比较操作都要求您首先查询规范的IUnknown,然后才能以有意义的方式比较指针是否相等。 @JonathanPotter - 这只是 IUnknown 的 COM 要求:docs.microsoft.com/en-us/windows/win32/com/… @jon 你把“你觉得合理的东西”与基本的 COM 规则混淆了。我已经解释了基本的 COM 规则是什么,Simon 提供了文档链接。 我只能说我很想看到可以在同一个地址实现两个不同对象的示例代码。 【参考方案1】:

我的问题是当我运行这个块两次时会发生什么?

在这种特定情况下,执行两次代码将产生两个不同的 WebView2 实例。然后将两个实例分配给同一个static 变量,导致一个实例不可撤销地泄露。

作为XY Problem,此信息并不是非常有用。您要解决的真正问题是知道 WebView2 控件何时完全构造。这个问题已经回答elsewhere。

【讨论】:

【参考方案2】:

所以当我尝试初始化一个 COM 对象两次时,我是在我的应用程序中创建两个 COM 对象,还是创建两个指向同一个对象的不同指针?或者指针指向它们各自的对象的对象可能有两个副本?

这实际上取决于 COM 对象的实现。如果它是作为单例实现的,那么多次实例化它会返回一个指向现有实例的指针(如果它还不存在,则创建一个新实例)。但是,如果 COM 对象不是作为单例实现的,那么每个实例化都会返回一个指向新实例的指针。

【讨论】:

我对 COM 对象的工作不多,只熟悉 C# 中的单例。但谢谢你的提示。我将研究单例,我正在尝试使用 MFC 搜索 WebView2 的帖子。

以上是关于你能有 2 个相同的 COM 对象吗?的主要内容,如果未能解决你的问题,请参考以下文章

你能有自动编号索引层次结构吗?

你能有一个没有 ON 关键字的 INNER JOIN 吗?

我可以将相同的数据读取器对象绑定到 2 个控件吗?

discord.py 你能从 discord 标签中获取用户对象吗?

修改代码参考手册

你能让一个对象可迭代吗? [复制]