COM-интерфейс, созданный ATL, наследует IDispatch, но позднее связывание не работает.

Это мой файл IDL. IFrame является двойным интерфейсом и наследует как IDispatch, так и IUnknown.

[
    object,
    uuid(C5AD0517-37FC-479C-9C7A-A063B17E4A2E),
    dual,
    nonextensible,
    pointer_default(unique)
]
    interface IFrame : IDispatch{
};
[
    uuid(F7D50952-4AF1-491B-B0AA-35083AEFA998),
    version(1.0),
]
library bdsCOMLib
{
    importlib("stdole2.tlb");
    [
        uuid(9C2E7E2D-A39C-4FE7-BEEB-3BF65F9D4C05)      
    ]
    coclass Frame
    {
        [default] interface IFrame;
    };
};

И это объявление класса CFrame, которое должно реализовать IFrame:

class ATL_NO_VTABLE CFrame :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CFrame, &CLSID_Frame>,
public IDispatchImpl<IFrame, &IID_IFrame, &LIBID_bdsCOMLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
    public:
        CFrame()
        {
        }

    DECLARE_REGISTRY_RESOURCEID(IDR_FRAME)


    BEGIN_COM_MAP(CFrame)
        COM_INTERFACE_ENTRY(IFrame)
        COM_INTERFACE_ENTRY(IDispatch)
    END_COM_MAP()



    DECLARE_PROTECT_FINAL_CONSTRUCT()

    HRESULT FinalConstruct()
    {
        return S_OK;
    }

    void FinalRelease()
    {
    }
};
OBJECT_ENTRY_AUTO(__uuidof(Frame), CFrame)

COM-сервер регистрируется и работает нормально, когда я использую объект Frame в VBA, но с помощью ранней привязки. Я хочу использовать этот объект с VBScript, поэтому мне нужна поздняя привязка.

Но позднее связывание сделать нельзя. Я прочитал о ситуации, и кажется, что ATL (и класс IDispatchImp) выполняют всю реализацию, необходимую для IDispatch, что дает мне возможность использовать объект с инструментами автоматизации (например, VBScript).

Однако на практике скрипт выдает ошибку «Элемент Active X не может быть создан». То же самое и в VBA, когда я пытаюсь выполнить раннее связывание.

Что я делаю не так? Я использую Visual Studio 2012 в 64-разрядной версии Windows 7, но мой COM-сервер 32-разрядный (и он зарегистрирован в системе).


person user3707763    schedule 08.07.2014    source источник
comment
В принципе, это хорошо и для VBScript. Однако ваш скриптовый хост должен иметь соответствующую разрядность. Если вы используете cscript, убедитесь, что вы запускаете 32-разрядную версию C:\Windows\SYSWOW64\cscript.exe для вашего 32-разрядного COM-сервера.   -  person Roman R.    schedule 08.07.2014
comment
@РоманР. Я думаю, что это не проблема здесь. VBA использует 32-битный хост, но поздняя привязка не работает. Ошибка связана с COM-сервером, я думаю, а не с клиентом.   -  person user3707763    schedule 08.07.2014
comment
Код неполный, и в выложенном вами фрагменте вряд ли есть что-то неправильное (при условии, что сервер имеет правильную регистрацию, включая библиотеку типов). Некоторые хосты могут ожидать, что вы реализуете определенные дополнительные интерфейсы, например. IProvideoClassIInfo. Ваша непосредственная стратегия отладки состоит в том, чтобы поставить точку останова в конструкторе, чтобы увидеть, создан ли экземпляр вашего класса. Затем, если да, вы видите, какие интерфейсы запрашиваются до того, как произойдет сбой. Если ваш конструктор не достигнут, значит, у вас проблема с регистрацией.   -  person Roman R.    schedule 08.07.2014
comment
Какая версия typelib объявлена ​​в .idl?   -  person sharptooth    schedule 08.07.2014
comment
@sharptooth разве это не версия (1.0)?   -  person user3707763    schedule 08.07.2014
comment
@ user3707763: Так и должно быть, но кто знает, что говорит ваш .idl.   -  person sharptooth    schedule 08.07.2014
comment
@sharptooth: эта часть цитируется выше, это 1.0   -  person Roman R.    schedule 08.07.2014
comment
@RomanR.: Действительно, я этого не заметил. Следующее, что выглядит странно, это то, что определение интерфейса находится вне определения библиотеки.   -  person sharptooth    schedule 08.07.2014
comment
@sharptooth, потому что у них разные uuid.   -  person user3707763    schedule 08.07.2014
comment
@ user3707763: Конечно, у них разные uuid, но во всех проектах, которые я видел, интерфейсы были объявлены внутри определения библиотеки.   -  person sharptooth    schedule 08.07.2014
comment
@sharptooth: Нет, это нормально, это поведение по умолчанию. Компилятор IDL будет включать в TLB все такие интерфейсы, на которые ссылается материал внутри библиотечного блока. Остальное будет хорошо компилироваться, будет доступно для кода C++, но не будет включено в TLB.   -  person Roman R.    schedule 08.07.2014
comment
Если ничего не помогает, вы можете поставить точки останова в IDispatchImpl методы и проверить, как они себя ведут. Скорее всего, вам понадобится Sleep() в конструкторе, чтобы у вас было время подключиться к нужному процессу.   -  person sharptooth    schedule 08.07.2014
comment
Используйте монитор процессов SysInternals для диагностики проблем с реестром. Если вы забудете зарегистрировать ProgId в вашем сценарии .rgs, это будет обычной ошибкой.   -  person Hans Passant    schedule 08.07.2014
comment
@HansPassant ProgID зарегистрирован в системе   -  person user3707763    schedule 08.07.2014
comment
Вам также необходимо определить интерфейс IFrame внутри библиотеки типов! Я не вижу интерфейс IFrame и не вижу его реализацию.   -  person xMRi    schedule 07.08.2014