【问题标题】:How to retrieve the Interface ID of a COM class so that it can be passed to CoCreateInstance?如何检索 COM 类的接口 ID 以便可以将其传递给 CoCreateInstance?
【发布时间】:2011-01-19 18:48:31
【问题描述】:

我想以编程方式检索任何类的接口 ID,以便可以将其传递给 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();

【问题讨论】:

  • 是的,“老派”的东西很难再获得选票了。但至少这是供下一个人审查的! :D

标签: c++ windows com


【解决方案1】:

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

最简单的方法是使用#import

【讨论】:

  • 如果必须预先知道,那么我如何在 C++ 中编写 COM DLL 并通过 Server.CreateObject() 在 Classic ASP 中使用它?经典 ASP 似乎能够绑定到我的 DLL 并与之交互,从而允许我在我的类中调用函数。
  • 因为 ASP 要求一个众所周知的接口,IDispatch msdn.microsoft.com/en-us/library/ms221608.aspx
  • 没错。使用我回答中的问题:“您要调用哪个接口的方法?”答案是 IDispatch,因此您向 CoCreateInstance 请求该接口。然后,您可以使用 IDispatch 的方法来调用在编译时您不知道名称和参数的其他方法。
  • 甜蜜,IDispatch 就是答案!为什么不把它扔进遮阳篷,这样其他人就可以在不挖掘 cmets 的情况下找到它。万分感谢!
【解决方案2】:

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

换句话说,你打算把你创建的那个对象当作什么接口类型?你要调用哪个接口的方法?

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

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

obj->QueryInterface(riid, pInterface);

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-11-01
      • 1970-01-01
      • 2011-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多