Может ли AppDomainManager быть загружен ProvideAssembly с хоста CLR? - PullRequest
3 голосов
/ 06 февраля 2012

У меня есть приложение, в котором размещается .net clr с настраиваемым диспетчером доменов приложений и AssemblyManager с хранилищем.

Все это прекрасно работает, когда сборка с AppDomainManager в dll находится в том же каталоге, что и исполняемый файл.

Что я хочу сделать, так это встроить сборку Managers в исполняемый файл. Когда я делаю это, ProvideAssembly вызывается с правильным строгим именем, я возвращаю поток с байтами сборки, но ICLRRuntimeHost-> Start () возвращает ошибку, указывающую, что тип не может быть загружен.

Все детали привязки сборки совпадают и т. Д.

Мои вопросы: кто-нибудь знает, поддерживается ли эта конфигурация? Может ли сборка AppDomainManagers загружаться таким образом, а не из файла?


В настоящее время только предоставить IHostAssemblyManager для CLR. И Звоните:
#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);
}

1 Ответ

1 голос
/ 15 декабря 2014

Как сказал Ганс, у вас уже есть все, что вам нужно.В упомянутой вами книге есть готовый пример, в котором сборка, содержащая класс AppDomainManager, извлекается хостом из составного файла OLE.

Я делаю нечто подобное, поэтому я могу подтвердить, что это работает.Необходимо соблюдать осторожность в отношении трех моментов:

  • при создании списка сборок, не связанных с хостом.Если вы не знаете, как его правильно построить, лучше позволить CLR обрабатывать его (передавая NULL). Таким образом, разрешение возвращается GAC -> Host -> other Fusion search paths
  • , когда вы возвращаете pAssemblyId, никогда, никогдапередать 0. Документы не сообщают об этом, но это приводит к очень .. своеобразному поведению.
  • чтение файла в IStream.Лично я написал свой неисчислимый класс FileStream, который реализует IStream с использованием Win32 API.Это лучше, чем полагаться на код, который не был написан для этой цели (или ссылаться на что-то «странное», например на API оболочки)
...