【发布时间】: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<>。它会自动进行引用计数,因此您不必调用 `ptr->Release()'。它是析构函数调用 Release。当发生异常时特别方便,这样您就不会绞合 COM 对象。
标签: c++ .net com clr appdomain