Получить IID из имени интерфейса в C ++? (VS 2010 автоматизация)

Учитывая имя COM-интерфейса в виде строки, как мне получить соответствующий IID, чтобы я мог вызвать QueryInterface ()?

Например:

// Attempt to cast IDispatch referenced by pDisp to an ICommandBarButton

char *interface_name = "ICommandBarButton";
IID iid;

<<< code to get the iid for interface_name goes here >>>
hr = pDisp->QueryInterface(iid, &interface);

Конечно, это предполагает, что имена интерфейсов уникальны для всей системы, в противном случае требуется больше контекста. Контекст заключается в том, что у меня есть механизм сценариев для автоматизации VS 2010, и мне нужно выполнять приведение типов между типами на основе имен интерфейсов, которые считываются из сценария в виде строк. У меня уже есть IDispatch * для объекта, который нужно преобразовать.

РЕДАКТИРОВАТЬ:

Пользователь Альф прокомментировал, что мне не нужно этого делать, и я был бы рад этого не делать. Используя ITypeLib, я определил, что мой IDispatch (созданный CommandBarControls.Add (msoButton)) является CommandBarControl. Мне нужен IDispatch для CommandBarButton, чтобы я мог получить доступ к свойствам, относящимся к кнопкам, таким как свойство Style - CommandBarControl IDispatch не распознает это свойство. В моем IDispatch, AFAIK, поддерживаются следующие интерфейсы:

Interface:CommandBarControl  GUID:43FD5911-7BAC-4BDC-AB6C-2DE65B5C0233
  Interface:IDispatch  GUID:00020400-0000-0000-C000-000000000046
    Interface:IUnknown  GUID:00000000-0000-0000-C000-000000000046

Сгенерировано, как показано ниже. CommandBarButton здесь не указан, поэтому хотелось бы, чтобы кто-нибудь показал мне, как выполнить это приведение, используя только механизмы времени выполнения IDispatch.

Экспериментальный код:

void
GetTypeInfo(ITypeInfo *pTypeInfo, int indent, char *&p)
{
    BSTR        olename;
    TYPEATTR    *typeattr;
    HRESULT     hr;

    hr = pTypeInfo->GetDocumentation(MEMBERID_NIL, &olename, NULL, NULL, NULL);
    if (hr == S_OK)
    {
        for (int i = 0; i < indent; i++)
            *p++ = ' ';
        p += sprintf(p, "Interface:");
        int len = SysStringLen(olename);
        for (int i = 0; i < len; i++)
            *p++ = (char)olename[i];
        *p++ = ' ';
        SysFreeString(olename);
    }

    hr = pTypeInfo->GetTypeAttr(&typeattr);
    if (hr == S_OK)
    {
        p += sprintf(p, " GUID:");
        for (int i = 0; i < 4; i++)
            p += sprintf(p, "%02X", ((unsigned char*)&typeattr->guid.Data1)[3-i]);
        *p++ = '-';
        for (int i = 0; i < 2; i++)
            p += sprintf(p, "%02X", ((unsigned char*)&typeattr->guid.Data2)[1-i]);
        *p++ = '-';
        for (int i = 0; i < 2; i++)
            p += sprintf(p, "%02X", ((unsigned char*)&typeattr->guid.Data3)[1-i]);
        *p++ = '-';
        for (int i = 0; i < 2; i++)
            p += sprintf(p, "%02X", typeattr->guid.Data4[i]);
        *p++ = '-';
        for (int i = 2; i < 8; i++)
            p += sprintf(p, "%02X", typeattr->guid.Data4[i]);
        *p++ = '\n';
        for (int i = 0; i < typeattr->cImplTypes; i++)
        {
            HREFTYPE reftype;
            ITypeInfo   *pTypeInfo2;
            hr = pTypeInfo->GetRefTypeOfImplType(i, &reftype);
            if (hr == S_OK)
            {
                hr = pTypeInfo->GetRefTypeInfo(reftype, &pTypeInfo2);
                if (hr == S_OK)
                {
                    GetTypeInfo(pTypeInfo2, indent + 2, p);
                    pTypeInfo2->Release();
                }
            }
        }
        pTypeInfo->ReleaseTypeAttr(typeattr);
    }
}


