可AppDomainManager被ProvideAssembly从CLR主机装? [英] Can AppDomainManager be loaded by ProvideAssembly from a CLR Host?

查看:272
本文介绍了可AppDomainManager被ProvideAssembly从CLR主机装?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我主持的.NET CLR与自定义应用程序域管理器和一个AssemblyManager与商店的应用程序。

这一切工作正常时,大会与AppDomainManager的是,在同一目录中的可执行文件的DLL。

我想要做的就是嵌入经理组装可执行文件里有什么。当我这样做ProvideAssembly时调用正确的强大的名字,我返回一个流与大会字节,但是ICLRRuntimeHost->启动()返回一个错误,指出一个类型不能被加载。

所有程序集绑定信息匹配等。

我的问题是,没有人知道是否支持此配置?能否AppDomainManagers组件以这种方式,而不是从一个文件中加载?


目前只提供IHostAssemblyManager到CLR。并呼吁:

 #定义组件LMscoreeIntegration,版本= 1.0.0.0,公钥= a0c02a181a22f567,文化=中性
#定义经理LMscoreeIntegration.Manager

m_clrcontrol-> SetAppDomainManagerType(组件,经理);
 

查找绑定从地图标识,返回存储的数据的IStream(已加强通过与调试器并没有什么失败)

  HRESULT STDMETHODCALLTYPE AssemblyManager :: GetNonHostStoreAssemblies(ICLRAssemblyReferenceList ** P preferenceList){
    * P preferenceList = NULL;
    返回S_OK;
}

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

HRESULT STDMETHODCALLTYPE AssemblyStore :: ProvideAssembly(AssemblyBindInfo * pBindInfo,UINT64 * pAssemblyId,UINT64 * pContext,的IStream ** ppStmAssemblyImage,IStream的** ppStmPDB){
    地图< wstring的,数据*>:迭代找到= m_impl-> m_assemblies.find(pBindInfo-> lpPostPolicyIdentity);
    如果(找到= m_impl->!m_assemblies.end()){
        * pAssemblyId =查找 - >二线> m_id;

        HGLOBAL HMEM = ::的GlobalAlloc(GMEM_MOVEABLE,查找 - >二线> m_cbLength);
        LPVOID的pData = :: GlobalLock(HMEM);
        的memcpy(pData所,查找 - >二线> m_pData,查找 - >二线> m_cbLength);
        :: GlobalUnlock(HMEM);

        HRESULT HR = ::了CreateStreamOnHGlobal(HMEM,FALSE,ppStmAssemblyImage);

        * pContext = 0;
        * ppStmPDB = NULL;
        返回S_OK;
    }

    返回0x80070002; // COR_E_FILENOTFOUND;
}
 

我得到的结合身份像这样:

 无效AddAssembly(AssemblyStore *商店,ICLRAssemblyIdentityManager * IDENT,为const char *文件名){
    INT长度= 0;
    为const char *缓冲区= LoadData(文件名,长度);
    的IStream *流= GetStream(缓冲区长度);
    如果(流!){返回; }

    DWORD cbBuffer = 0;
    HRESULT小时= ident-> GetBindingIdentityFromStream(流,0,NULL,&安培; cbBuffer);

    为wchar_t *绑定=(wchar_t的*)malloc的(cbBuffer *的sizeof(wchar_t的));
    流= GetStream(缓冲区长度);
    HR = ident-> GetBindingIdentityFromStream(流0,绑定,和放大器; cbBuffer);

    BOOL强;
    HR = ident-> IsStronglyNamed(结合,与安培;强);
    如果(!强){
        的printf(不强:%S \ N,绑定);
    }

    store-> AddAssembly(绑定,(BYTE *)缓冲区,长度);
}
 

解决方案

像汉斯说,你已经拥有你所需要的一切。你所提到的这本书有一个现成的例子,其中包含AppDomainManager类组件拉出一个OLE复合文件的主机。

我在做类似的事情,所以我可以证实它的工作原理。你必须要小心三点:

  • 当你生成非主机组件列表中。如果你不知道如何正确地构建它,它的方式更好地让CLR处理它(传回NULL) 这样的分辨率变 GAC - >主持人 - >其他融合搜索路径
  • 当您返回 pAssemblyId ,永远,永远传递0。文档不告诉它,但它导致了一个非常奇特的..行为。
  • 文件读入一个的IStream 。就个人而言,我通过使用Win32 API写我的FileStream unamanged类实现的IStream 。路不是依靠,这不是为了这个目的写code(或链接到一些奇怪,如外壳API)好

I have an application hosting the .net clr with a custom AppDomain Manager and an AssemblyManager with a store.

This all works fine when the Assembly with the AppDomainManager in is a dll in the same directory as the executable.

What I want to do is embed the Managers assembly inside the executable. When I do this ProvideAssembly is called with the correct strong name, I return a stream with the assembly bytes, but ICLRRuntimeHost->Start() returns an error indicating that a type cannot be loaded.

All the assembly binding details match etc.

My questions is, does anyone know if this configuration is supported? Can the AppDomainManagers assembly be loaded in this way rather than from a file?


Currently only provide an IHostAssemblyManager to the CLR. And Call:

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

m_clrcontrol->SetAppDomainManagerType(ASSEMBLY, MANAGER);

Lookup Binding identity from map, return an IStream of the stored data (Have stepped through with a debugger and nothing fails).

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

I get the binding identities like so:

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

解决方案

Like Hans said, you already have everything you need. The book you mentioned has a ready-made example in which the assembly that contains the AppDomainManager class is pulled out of a OLE compound file by the host.

I am doing something similar, so I can confirm it works. You have to be careful on three points:

  • when you generate the list of non-host assemblies. If you do not know how to build it properly, it's way better to let the CLR handle it (passing back NULL) In this way the resolution becomes GAC -> Host -> other Fusion search paths
  • when you return pAssemblyId, never, ever pass 0. The docs don't tell it, but it results in a very .. peculiar behaviour.
  • reading the file into a IStream. Personally, I wrote my FileStream unamanged class that implements IStream by using the Win32 API. Way better than relying on code that was not written for this purpose (or linking to something "strange", like the shell API)

这篇关于可AppDomainManager被ProvideAssembly从CLR主机装?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