gpt4 book ai didi

.net - ProvideAssembly 可以从 CLR 主机加载 AppDomainManager 吗?

转载 作者:行者123 更新时间:2023-12-03 02:22:25 28 4
gpt4 key购买 nike

我有一个应用程序托管 .net clr,其中包含自定义 AppDomain Manager 和带有存储的 AssemblyManager。

当包含 AppDomainManager 的程序集是与可执行文件位于同一目录中的 dll 时,这一切都可以正常工作。

我想要做的是将 Managers 程序集嵌入到可执行文件中。当我执行此操作时,使用正确的强名称调用 ProvideAssembly,我返回一个包含程序集字节的流,但 ICLRRuntimeHost->Start() 返回一个错误,指示无法加载类型。

所有程序集绑定(bind)详细信息都匹配等。

我的问题是,有谁知道是否支持此配置? AppDomainManagers 程序集可以通过这种方式加载,而不是从文件加载吗?

<小时/>目前仅向 CLR 提供 IHostAssemblyManager。并调用:

#define ASSEMBLY L"MscoreeIntegration, Version=1.0.0.0, PublicKeyToken=a0c02a181a22f567, Culture=neutral"
#define MANAGER L"MscoreeIntegration.Manager"

m_clrcontrol->SetAppDomainManagerType(ASSEMBLY, MANAGER);

从映射中查找绑定(bind)标识,返回存储数据的 IStream(已使用调试器单步执行,没有失败)。

HRESULT STDMETHODCALLTYPE AssemblyManager::GetNonHostStoreAssemblies(ICLRAssemblyReferenceList **ppReferenceList){
*ppReferenceList = NULL;
return S_OK;
}

HRESULT STDMETHODCALLTYPE AssemblyManager::GetAssemblyStore(IHostAssemblyStore **ppAssemblyStore){
*ppAssemblyStore = m_impl->m_store;
return S_OK;
}

HRESULT STDMETHODCALLTYPE AssemblyStore::ProvideAssembly(AssemblyBindInfo *pBindInfo, UINT64 *pAssemblyId, UINT64 *pContext, IStream **ppStmAssemblyImage, IStream **ppStmPDB){
map<wstring,Data*>::iterator find = m_impl->m_assemblies.find(pBindInfo->lpPostPolicyIdentity);
if(find!=m_impl->m_assemblies.end()){
*pAssemblyId = find->second->m_id;

HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE, find->second->m_cbLength);
LPVOID pData = ::GlobalLock(hMem);
memcpy(pData, find->second->m_pData, find->second->m_cbLength);
::GlobalUnlock(hMem);

HRESULT hr = ::CreateStreamOnHGlobal(hMem, FALSE, ppStmAssemblyImage);

*pContext = 0;
*ppStmPDB = NULL;
return S_OK;
}

return 0x80070002; //COR_E_FILENOTFOUND;
}

我得到的绑定(bind)身份如下:

void AddAssembly(AssemblyStore *store, ICLRAssemblyIdentityManager *ident, const char* filename){
int length = 0;
const char *buffer = LoadData(filename, length);
IStream *stream = GetStream(buffer, length);
if(!stream){ return; }

DWORD cbBuffer = 0;
HRESULT hr = ident->GetBindingIdentityFromStream(stream, 0, NULL, &cbBuffer);

wchar_t *bind = (wchar_t*)malloc(cbBuffer*sizeof(wchar_t));
stream = GetStream(buffer, length);
hr = ident->GetBindingIdentityFromStream(stream, 0, bind, &cbBuffer);

BOOL strong;
hr = ident->IsStronglyNamed(bind, &strong);
if(!strong){
printf("NOT STRONG: %S\n", bind);
}

store->AddAssembly(bind, (BYTE*)buffer, length);
}

最佳答案

就像汉斯所说,你已经拥有了你需要的一切。您提到的书有一个现成的示例,其中包含 AppDomainManager 类的程序集由主机从 OLE 复合文件中提取。

我正在做类似的事情,所以我可以确认它是否有效。您必须注意三点:

  • 当您生成非宿主程序集列表时。如果您不知道如何正确构建它,最好让 CLR 处理它(传回 NULL)这样解析就变成了GAC -> Host -> other Fusion search paths
  • 当您返回pAssemblyId时,永远不会传递0。文档没有告诉它,但它会导致非常..奇怪的行为。
  • 将文件读入IStream。就我个人而言,我编写了使用 Win32 API 实现 IStream 的 FileStream 未修改类。比依赖不是为此目的编写的代码(或链接到“奇怪”的东西,例如 shell API)要好得多

关于.net - ProvideAssembly 可以从 CLR 主机加载 AppDomainManager 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9161463/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com