我有一个托管.net clr的应用程序,其中包含一个自定义AppDomain Manager和一个带有商店的AssemblyManager。
当具有AppDomainManager的程序集与可执行文件位于同一目录中时,这一切都正常。
我想要做的是将Managers程序集嵌入可执行文件中。当我这样做时,使用正确的强名称调用ProvideAssembly,我返回一个包含汇编字节的流,但ICLRRuntimeHost-> Start()返回一个错误,指示无法加载类型。
所有装配绑定详细信息都匹配等。
我的问题是,是否有人知道是否支持此配置?可以用这种方式而不是从文件加载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);
查找从映射中绑定标识,返回存储数据的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;
}
我得到了这样的绑定身份:
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);
}
答案 0 :(得分:1)
汉斯说,你已经拥有了所需的一切。你提到的那本书有一个现成的例子,其中包含AppDomainManager类的程序集被主机从OLE复合文件中拉出来。
我正在做类似的事情,所以我确认它有效。你必须小心三点:
GAC -> Host -> other Fusion search paths
pAssemblyId
时,永远不会超过0.文档不会告诉它,但它会产生一种非常奇怪的行为。IStream
。就个人而言,我编写了我的FileStream unamanged类,它使用Win32 API实现IStream
。比依赖不是为此目的编写的代码(或链接到某些东西&#34;奇怪的&#34;,像shell API)更好的方式答案 1 :(得分:0)
请注意,在“ pBindInfo”中,传递的程序集的标识与请求的“ processorarchitecture”相匹配,尤其是在“ lpPostPolicyIdentity”中查找所请求的“ processorarchitecture”,如果程序集不匹配,则使请求失败。 clr会尝试先加载x64或x86,然后再加载msil(anycpu),因此请等到您收到正确的请求