С++ (ATL) ITypeInfo.GetContainingTypeLib завершается с ошибкой при передаче живого экземпляра класса VBA

Итак, я задал этот вопрос в контексте С#, и у меня есть -cl">установить награду там.

Я написал эквивалентный фрагмент кода C++ (для размещения в проекте ATL DLL), чтобы использовать опыт разработчиков C++.

IDispatch имеет метод GetTypeInfo(), с помощью которого можно получить указатель на ITypeInfo. Сам ITypeInfo имеет метод GetContainingTypeLib, который получает содержащий ITypeLib (как он говорит). Это полезно, когда заданный экземпляр CoClass один раз может получить доступ ко всем другим CoClass в данной DLL, что очень полезно для отражения.

Я задавался вопросом, будет ли Excel VBA сотрудничать аналогичным образом и возвращать ITypeLib для содержащего проекта VBA и в равной степени позволит мне перебирать все типы, найденные в нем. Итак, я написал тестовый код C#, и он связан. Здесь я даю эквивалентный код C++, чтобы использовать возможности C++.

ИДЛ...

[
    object,
    uuid(ddc4e135-49d6-49f8-ad57-ded4180095fd),
    dual,
    nonextensible,
    pointer_default(unique)
]
interface ICoClassGetContainingTypeLib : IDispatch
{
    HRESULT GetContainingTypeLib(IDispatch* vbaClass, IUnknown** iunkTypeLib);
};

[
    uuid(bc8410a6-802a-4f91-a73b-c03179bb402b)
]
coclass CoClassGetContainingTypeLib
{
    [default] interface ICoClassGetContainingTypeLib;
};

Реализация метода cpp

STDMETHODIMP CCoClassGetContainingTypeLib::GetContainingTypeLib(IDispatch* vbaClass, IUnknown** iunkTypeLib)
{
    CComPtr<IDispatch> itfDispatch(vbaClass);
    CComPtr<ITypeInfo> pITypeInfo;

    HRESULT hr = S_OK;
    HRESULT hr2 = S_OK;
    try
    {

        hr = itfDispatch->GetTypeInfo(0, 0, &pITypeInfo);
        if (SUCCEEDED(hr)) 
        {
            UINT* idx(0);
            CComQIPtr<ITypeLib> pTLib;
            HRESULT hr2 = pITypeInfo->GetContainingTypeLib(&pTLib, idx);
            return hr2; // throws exception Exception 0x800A88C1 
            // which ends u[p at 35009

            //TODO If successful copy to ByRef param  iunkTypeLib
        }
    }
    catch (std::exception ex)
    {
        return E_FAIL;
    }
    return S_OK;
}

И объявление заголовка

STDMETHOD(GetContainingTypeLib)(IDispatch* vbaClass, IUnknown** iunkTypeLib);

И какой-то клиент VBA

Sub TestGetContainingTypeLib()

    Dim oTR As ToolsReferences  '* could be ANY VBA class
    Set oTR = New ToolsReferences   '* could be ANY VBA class

    '* instantiate my ATL project
    Dim oTest As GetContainingTypeLibTestLib.CoClassGetContainingTypeLib
    Set oTest = New GetContainingTypeLibTestLib.CoClassGetContainingTypeLib

    Dim iunkTypeLib As IUnknown
    Set iunkTypeLib = Nothing   '* not strictly required
    Call oTest.GetContainingTypeLib(oTR, iunkTypeLib)

End Sub

В Интернете очень мало информации, объясняющей номер исключения 0x800A88C1. Я думаю, что это команда Excel говорит «нет».


person S Meaden    schedule 04.09.2018    source источник
comment
Это нормально, когда информация о типе загружается не из статически скомпилированной библиотеки типов, а синтезируется на лету. Это относится к таким языкам, как VBA или JavaScript, где объекты полностью создаются во время выполнения.   -  person Igor Tandetnik    schedule 04.09.2018
comment
@IgorTandetnik: Я согласен, но VBA проходит этап компиляции.   -  person S Meaden    schedule 05.09.2018
comment
Конечно, это Excel говорит нет!. Документы не очень хороши, они говорят о сервере ITypeLib. Немного сверх того, на практике вам нужен код, который знает, как загрузить библиотеку типов и передать информацию из нее другому коду. У Excel действительно есть один, но он активен только в редакторе кода VBA. Мяч, который катится под капотом с помощью LoadTypeLib(). Он исчезает во время выполнения, библиотека типов больше не играет роли, когда скомпилированный код VBA уже знает, какие guids использовать. LoadTypeLib() - это курица и яйцо, очень хитроумно в VBA с автоматическим созданием компилятором файлов .oca.   -  person Hans Passant    schedule 05.09.2018
comment
@HansPassant Я так рад, что вы ответили, вы отличный эксперт ... У меня есть код для перебора типов, спасибо. Я думаю, что согласен с вами, что Excel делает это, потому что, когда книга ссылается на другую книгу, как еще работает Intellisense. Обидно, если, как вы говорите, что он исчезает во время выполнения. Что такое файлы .oca, пожалуйста?   -  person S Meaden    schedule 05.09.2018
comment
Эта глубина обсуждения для vba жизненно важна, поэтому я надеюсь, что будет сформирована какая-то форма ответа, включающая то, что обсуждается, чтобы мы могли легко найти и просмотреть его в будущем. +1   -  person QHarr    schedule 05.09.2018