天天看點

hr1 = 0x80020009 發生意外。

環境:win7 64位,vs2008,wps2013

錯誤代碼:

BOOL CWPSOper::ConvertToPdf(IDispatch* lpDoc,_bstr_t sTargetPath)
{
	CComVariant varParams[15];
        varParams[1].vt = VT_I4;
        varParams[1].iVal = 1;
        varParams[0].vt = VT_BYREF|*/VT_VARIANT;
        varParams[0].pvarVal = &(varParams[1]);
        CComVariant varRet, varRet2, varRet3;
        HRESULT hr1 = GetProperty(lpDoc, L"Application", &varRet);
        HRESULT hr2 = GetProperty(varRet.pdispVal, L"Documents", &varRet2);
        hr1 = InvokeN(varRet2.pdispVal, L"Item", varParams, 1, &varRet3);
}

HRESULT InvokeN(IDispatch *pDisp, LPCOLESTR lpszName, VARIANT *varParams, int nParams, VARIANT *pvarRet)
{   
    if(pDisp == NULL)
        return E_FAIL;   

    HRESULT hr;   
    DISPID dispid;   

    hr = pDisp->GetIDsOfNames(IID_NULL, (LPOLESTR*)&lpszName, 1, LOCALE_USER_DEFAULT, &dispid);   
    if (SUCCEEDED(hr))
    {   
        DISPPARAMS dispparams = { varParams, NULL, nParams, 0};   
        return pDisp->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL);   

    }
    return hr;   

} 
           

解決:

而通過vc添加typelib中類,通過wpsapi.dll生成CDocument,CDocuments,CApplication三個類,然後調試跟到oledisp2.cpp中的

 SCODE sc = m_lpDispatch->Invoke(dwDispID, IID_NULL, 0, wFlags,

        &dispparams, pvarResult, &excepInfo, &nArgErr);

發現dispparams的iVal值為0x00000001

而我的錯誤代碼中iVal值為0xcccc0001

然後源代碼改為varParams[1].lVal = 0x00000001;

結果就傳回正确值S_OK了

原因:顯而易見,variant是union類型, iVal隻是lVal中的後半段記憶體,但是com處理invoke調用應該統一使用long,不會又是long又是int

繼續閱讀