Как получить идентификатор интерфейса класса COM, чтобы его можно было передать в CoCreateInstance? - PullRequest
10 голосов
/ 22 февраля 2010

Я хочу программно получить идентификатор интерфейса для любого класса, чтобы я мог передать его в 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();

Ответы [ 3 ]

3 голосов
/ 22 февраля 2010

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

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

3 голосов
/ 22 февраля 2010

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

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

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

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

obj->QueryInterface(riid, pInterface);

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

2 голосов
/ 22 февраля 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...