现在有一个COM接口,此接口有5个参数,但不能直接调用它,因为得不到此接口的IID,只所以只能使用Invoke,但不知道如何传这5个参数,请高手指点.

解决方案 »

  1.   

    不知你为何不能获得IID的接口,不过要用IDispatchImp::Invoke进行调用参数设计一般使用如下的模式:
    1、构造一个结构体;
    2、在结构体中包含你所需要传送的5个变量;
    3、创建结构体的实例和指针,把指针赋值给DISPPARAMS* pdispparams……在COM的服务端和调用端都调用这个结构,并对结构体进行操作。
      

  2.   

    VC调用COM接口,此接口有5个参数,只能使用Invoke调.
    不知道如何调,以下是我的代码,调用不成功.
    HRESULT CWriteProperty::CallAddMethod(IDispatchPtr pDisp,VARIANT rgvargName,VARIANT rgvargValue)
    {
    VARIANT vLinkToContent,vPropertyType;
    vLinkToContent.vt = VT_BOOL;
    vLinkToContent.boolVal = VARIANT_FALSE;
    vPropertyType.vt = VT_I2;
    vPropertyType.intVal = msoPropertyTypeString; DISPID dispid;
    DISPID dispdNamed = DISPATCH_METHOD; 
    DISPPARAMS dispparamsNoArgs = {NULL,NULL,0,0};
    dispparamsNoArgs.cArgs = 5;
    dispparamsNoArgs.rgvarg[0] = rgvargName;
    dispparamsNoArgs.rgvarg[1] = vLinkToContent;
    dispparamsNoArgs.rgvarg[2] = vPropertyType;
    dispparamsNoArgs.rgvarg[3] = rgvargValue;
    // dispparamsNoArgs.rgvarg[4] = NULL;
    dispparamsNoArgs.cNamedArgs = 1;
    dispparamsNoArgs.rgdispidNamedArgs = &dispdNamed;// dispparamsNoArgs[1].cArgs = 1;
    // dispparamsNoArgs[1].rgvarg = &vLinkToContent;
    // dispparamsNoArgs[1].cNamedArgs = 1;
    // dispparamsNoArgs[1].rgdispidNamedArgs = &dispdNamed;
    //
    // dispparamsNoArgs[2].cArgs = 1;
    // dispparamsNoArgs[2].rgvarg = &vPropertyType;
    // dispparamsNoArgs[2].cNamedArgs = 1;
    // dispparamsNoArgs[2].rgdispidNamedArgs = &dispdNamed;
    //
    // dispparamsNoArgs[3].cArgs = 1;
    // dispparamsNoArgs[3].rgvarg = rgvargValue;
    // dispparamsNoArgs[3].cNamedArgs = 1;
    // dispparamsNoArgs[3].rgdispidNamedArgs = &dispdNamed;
    //
    // dispparamsNoArgs[4].cArgs = 0;
    // dispparamsNoArgs[4].rgvarg = NULL;
    // dispparamsNoArgs[4].cNamedArgs = 0;
    // dispparamsNoArgs[4].rgdispidNamedArgs = NULL;
    BSTR bstrMember(L"Add");
    // Code omitted for brevity.
    HRESULT hresult = pDisp->GetIDsOfNames(IID_NULL, &bstrMember, 1, 
      LOCALE_USER_DEFAULT, &dispid); hresult = pDisp->Invoke(
            dispid,
            IID_NULL,
            LOCALE_USER_DEFAULT,
            DISPATCH_METHOD,
            &dispparamsNoArgs, NULL, NULL, NULL);
    return hresult;
    }
      

  3.   

    hediant(何)
    能不能给个具体的代码参考一下.
      

  4.   

    而且我也不知道如何获得此接口的IID,
    IDispatchPtr Properties = pWordDoc->GetCustomDocumentProperties();
    得到此接口的IDispatchPtr ,但从IDispatchPtr如何得到DocumentPropertiesPtr指针呢?
    直接查询也是空的,如果直接得是空的,不明白为什么?
    所以只能使用Invoke
      

  5.   

    IDispatch接口(的invoke方法)一般是给脚本解释器一类的程序用的,如果你的com对象支持双接口(dual-interface)的话,最好转成方法调用的方式来调它,这样比较简单。如果不支持双接口,那只能用invoke了。invoke调用的时候参数传递挺麻烦的。看样子好象你的参数传递不对。你说的不成功有什么错误提示么?
      

  6.   

    但从IDispatchPtr如何得到DocumentPropertiesPtr指针呢?
    ----------
    如果是dual-interface,可以直接强制转成DocumentPropertiesPtr。
      

  7.   

    没有什么错误提示,就是添加属性不成功.
    有没有调用Invoke传多个参数的例子?
      

  8.   

    可以给出你调的这个接口方法的完整IDL么?要不我没法去判断你给的参数到底对不对啊。
      

  9.   

    我调用的就是Add方法,它的定义如下
    Function Add(Name As String, LinkToContent As Boolean, [Type], [Value], [LinkSource]) As DocumentProperty
        Office.DocumentProperties 的成员
      

  10.   

    你给的是vb的接口吧,需要idl的定义才行。
      

  11.   

    [
      odl,
      uuid(2DF8D04D-5BFA-101B-BDE5-00AA0044DE52),
      helpcontext(0x0003d09a)
    ]
    interface DocumentProperties : IDispatch {
        [propget, helpcontext(0x0003d09b)]
        IDispatch* _stdcall Parent();
        [propget, helpcontext(0x0003d09c)]
        HRESULT _stdcall Item(
                        [in] VARIANT Index, 
                        [in, lcid] long lcid, 
                        [out, retval] DocumentProperty** ppIDocProp);
        [propget, helpcontext(0x0003d09d)]
        HRESULT _stdcall Count([out, retval] long* pc);
        [helpcontext(0x0003d09e)]
        HRESULT _stdcall Add(
                        [in] BSTR Name, 
                        [in] VARIANT_BOOL LinkToContent, 
                        [in, optional] VARIANT Type, 
                        [in, optional] VARIANT Value, 
                        [in, optional] VARIANT LinkSource, 
                        [in, lcid] long lcid, 
                        [out, retval] DocumentProperty** ppIDocProp);
        [propget]
        HRESULT _stdcall _NewEnum([out, retval] IUnknown** ppunkEnum);
        [propget, helpcontext(0x0003d0a1)]
        HRESULT _stdcall Application([out, retval] IDispatch** ppidisp);
        [propget, helpcontext(0x0003d0a2)]
        HRESULT _stdcall Creator([out, retval] long* plCreator);
    };
    就是要调用DocumentProperties这个接口的Add方法
      

  12.   

    但从IDispatchPtr如何得到DocumentPropertiesPtr指针呢? 
    ---------- 
    如果是dual-interface,可以直接强制转成DocumentPropertiesPtr。 
    智能指针重载了运算符=,只要把IDispatchPtr的值赋给DocumentPropertiesPtr定义的变量,它自然就回调用运算符=,这样就能得到DocumentPropertiesPtr的指针了
      

  13.   

    看了楼主贴的IDL,这个接口不是dual-interface的。所以,只能通过dispatch接口来调用了。
      

  14.   

    能不能给个调用Add这个方法的dispatch的例子呀!!!!
    谢谢!
      

  15.   

    VARIANTARG v[10];
    v[0].vt = VT_I4, v[0].lVal = ...;
    v[1].vt = ...  , v[1].... = ...;
    ...DISPPARAMS dispparam = {v, ...}
      

  16.   

    sinkileu 
    能否说的详细点,谢谢!!!!
      

  17.   

    #include "stdafx.h"
    #include <ole2.h>// 
    // AutoWrap() - Automation helper function...
    // 
    HRESULT AutoWrap(int autoType, VARIANT *pvResult, IDispatch *pDisp, 
          LPOLESTR ptName, int cArgs...) 
    {
          // Begin variable-argument list...
          va_list er;
          va_start(er, cArgs);      if(!pDisp) {
                MessageBox(NULL, "NULL IDispatch passed to AutoWrap()", 
                           "Error", 0x10010);
                _exit(0);
          }      // Variables used...
          DISPPARAMS dp = { NULL, NULL, 0, 0 };
          DISPID dispidNamed = DISPID_PROPERTYPUT;
          DISPID dispID;
          HRESULT hr;
          char buf[200];
          char szName[200];
       
          // Convert down to ANSI
          WideCharToMultiByte(CP_ACP, 0, ptName, -1, szName, 256, NULL, NULL);
       
          // Get DISPID for name passed...
          hr = pDisp->GetIDsOfNames(IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT, 
                                    &dispID);
          if(FAILED(hr)) {
                sprintf(buf, 
                        "IDispatch::GetIDsOfNames(\"%s\") failed w/err0x%08lx",
                        szName, hr);
                MessageBox(NULL, buf, "AutoWrap()", 0x10010);
                _exit(0);
                return hr;
          }
       
          // Allocate memory for arguments...
          VARIANT *pArgs = new VARIANT[cArgs+1];      // Extract arguments...
          for(int i=0; i<cArgs; i++) {
                pArgs[i] = va_arg(er, VARIANT);
          }
       
          // Build DISPPARAMS
          dp.cArgs = cArgs;
          dp.rgvarg = pArgs;
       
          // Handle special-case for property-puts!
          if(autoType & DISPATCH_PROPERTYPUT) {
                dp.cNamedArgs = 1;
                dp.rgdispidNamedArgs = &dispidNamed;
          }
       
          // Make the call!
          hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, autoType, 
                             &dp, pvResult, NULL, NULL);
          if(FAILED(hr)) {
                sprintf(buf,
                        "IDispatch::Invoke(\"%s\"=%08lx) failed w/err 0x%08lx", 
                        szName, dispID, hr);
                MessageBox(NULL, buf, "AutoWrap()", 0x10010);
                _exit(0);
                return hr;
          }
          // End variable-argument section...
          va_end(er);
       
          delete [] pArgs;
       
          return hr;}int main(int argc, char* argv[])
    {
          // Initialize COM for this thread...
          CoInitialize(NULL);      // Get CLSID for Word.Application...
          CLSID clsid;
          HRESULT hr = CLSIDFromProgID(L"Word.Application", &clsid);
          if(FAILED(hr)) {
                ::MessageBox(NULL, "CLSIDFromProgID() failed", "Error", 
                             0x10010);
                return -1;
          }      // Start Word and get IDispatch...
          IDispatch *pWordApp;
          hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, 
                                IID_IDispatch, (void **)&pWordApp);
          if(FAILED(hr)) {
                ::MessageBox(NULL, "Word not registered properly", 
                             "Error", 0x10010);
                return -2;
          }      // Make Word visible
          {
                VARIANT x;
                x.vt = VT_I4;
                x.lVal = 1;
                AutoWrap(DISPATCH_PROPERTYPUT, NULL, pWordApp, L"Visible", 1, 
                         x);
          }      // Get Documents collection
          IDispatch *pDocs;
          {
                VARIANT result;
                VariantInit(&result);
                AutoWrap(DISPATCH_PROPERTYGET, &result, pWordApp, L"Documents", 
                         0);            pDocs = result.pdispVal;
          }      // Call Documents.Open() to open C:\Doc1.doc
          IDispatch *pDoc;
          {
                VARIANT result;
                VariantInit(&result);
                VARIANT x;
                x.vt = VT_BSTR;
                x.bstrVal = ::SysAllocString(L"C:\\Doc1.doc");            AutoWrap(DISPATCH_METHOD, &result, pDocs, L"Open", 1, x);
                pDoc = result.pdispVal;
                SysFreeString(x.bstrVal);
          }      // Get BuiltinDocumentProperties collection
          IDispatch *pProps;
          {
                VARIANT result;
                VariantInit(&result);
                AutoWrap(DISPATCH_PROPERTYGET, &result, pDoc, 
                         L"BuiltinDocumentProperties", 0);
                pProps = result.pdispVal;
          }      // Get "Subject" from BuiltInDocumentProperties.Item("Subject")
          IDispatch *pPropSubject;
          {
                VARIANT result;
                VariantInit(&result);
                VARIANT x;
                x.vt = VT_BSTR;
                x.bstrVal = ::SysAllocString(L"Subject");
                AutoWrap(DISPATCH_PROPERTYGET, &result, pProps, L"Item", 1, x);
                pPropSubject = result.pdispVal;
                SysFreeString(x.bstrVal);
          }      // Get the Value of the Subject property and display it
          {
                VARIANT result;
                VariantInit(&result);
                AutoWrap(DISPATCH_PROPERTYGET, &result, pPropSubject, L"Value",
                         0);
                char buf[512];
                wcstombs(buf, result.bstrVal, 512);
                ::MessageBox(NULL, buf, "Subject", 0x10000);
     
          }      // Set the Value of the Subject DocumentProperty
          {
                VARIANT x;
                x.vt = VT_BSTR;
                x.bstrVal = ::SysAllocString(L"This is my subject");
                AutoWrap(DISPATCH_PROPERTYPUT, NULL, pPropSubject, L"Value", 1, 
                         x);
                ::MessageBox(NULL, 
                             "Subject property changed, examine document.",
                             "Subject", 0x10000);
                SysFreeString(x.bstrVal);
          }      // Get CustomDocumentProperties collection
          IDispatch *pCustomProps;
          {
                VARIANT result;
                VariantInit(&result);
                AutoWrap(DISPATCH_PROPERTYGET, &result, pDoc, 
                         L"CustomDocumentProperties", 0);
                pCustomProps = result.pdispVal;
          }      // Add a new property named "CurrentYear"
          {   
                VARIANT parm1, parm2, parm3, parm4;
                parm1.vt = VT_BSTR;
                parm1.bstrVal = SysAllocString(L"CurrentYear");
                parm2.vt = VT_BOOL;
                parm2.boolVal = false;
                parm3.vt = VT_I4;
                parm3.lVal = 1; //msoPropertyTypeNumber = 1
                parm4.vt = VT_I4;
                parm4.lVal = 1999;            AutoWrap(DISPATCH_METHOD, NULL, pCustomProps, L"Add", 4, parm4,
                         parm3, parm2, parm1);
                ::MessageBox(NULL, "Custom property added, examine document.",
                             "Custom Property", 0x10000);
                SysFreeString(parm1.bstrVal);
          }      // Get the custom property "CurrentYear" and delete it
          IDispatch *pCustomProp;
          {
                VARIANT result;
                VariantInit(&result);
                VARIANT x;
                x.vt = VT_BSTR;
                x.bstrVal = ::SysAllocString(L"CurrentYear");
                AutoWrap(DISPATCH_PROPERTYGET, &result, pCustomProps, L"Item",
                         1, x);
                pCustomProp = result.pdispVal;
                SysFreeString(x.bstrVal);
                AutoWrap(DISPATCH_METHOD, NULL, pCustomProp, L"Delete", 0);
                ::MessageBox(NULL,
                             "Custom property removed, examine document.",
                             "Custom Property", 0x10000);
          }
      
          // Close the document without saving changes and quit Word
          {
                VARIANT x;
                x.vt = VT_BOOL;
                x.boolVal = false;
                AutoWrap(DISPATCH_METHOD, NULL, pDoc, L"Close", 1, x);
                AutoWrap(DISPATCH_METHOD, NULL, pWordApp, L"Quit", 0);
          }      // Cleanup
          pCustomProp->Release();
          pCustomProps->Release();
          pPropSubject->Release();
          pProps->Release();
          pDoc->Release();
          pDocs->Release();
          pWordApp->Release();
          // Uninitialize COM for this thread...
          CoUninitialize();      return 0;
    }
      

  18.   

    #include "stdafx.h"
    #include <ole2.h>// 
    // AutoWrap() - Automation helper function...
    // 
    HRESULT AutoWrap(int autoType, VARIANT *pvResult, IDispatch *pDisp, 
          LPOLESTR ptName, int cArgs...) 
    {
          // Begin variable-argument list...
          va_list er;
          va_start(er, cArgs);      if(!pDisp) {
                MessageBox(NULL, "NULL IDispatch passed to AutoWrap()", 
                           "Error", 0x10010);
                _exit(0);
          }      // Variables used...
          DISPPARAMS dp = { NULL, NULL, 0, 0 };
          DISPID dispidNamed = DISPID_PROPERTYPUT;
          DISPID dispID;
          HRESULT hr;
          char buf[200];
          char szName[200];
       
          // Convert down to ANSI
          WideCharToMultiByte(CP_ACP, 0, ptName, -1, szName, 256, NULL, NULL);
       
          // Get DISPID for name passed...
          hr = pDisp->GetIDsOfNames(IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT, 
                                    &dispID);
          if(FAILED(hr)) {
                sprintf(buf, 
                        "IDispatch::GetIDsOfNames(\"%s\") failed w/err0x%08lx",
                        szName, hr);
                MessageBox(NULL, buf, "AutoWrap()", 0x10010);
                _exit(0);
                return hr;
          }
       
          // Allocate memory for arguments...
          VARIANT *pArgs = new VARIANT[cArgs+1];      // Extract arguments...
          for(int i=0; i<cArgs; i++) {
                pArgs[i] = va_arg(er, VARIANT);
          }
       
          // Build DISPPARAMS
          dp.cArgs = cArgs;
          dp.rgvarg = pArgs;
       
          // Handle special-case for property-puts!
          if(autoType & DISPATCH_PROPERTYPUT) {
                dp.cNamedArgs = 1;
                dp.rgdispidNamedArgs = &dispidNamed;
          }
       
          // Make the call!
          hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, autoType, 
                             &dp, pvResult, NULL, NULL);
          if(FAILED(hr)) {
                sprintf(buf,
                        "IDispatch::Invoke(\"%s\"=%08lx) failed w/err 0x%08lx", 
                        szName, dispID, hr);
                MessageBox(NULL, buf, "AutoWrap()", 0x10010);
                _exit(0);
                return hr;
          }
          // End variable-argument section...
          va_end(er);
       
          delete [] pArgs;
       
          return hr;}int main(int argc, char* argv[])
    {
          // Initialize COM for this thread...
          CoInitialize(NULL);      // Get CLSID for Word.Application...
          CLSID clsid;
          HRESULT hr = CLSIDFromProgID(L"Word.Application", &clsid);
          if(FAILED(hr)) {
                ::MessageBox(NULL, "CLSIDFromProgID() failed", "Error", 
                             0x10010);
                return -1;
          }      // Start Word and get IDispatch...
          IDispatch *pWordApp;
          hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, 
                                IID_IDispatch, (void **)&pWordApp);
          if(FAILED(hr)) {
                ::MessageBox(NULL, "Word not registered properly", 
                             "Error", 0x10010);
                return -2;
          }      // Make Word visible
          {
                VARIANT x;
                x.vt = VT_I4;
                x.lVal = 1;
                AutoWrap(DISPATCH_PROPERTYPUT, NULL, pWordApp, L"Visible", 1, 
                         x);
          }      // Get Documents collection
          IDispatch *pDocs;
          {
                VARIANT result;
                VariantInit(&result);
                AutoWrap(DISPATCH_PROPERTYGET, &result, pWordApp, L"Documents", 
                         0);            pDocs = result.pdispVal;
          }      // Call Documents.Open() to open C:\Doc1.doc
          IDispatch *pDoc;
          {
                VARIANT result;
                VariantInit(&result);
                VARIANT x;
                x.vt = VT_BSTR;
                x.bstrVal = ::SysAllocString(L"C:\\Doc1.doc");            AutoWrap(DISPATCH_METHOD, &result, pDocs, L"Open", 1, x);
                pDoc = result.pdispVal;
                SysFreeString(x.bstrVal);
          }      // Get BuiltinDocumentProperties collection
          IDispatch *pProps;
          {
                VARIANT result;
                VariantInit(&result);
                AutoWrap(DISPATCH_PROPERTYGET, &result, pDoc, 
                         L"BuiltinDocumentProperties", 0);
                pProps = result.pdispVal;
          }      // Get "Subject" from BuiltInDocumentProperties.Item("Subject")
          IDispatch *pPropSubject;
          {
                VARIANT result;
                VariantInit(&result);
                VARIANT x;
                x.vt = VT_BSTR;
                x.bstrVal = ::SysAllocString(L"Subject");
                AutoWrap(DISPATCH_PROPERTYGET, &result, pProps, L"Item", 1, x);
                pPropSubject = result.pdispVal;
                SysFreeString(x.bstrVal);
          }      // Get the Value of the Subject property and display it
          {
                VARIANT result;
                VariantInit(&result);
                AutoWrap(DISPATCH_PROPERTYGET, &result, pPropSubject, L"Value",
                         0);
                char buf[512];
                wcstombs(buf, result.bstrVal, 512);
                ::MessageBox(NULL, buf, "Subject", 0x10000);
     
          }      // Set the Value of the Subject DocumentProperty
          {
                VARIANT x;
                x.vt = VT_BSTR;
                x.bstrVal = ::SysAllocString(L"This is my subject");
                AutoWrap(DISPATCH_PROPERTYPUT, NULL, pPropSubject, L"Value", 1, 
                         x);
                ::MessageBox(NULL, 
                             "Subject property changed, examine document.",
                             "Subject", 0x10000);
                SysFreeString(x.bstrVal);
          }      // Get CustomDocumentProperties collection
          IDispatch *pCustomProps;
          {
                VARIANT result;
                VariantInit(&result);
                AutoWrap(DISPATCH_PROPERTYGET, &result, pDoc, 
                         L"CustomDocumentProperties", 0);
                pCustomProps = result.pdispVal;
          }      // Add a new property named "CurrentYear"
          {   
                VARIANT parm1, parm2, parm3, parm4;
                parm1.vt = VT_BSTR;
                parm1.bstrVal = SysAllocString(L"CurrentYear");
                parm2.vt = VT_BOOL;
                parm2.boolVal = false;
                parm3.vt = VT_I4;
                parm3.lVal = 1; //msoPropertyTypeNumber = 1
                parm4.vt = VT_I4;
                parm4.lVal = 1999;            AutoWrap(DISPATCH_METHOD, NULL, pCustomProps, L"Add", 4, parm4,
                         parm3, parm2, parm1);
                ::MessageBox(NULL, "Custom property added, examine document.",
                             "Custom Property", 0x10000);
                SysFreeString(parm1.bstrVal);
          }      // Get the custom property "CurrentYear" and delete it
          IDispatch *pCustomProp;
          {
                VARIANT result;
                VariantInit(&result);
                VARIANT x;
                x.vt = VT_BSTR;
                x.bstrVal = ::SysAllocString(L"CurrentYear");
                AutoWrap(DISPATCH_PROPERTYGET, &result, pCustomProps, L"Item",
                         1, x);
                pCustomProp = result.pdispVal;
                SysFreeString(x.bstrVal);
                AutoWrap(DISPATCH_METHOD, NULL, pCustomProp, L"Delete", 0);
                ::MessageBox(NULL,
                             "Custom property removed, examine document.",
                             "Custom Property", 0x10000);
          }
      
          // Close the document without saving changes and quit Word
          {
                VARIANT x;
                x.vt = VT_BOOL;
                x.boolVal = false;
                AutoWrap(DISPATCH_METHOD, NULL, pDoc, L"Close", 1, x);
                AutoWrap(DISPATCH_METHOD, NULL, pWordApp, L"Quit", 0);
          }      // Cleanup
          pCustomProp->Release();
          pCustomProps->Release();
          pPropSubject->Release();
          pProps->Release();
          pDoc->Release();
          pDocs->Release();
          pWordApp->Release();
          // Uninitialize COM for this thread...
          CoUninitialize();      return 0;
    }