windows 如何检索 COM 类的接口 ID,以便将其传递给 CoCreateInstance?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2313432/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 14:00:21  来源:igfitidea点击:

How to retrieve the Interface ID of a COM class so that it can be passed to CoCreateInstance?

c++windowscom

提问by NTDLS

I want to programaticly retrieve the Interface ID for any class so that I can pass it to CoCreateInstance. Any help is very much appreciated!!

我想以编程方式检索任何类的接口 ID,以便我可以将它传递给 CoCreateInstance。很感谢任何形式的帮助!!

See "How Do I Get This" below:

请参阅下面的“我如何获得它”:

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();

EDIT: Thanks for all of the help, seems to work perfectly now! :

编辑:感谢所有的帮助,现在似乎工作完美!:

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();

采纳答案by Remus Rusanu

You need to know upfront what interface you ask for. This you get from the product specifications, from SDK header files, or you can import the TLB of the COM object into your project.

您需要预先知道您要求的界面。这可以从产品规范、SDK 头文件中获得,或者您可以将 COM 对象的 TLB 导入到您的项目中。

the easisest way is to use #import

最简单的方法是使用#import

回答by Rob Kennedy

You already know it. It's going to be the compile-time output typethat you want the function to store in the pInterfacevariable that you've given it.

你已经知道了。这将是您希望函数存储在您提供的变量中的编译时输出类型pInterface

In other words, what interface type are you going to treat that object you've created as? Which interface's methods are you going to call on it?

换句话说,您要将创建的对象视为什么接口类型?你打算调用哪个接口的方法?

The type you get from CLSIDFromProgIDmight be any version of the interface, including one that didn't even exist at the time you compiled your code. You can usually assume that whatever version is available at run time also supports some lesser version that you know about at compile time. You ask the OS to instantiate an instance of the recent version, but then you also ask it to return a reference to the lesser version's interface — the one you know how to handle.

您从中获得的类型CLSIDFromProgID可能是接口的任何版本,包括在您编译代码时甚至不存在的类型。您通常可以假设运行时可用的任何版本也支持您在编译时知道的一些较小的版本。您要求操作系统实例化最新版本的实例,但随后您也要求它返回对较低版本界面的引用——您知道如何处理的界面。

The function calls QueryInterfaceon the object for you, using the type you requested, something like this:

该函数QueryInterface使用您请求的类型为您调用对象,如下所示:

obj->QueryInterface(riid, pInterface);

If you have nothing more specific to request, just use IUnknown.

如果您没有更具体的要求,请使用IUnknown.

回答by Dewfy

platform SDK is distributed with source code of OleView utility, t contains pretty good example to build tree of all possible CLSIDs and them names

平台 SDK 与 OleView 实用程序的源代码一起分发,t 包含很好的示例来构建所有可能的 CLSID 及其名称的树