void
GetDispatchInfo(IDispatch *pDisp)
{
    char        buffer[16384];
    char        *p = buffer;
    UINT        ticount;
    HRESULT     hr;

    hr = pDisp->GetTypeInfoCount(&ticount);
    if (hr == S_OK)
    {
        for (UINT ti = 0; ti < ticount; ti++)
        {
            ITypeInfo *pTypeInfo;
            hr = pDisp->GetTypeInfo(ti, 0, &pTypeInfo);
            if (hr == S_OK)
            {
                GetTypeInfo(pTypeInfo, 0, p);
                pTypeInfo->Release();
            }
        }
    }
    *p = 0;
    OutputDebugString(buffer);
}

person Chungzuwalla    schedule 23.09.2014    source источник
comment
обычные механизмы связывания интерфейс-uuid работают только во время компиляции. поддержка сценариев основана на IDispatch и библиотеках типов. вы не используете для этого QueryInterface (за исключением самого IDispatch), вы используете механизмы времени выполнения IDispatch. вот для чего он нужен. почему бы не использовать это.   -  person Cheers and hth. - Alf    schedule 24.09.2014
comment
Спасибо, Альф, я изменил вопрос.   -  person Chungzuwalla    schedule 24.09.2014
comment
Это невозможно. Единственное, что волнует COM, - это {guid}. Название интерфейса - это ускользающая деталь, которую никогда не понимают программисты. Удобство программирования, оно быстро исчезает, когда вам нужно взаимодействовать с другой программой. Все называют это IMyInterface или какой-нибудь скучный вариант этого. Это не сработает, интерфейсы должны быть глобально уникальными. ГУ в гид.   -  person Hans Passant    schedule 24.09.2014
comment
Также не совсем то, что вы просили, но вы можете рассмотреть возможность использования ProgID: visualbasic.freetutes.com/learn-vb6-advanced/ Lesson4 / p35.html   -  person FoggyDay    schedule 24.09.2014


Ответы (2)


Хорошо, исходя из приведенных выше комментариев, я думаю, что исходный вопрос (глобальное преобразование имени интерфейса в GUID) невозможен.

Другими словами, интерпретатор Visual Basic, представленный такими командами, как:

control = commandBar.Controls.Add(MsoControlType.msoControlButton)
button = DirectCast(control, CommandBarButton)

полагается на что-то другое, а не на поиск строки CommandBarButton в некоторой общесистемной таблице. И это что-то, похоже, находится где-то внутри механизмов времени выполнения IDispatch и связанной с ним библиотеки типов. По-видимому, есть способ воспроизвести то, что здесь делает VB, используя некоторую библиотеку типов voodoo. Но исходный вопрос задан не так ...

РЕДАКТИРОВАТЬ:

Я нашел способ решения моей проблемы и опубликовал ответ на свой вопрос:

IDispatch возвращает DISP_E_UNKNOWNNAME для CommandBarButton.Style

Вкратце, запрос к IDispatch для IUnknown, а затем повторный запрос к IUnknown для IDispatch возвращает другой IDispatch, который, по-видимому, предназначен для наиболее производного класса (в данном случае CommandBarButton). Библиотеки типов Voodoo не нужны. Надеюсь, это кому-то поможет.

person Chungzuwalla    schedule 24.09.2014
comment
Реквизит для того, чтобы дать ответ после его нахождения. - person Medinoc; 16.12.2014

Если интерфейс зарегистрирован (обычно для маршаллинга), есть вероятность, что вы найдете его в реестре в разделе HKCR \ Interface. К сожалению, интерфейсы, которые там есть, зарегистрированы IID, поэтому, если вы хотите найти IID по имени, вам придется выполнить линейный поиск.

И даже тогда это не будет гарантированно работать (регистрация интерфейса не является обязательной, и я даже не уверен, что имя интерфейса используется при регистрации).

person Medinoc    schedule 24.09.2014