Avatar billede Broholm Novice
13. januar 2005 - 16:55 Der er 3 kommentarer og
1 løsning

Invoke af global funktion i typelib (appobject)

Koden nedenfor forklarer det meste... Bare opret en Win32 console app. med ATL understøttelse. Det er på engelsk, da jeg også har posted det i et engelsk forum... Af en eller anden grund så fejler den altid, når jeg kalder den funktion (+nogle andre).

-Broholm


// ATLGlobal.cpp : Defines the entry point for the console application.
//

/* Should do the same as the following .vbs file (which works)

Dim w

Set w = CreateObject("Word.Application")

MsgBox(w.CentimetersToPoints(0.5))

Set w = Nothing

*/

/* IDL for CentimetersToPoints is:

[id(0x00000173), helpcontext(0x09700173)]
HRESULT CentimetersToPoints(
[in] single Centimeters,
[out, retval] single* prop);

*/


//This is for demonstration purposes only - Pardon the hardcoding of method names and values, and forgetting to invoke Quit method.



#include "stdafx.h"

#define hrCheck(hr) if(FAILED(##hr)) { return -1;};

int _tmain(int argc, _TCHAR* argv[])
{
::CoInitialize(NULL);
{ //<-- Scope to force CComPtr destructors before ::CoUninitialize()
CComBSTR ProgId("Word.Application");
HRESULT hr;

CComPtr<IUnknown> pUnk;
hr = pUnk.CoCreateInstance(ProgId,NULL,CLSCTX_SERVER);
hrCheck(hr);

CComQIPtr<IDispatch> pDisp;
hr = pUnk.QueryInterface(&pDisp);
hrCheck(hr);

DISPID dispIdClass;
CComBSTR MethodName("CentimetersToPoints");
hr = pDisp->GetIDsOfNames(IID_NULL,&MethodName,1,LOCALE_USER_DEFAULT,&dispIdClass);
hrCheck(hr);


CComVariant vArg(0.5);
hr = vArg.ChangeType(VT_R4); //lpfuncdesc->lprgelemdescParam[0].tdesc.vt is 4 => VT_R4
hrCheck(hr);
DISPID dispidNamedArgs = -1;

DISPPARAMS dpArgs;
dpArgs.cArgs = 1;
dpArgs.cNamedArgs = 0;
dpArgs.rgvarg = &vArg;
dpArgs.rgdispidNamedArgs = &dispidNamedArgs;

EXCEPINFO e;
CComVariant vResult;
//vResult.ChangeType(VT_R4); //<--- Even tried this 
UINT puArgErr(0);

hr = pDisp->Invoke(dispIdClass,IID_NULL,LOCALE_USER_DEFAULT,DISPATCH_METHOD,&dpArgs,&vResult,&e,&puArgErr);
hrCheck(hr); //<--- Always fails! 

//I've also tried getting a pointer to the hidden _Global interface and invoking the method there... But same error.

};
::CoUninitialize();
return 0;
}
Avatar billede segmose Nybegynder
14. januar 2005 - 08:52 #1
Giver Invoke nogen fejl?
Avatar billede Broholm Novice
14. januar 2005 - 12:11 #2
Ja og nej... E_FAIL "Unspecified error"
Avatar billede Broholm Novice
14. januar 2005 - 13:48 #3
Her er lige et andet eksempel, hvir jeg går til flere yderligheder:

// ATLGlobal.cpp : Defines the entry point for the console application.
//

/* Should do the same as the following .vbs file (which works)

Dim w

Set w = CreateObject("Word.Application")

MsgBox(w.CentimetersToPoints(0.5))

Set w = Nothing   

*/

/* IDL for CentimetersToPoints is:

[id(0x00000173), helpcontext(0x09700173)]
HRESULT CentimetersToPoints(
                [in] single Centimeters,
                [out, retval] single* prop);

*/


//This is for demonstration purposes only -
//Pardon the hardcoding of method names and values, and forgetting to invoke Quit method.
//I'm also aware that not all resources is released

#include "stdafx.h"

#define hrCheck(hr) if(FAILED(##hr)) {  return -1;};

