2012-04-18 3 views
2

Я пытаюсь написать плагин для стороннего продукта. Это принимает форму родной C++ DLL, которая реализует указанный интерфейс из поставляемой библиотеки типов. Мой плагин загружается успешно, и методы, описанные интерфейсом, вызывают в ожидаемых точках, я могу записать файл журнала из моего плагина и запросить веб-службу, насколько это хорошо.COM Interop - Участник не найден

Однако, для моего плагина, который запрашивает основную программу, метод Initialize() передает интерфейс IDispatch. Я пытаюсь использовать этот интерфейс с некоторым кодом, как это:

Initialize(LPDISPATCH pDispArchivingControl) { 
    LPOLESTR ptName = L"currentVaultId"; 
    HRESULT hr= pDispArchivingControl->GetIDsOfNames(IID_NULL, &ptName, 1, 
         LOCALE_USER_DEFAULT, &dispID); 
    // add parameters, etc 
    hr = pDispArchivingControl->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, 
        DISPATCH_METHOD, &dp, pvResult, NULL, NULL); 
    // hr = 0x80020003 Member not found. 
} 

Первая секция, GetIDsOfNames(), делает то, что я думаю, что он должен, т.е. положить имена методов из документации программы в ptName дает мне разные значения в dispID - 15, 27 и так далее.

Второй раздел, Invoke(), всегда возвращает HRESULT 0x80020003 (Member not found).

Я нашел некоторые решения, перечисленные здесь: HOWTO: Troubleshoot "Member Not Found" 0x80020003 Error. Для разрешения 1 я попробовал как DISPATCH_METHOD, так и DISPATCH_PROPERTYGET в качестве четвертого параметра. Правильно ли я предполагаю, что 2 и 3 не могут применяться ко мне, поскольку я возвращаю значения обратно в dispID? Я не уверен, как это изменить.

Теперь у меня есть идеи, и Google больше не помогает мне - может ли кто-нибудь предложить, что делать дальше?


ОБНОВЛЕНИЕ: Это то, что один из методов выглядит в оле. Я не мог найти его в TreeView, но смог открыть его с помощью File> View TypeLib ...

method seen in oleview

+1

Не похоже на метод. Мы не можем видеть dp, это фактически индексированное свойство? Почему вы используете позднюю привязку, когда у вас есть библиотека типов? Посмотрите на него с Oleview.exe –

+0

@HansPassant Я использую позднюю привязку, потому что я не знаю, что я делаю :) Я довольно новичок в C++ и COM. Я также попытался использовать #import с библиотекой типов, но не смог понять, как подключить к нему переданный интерфейс. Я попытался создать экземпляр и назначить ему интерфейс, который компилируется, но дает «недопустимый указатель» во время выполнения. Является ли #import лучше для этой ситуации? или что-то другое? –

+1

Импорт должен создать интерфейс 'IArchivingControl' и, возможно, даже класс интеллектуальных указателей ATL' IArchivingControlPtr' ATL, если вам повезет. Если у вас есть умный указатель, просто попробуйте назначить ему IDispatch и посмотреть, получится ли у вас ненулевой объект, с которым вы можете позвонить. Если у вас нет умного указателя, попробуйте вызвать 'QueryInterface' в IDispatch с помощью IID_IArchivingControl и он должен создать для вас интерфейс IArchivingControl. Не забудьте «освободить» их обоих, когда закончите. – Rup

ответ

1

Правильный ответ на этот вопрос, учитывая Гансом Passant и Руп в комментариях, является не использовать позднюю привязку, но до #import библиотеки типов.

Я положил это в stdafx.h:

#import "ArchivingControl.tlb" raw_interfaces_only, raw_native_types, named_guids, auto_search 

И это в моем файле .cpp:

ArchivingControl::IArchivingControlPtr JTArchivingControlPtr; 
STDMETHODIMP CMyClass::Initialize(LPDISPATCH pDispArchivingControl) 
{ 
    JTArchivingControlPtr = pDispArchivingControl; 
    return S_OK; 
} 
STDMETHODIMP CMyClass::OtherFunction() 
{ 
    BSTR pVaultId; 
    JTArchivingControlPtr->get_currentVaultId(&pVaultId); 
    return S_OK; 
} 

А теперь все работает хорошо, плюс у меня есть способ меньше кода сейчас - спасибо!