Как получить идентификатор интерфейса COM-класса, чтобы он мог быть передан CoCreateInstance?

Я хочу программно получить идентификатор интерфейса для любого класса, чтобы передать его в CoCreateInstance. Любая помощь очень ценится!

См. "Как мне это получить" ниже:

HRESULT hResult;
CLSID ClassID;
void *pInterface;

if(!(hResult = SUCCEEDED(CoInitialize(NULL))))
{
    return 1;
}

if(S_OK == CLSIDFromProgID(OLESTR("Scripting.FileSystemObject"), &ClassID))
{
    hResult = CoCreateInstance(ClassID, NULL, CLSCTX_INPROC_SERVER,
        <<How Do I Get This?>>, (LPVOID *)&pInterface);
}

CoUninitialize();

РЕДАКТИРОВАТЬ: Спасибо за всю помощь, кажется, отлично работает сейчас!:

HRESULT hResult;
CLSID ClassID;
IClassFactory *pClf;
void *pVdb;

if(!(hResult = SUCCEEDED(CoInitialize(NULL))))
{
    return 1;
}

if(SUCCEEDED(CLSIDFromProgID(OLESTR("Scripting.FileSystemObject"), &ClassID))
{
    IDispatch *pDispatch;

    if(SUCCEEDED(CoCreateInstance(ClassID, NULL, CLSCTX_INPROC_SERVER,
            IID_IDispatch, (void **)&pDispatch))
    {
        OLECHAR *sMember = L"FileExists";

        DISPID idFileExists;

        if(SUCCEEDED(pDispatch->GetIDsOfNames(
                IID_NULL, &sMember, 1, LOCALE_SYSTEM_DEFAULT, &idFileExists))
        {
            unsigned int puArgErr = 0;

            VARIANT VarResult;
            EXCEPINFO pExcepInfo;

            VariantInit(&VarResult); 
            VariantInit(&pExcepInfo); 

            DISPPARAMS pParams;
            memset(&pParams, 0, sizeof(DISPPARAMS)); 
            pParams.cArgs = 1; 

            VARIANT Arguments[1];
            VariantInit(&Arguments[0]); 

            pParams.rgvarg = Arguments; 
            pParams.cNamedArgs = 0;
            pParams.rgvarg[0].vt = VT_BSTR;
            pParams.rgvarg[0].bstrVal = SysAllocString(L"C:\\Test.txt");

            hResult = pDispatch->Invoke(  
                idFileExists,
                IID_NULL,
                LOCALE_SYSTEM_DEFAULT,
                DISPATCH_METHOD,
                &pParams,
                &VarResult,
                &pExcepInfo,
                &puArgErr
            );

            SysFreeString(pParams.rgvarg[0].bstrVal);

            printf("File Exists? %d\n", abs(VarResult.boolVal));
        }

        pDispatch->Release();
    }
}

CoUninitialize();

Ответ 1

Вам нужно знать, какой интерфейс вы запрашиваете. Это вы получаете из спецификации продукта, из файлов заголовков SDK или можете импортировать TLB объекта COM в свой проект.

Самый простой способ - использовать # import

Ответ 2

Вы уже это знаете. Это будет тип вывода времени компиляции, который вы хотите сохранить в переменной pInterface, которую вы указали.

Другими словами, какой тип интерфейса вы собираетесь обрабатывать созданный вами объект? Какие методы интерфейса вы собираетесь называть?

Тип, который вы получаете из CLSIDFromProgID, может быть любой версией интерфейса, включая тот, который даже не существовал при компиляции вашего кода. Обычно можно предположить, что любая версия доступна во время выполнения, а также поддерживает меньшую версию, о которой вы знаете во время компиляции. Вы попросите ОС создать экземпляр последней версии, но затем вы также попросите его вернуть ссылку на интерфейс меньшей версии - тот, с которым вы знаете, как обращаться.

Функция вызывает QueryInterface объекта для вас, используя запрошенный вами тип, например:

obj->QueryInterface(riid, pInterface);

Если у вас нет более конкретного запроса, просто используйте IUnknown.

Ответ 3

платформа SDK распространяется с исходным кодом утилиты OleView, t содержит довольно хороший пример для построения дерева всех возможных CLSID и их имен