Search code examples
c++.netcomclrappdomain

Why do EnumDomains/NextDomain loop forever?


The following simple code can be directly run in Visual Studio C++ console project.

It will loop forever because the NextDomain will always return the same IUnknown *

According to Microsoft, it should return NULL if the enumeration reaches end. See https://learn.microsoft.com/en-us/dotnet/framework/unmanaged-api/hosting/icorruntimehost-nextdomain-method

However, the NULL is never reached. It seems that it never return the NextDomain but keep returning the same domain.

Is there anything wrong? Thanks.

#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;
}

Solution

  • Return code from most enumerators is S_OK to continue and S_FALSE when it did not succeed. S_FALSE is not a fail code.

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