int _tmain(int argc, _TCHAR* argv[])
{
    ::CoInitialize(NULL);
    { //<-- Scope to force CComPtr destructors before ::CoUninitialize()
    CComBSTR ProgId("Word.Application");
    HRESULT hr;

    CComPtr<IUnknown> pUnk;
    hr = pUnk.CoCreateInstance(ProgId,NULL,CLSCTX_SERVER);
    hrCheck(hr);
   
    CComQIPtr<IDispatch> pDisp;
    hr = pUnk.QueryInterface(&pDisp);
    hrCheck(hr);

    DISPID dispIdClass;
    CComBSTR MethodName("CentimetersToPoints");
    hr = pDisp->GetIDsOfNames(IID_NULL,&MethodName,1,LOCALE_USER_DEFAULT,&dispIdClass);
    hrCheck(hr);

    CComVariant vArg(0.5);
    hr = vArg.ChangeType(VT_R4); //lpfuncdesc->lprgelemdescParam[0].tdesc.vt is 4 => VT_R4
    hrCheck(hr);
    DISPID dispidNamedArgs    = -1;
   
    DISPPARAMS dpArgs;
    dpArgs.cArgs            = 1;
    dpArgs.cNamedArgs        = 0;
    dpArgs.rgvarg            = &vArg;
    dpArgs.rgdispidNamedArgs = &dispidNamedArgs;

    EXCEPINFO e;
    CComVariant vResult;
    //vResult.ChangeType(VT_R4); //<--- Even tried this :-(
    UINT puArgErr(0);

    hr = pDisp->Invoke(dispIdClass,IID_NULL,LOCALE_USER_DEFAULT,DISPATCH_METHOD,&dpArgs,&vResult,&e,&puArgErr); //<-- FAILS with hr = E_FAIL
    if(FAILED(hr))
        std::cout << "Invoke failed" << std::endl;
    //Ok that one fails - now get the appobject coclass and invoke thru that interface
    //Get TypeLib
    CComPtr<ITypeInfo> pTI;
    hr = pDisp->GetTypeInfo(0,LOCALE_USER_DEFAULT,&pTI);
    CComQIPtr<ITypeLib> pTypeLib;
    UINT TLindex(0);
    hr = pTI->GetContainingTypeLib(&pTypeLib,&TLindex);
    hrCheck(hr);

    //Find CoClass'es in TypeLib - BTW Any comments on how to do this more efficient than a for-loop?
    UINT iTypeInfoCount = pTypeLib->GetTypeInfoCount();
    for(UINT i(0); i < iTypeInfoCount; ++i)               
    {
        TYPEKIND typeKind;                               
        hr = pTypeLib->GetTypeInfoType(i, &typeKind);
        hrCheck(hr);
        if(typeKind    != TKIND_COCLASS)
            continue;

        //Found a CoClass - now check for TYPEFLAG_FAPPOBJECT
        CComQIPtr<ITypeInfo> pAOTypeInfo;
        hr = pTypeLib->GetTypeInfo(i, &pAOTypeInfo);
        hrCheck(hr);

        TYPEATTR* pAOTypeAttr;
        hr = pAOTypeInfo->GetTypeAttr(&pAOTypeAttr);
        hrCheck(hr);
        if((pAOTypeAttr->wTypeFlags    & TYPEFLAG_FAPPOBJECT) != TYPEFLAG_FAPPOBJECT)
        {
            pAOTypeInfo->ReleaseTypeAttr(pAOTypeAttr);
            continue;
        };

        //Found AppObject
        CComBSTR name;
        hr = pTypeLib->GetDocumentation(i, &name, 0, 0,    0);
        hrCheck(hr);
       
        //Enumerate the coclass's interfaces (only one in this case)
        for(int    j(0); j    < pAOTypeAttr->cImplTypes; ++j)
        {
            //Get GUID of implemented interface
            CComQIPtr<ITypeInfo> pAOTypeInfoImpl;
            HREFTYPE hRefType;
            hr = pAOTypeInfo->GetRefTypeOfImplType(j,&hRefType);
            hrCheck(hr);
            hr = pAOTypeInfo->GetRefTypeInfo(hRefType,&pAOTypeInfoImpl);
            hrCheck(hr);
            TYPEATTR* pAOTypeAttrImpl;
            hr = pAOTypeInfoImpl->GetTypeAttr(&pAOTypeAttrImpl);
            hrCheck(hr);

            //Create instance of coclass, requesting the implemented interface
            CComPtr<IDispatch> pAODisp;
            hr = pAOTypeInfo->CreateInstance(NULL,pAOTypeAttrImpl->guid,(void**)&pAODisp);
            pAOTypeInfoImpl->ReleaseTypeAttr(pAOTypeAttrImpl);
            hrCheck(hr);

            //Get ID and Invoke
            hr = pAODisp->GetIDsOfNames(IID_NULL,&MethodName,1,LOCALE_USER_DEFAULT,&dispIdClass);
            hrCheck(hr);
            hr = pAODisp->Invoke(dispIdClass,IID_NULL,LOCALE_USER_DEFAULT,DISPATCH_METHOD,&dpArgs,&vResult,&e,&puArgErr);
            hrCheck(hr); //<---    Still fails! :-(

        };
        pAOTypeInfo->ReleaseTypeAttr(pAOTypeAttr);
    };
    };
    ::CoUninitialize();
    return 0;
}
Avatar billede Broholm Novice
14. januar 2005 - 19:35 #4
Jeg fandt selv fejlen... Det skulle være DISPATCH_METHOD|DISPATCH_PROPERTYGET
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester