【问题标题】:Why do EnumDomains/NextDomain loop forever?为什么 EnumDomains/NextDomain 永远循环?
【发布时间】:2021-10-04 17:12:58
【问题描述】:

以下简单代码可以直接在 Visual Studio C++ 控制台项目中运行。

它将永远循环,因为 NextDomain 将始终返回相同的 IUnknown *

根据微软的说法,如果枚举结束,它应该返回 NULL。见https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/hosting/icorruntimehost-nextdomain-method

但是,永远不会达到 NULL。似乎它永远不会返回 NextDomain 而是继续返回相同的域。

有什么问题吗?谢谢。

#include <iostream>
#include <Windows.h>
#include <metahost.h>
#include <mscoree.h>
#pragma comment(lib, "mscoree.lib")

int main()
{
    ICLRMetaHost* clrMetaHost = NULL;
    ICLRRuntimeInfo* clrRuntimeInfo = NULL;
    ICorRuntimeHost* clrCorRuntimeHost = NULL;

    do {
        if (FAILED(CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&clrMetaHost))))
        {
            std::cout << "failed 1" << std::endl;
            break;
        }


        if (FAILED(clrMetaHost->GetRuntime(L"v2.0.50727", IID_PPV_ARGS(&clrRuntimeInfo))))
        {
            if (FAILED(clrMetaHost->GetRuntime(L"v4.0.30319", IID_PPV_ARGS(&clrRuntimeInfo))))
            {
                std::cout << "failed 2" << std::endl;
                break;
            }
        }

        if (FAILED(clrRuntimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_PPV_ARGS(&clrCorRuntimeHost))))
        {
            std::cout << "failed 3" << std::endl;
            break;
        }


        if (FAILED(clrCorRuntimeHost->Start()))
        {
            std::cout << "failed 4" << std::endl;
            break;
        }

        HDOMAINENUM hDomainEnum = nullptr;
        if (FAILED(clrCorRuntimeHost->EnumDomains(&hDomainEnum))) {
            std::cout << "failed 5" << std::endl;
            break;
        }

        IUnknown* domain;
        while (SUCCEEDED(clrCorRuntimeHost->NextDomain(hDomainEnum, &domain))
            && domain != NULL) {
            std::cout << "why loop forever here?" << std::endl;
            domain->Release();
        }

        if (FAILED(clrCorRuntimeHost->CloseEnum(hDomainEnum))) {
            std::cout << "failed 6" << std::endl;
        }

        break;

    } while (0);

    if (clrCorRuntimeHost != NULL) clrCorRuntimeHost->Release();
    if (clrRuntimeInfo != NULL) clrRuntimeInfo->Release();
    if (clrMetaHost != NULL) clrMetaHost->Release();

    return 0;
}

【问题讨论】:

  • 不能说这个枚举接口,但是很多枚举接口完成后不会返回错误码,而是返回一个S_FALSE(这是成功码)。更有可能测试总是返回 S_OK 或测试 S_FALSE 正在完成迭代。
  • 谢谢。在循环内更改为 S_OK 或将域设置为 nullptr 解决了这个问题!
  • 你应该学习如何使用CComPtr&lt;&gt;。它会自动进行引用计数,因此您不必调用 `ptr->Release()'。它是析构函数调用 Release。当发生异常时特别方便,这样您就不会绞合 COM 对象。

标签: c++ .net com clr appdomain


【解决方案1】:

大多数枚举器的返回代码是 S_OK 继续,S_FALSE 失败。 S_FALSE 不是失败代码。

while (S_OK == clrCorRuntimeHost->NextDomain(hDomainEnum, &domain))
            && domain != NULL) {
            std::cout << "why loop forever here?" << std::endl;
            domain->Release();
        }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-20
    • 2013-10-02
    • 1970-01-01
    • 2020-09-11
    • 1970-01-01
    • 1970-01-01
    • 2011-06-14
    相关资源
    最近更新 更多