CLRホストからProvideAssemblyによってAppDomainManagerをロードできますか?

カスタムAppDomain Managerを持つ.net clrとストアを持つAssemblyManagerをホストするアプリケーションがあります。

AppDomainManagerを持つアセンブリが実行可能ファイルと同じディレクトリにあるdllである場合、これはすべて正常に動作します。

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.

すべてのアセンブリバインディングの詳細などが一致します。

私の質問は、誰もがこの設定がサポートされているかどうか知っていますか? AppDomainManagersアセンブリをファイルからではなくこの方法で読み込むことはできますか?


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

ルックアップマップからアイデンティティをバインドし、格納されたデータの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::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);
}
3
はい、これはサポートされています。
追加された 著者 Hans Passant,
あなたがまだ持っていないものはありません。あなたの問題をよりよく説明するまで、誰もあなたを助けることはできません。コードスニペットは最小要件です。
追加された 著者 Hans Passant,
こんにちは、コメントありがとう、私はあなたが私のホストが失敗する理由を解決することができますので、あなたが私を指すことができる任意のドキュメント/ページがありますか?私はMSのCLRを参照してオンラインドキュメントとMSの本をホスティング "CLRのカスタマイズ"私は何か愚かなことをしている必要があります!
追加された 著者 BafflingTangent,
こんにちは、あなたが見たいスニペットを追加しましたか?ありがとう。
追加された 著者 BafflingTangent,

1 答え

ハンスは言ったように、あなたはすでに必要なものすべてを持っています。上記の本には、AppDomainManagerクラスを含むアセンブリがホストによってOLE複合ファイルから取り出される既成の例があります。

私は似たようなことをやっているので、それが機能することを確認することができます。あなたは3つの点に注意する必要があります:

  • 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)
1
追加された