为什么 EnumDomains/NextDomain 永远循环?

问题描述

下面的简单代码可以直接在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_OK 以继续,而 S_FALSE 在它没有成功时。 S_FALSE 不是失败代码。

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