0

我们使用 Outlook 对象模型如下读取所有 Outlook 联系人:

  • Outlook 对象模型
  • 微软 Office 2010 64 位
  • Windows 7旗舰版

   #import "mso.dll" named_guids
    #import "msoutl.olb" no_namespace
    ...
    ...
    void OutlookFeaturesImpl::getContactsFromOutlook()
    {
        _NameSpacePtr pNameSpace = m_ApplicationPtr->GetNamespace(_bstr_t("MAPI"));
        ....
        MAPIFolderPtr pFolder = pNameSpace->GetDefaultFolder(olFolderContacts);
        if( pFolder )
        {
            ....
            _ItemsPtr pItems = pFolder->GetItems();
            ....
            _ContactItemPtr contact = pItems->Find(bstrFilter);
            if( contact )
            {
                collectContactDetails(contact)
            }
        }
    }

    void OutlookFeaturesImpl::collectContactDetails( _ContactItemPtr pContact )
    {
        // The following 2 lines work fine. No Outlook security popup.
        _bstr_t bstrFirstName = pContact->GetFirstName();
        _bstr_t bstrLastName = pContact->GetLastName();

        // The following calls to get Email address and Properties trigger the Outlooks' security prompt since they are part of the "Outlook security object model guard" as you may see from this link: 
        // http://www.vbforums.com/showthread.php?402086-FAQ-s-OD-Why-do-I-get-an-Outlook-Security-Prompt
        _bstr_t emailAddType = pContact->GetEmail1AddressType();
        _bstr_t bstrEmailAddress = pContact->GetEmail1Address();
        _PropertyAccessorPtr p = pContact->GetPropertyAccessor();
    }

为了摆脱 Outlook 安全弹出消息,我在互联网上找到了一些解决方案,如下所示:


   void OutlookFeaturesImpl::collectContactDetails( _ContactItemPtr pContact )
    {
        CComQIPtr pIMessage;
        // we should use late binding when calling GetMAPIOBJECT()
        CComQIPtr pIDispatch(pContact);
        OLECHAR FAR* szMember = L"MAPIOBJECT";
        DISPID dispID;
        hr = pIDispatch->GetIDsOfNames( IID_NULL, &szMember, 1, LOCALE_USER_DEFAULT, &dispID );
        if( SUCCEEDED(hr) )
        {
            DISPPARAMS params = {0, 0, 0, 0};
            params.cArgs = 0;
            _variant_t varResult;

            hr = pIDispatch->Invoke( dispID, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, ¶ms, &varResult, NULL, NULL );
            if( SUCCEEDED(hr) )
            {
                pIMessage = varResult; // pIMessage will be NULL after this assignment
            }
        }

        if( pIMessage ) // It is NULL and hence does not go inside
        {
            LPSPropTagArray lpNamedPropTags = NULL;
            MAPINAMEID NamedID = {0};
            LPMAPINAMEID lpNamedID = &NamedID;
            NamedID.lpguid = (LPGUID)&PSETID_Address;
            NamedID.ulKind = MNID_ID;
            NamedID.Kind.lID = dispidEmailOriginalDisplayName;

            hr = pIMessage->GetIDsFromNames(1, &lpNamedID, NULL, &lpNamedPropTags);

            if (SUCCEEDED(hr) && lpNamedPropTags)
            {
                SPropValue* pPropValue = NULL;
                SPropTagArray sPropTagArray;
                sPropTagArray.cValues = 1;
                sPropTagArray.aulPropTag[0] = CHANGE_PROP_TYPE(lpNamedPropTags->aulPropTag[0],PT_STRING8);
                ULONG cProps = 0;

                hr = pIMessage->GetProps(&sPropTagArray, NULL, &cProps, &pPropValue);

                if (SUCCEEDED(hr) && 1 == cProps && pPropValue && PT_STRING8 == PROP_TYPE(pPropValue[0].ulPropTag) && pPropValue[0].Value.lpszA)
                {
                    _bstr_t bstrEmail1Address = pPropValue->Value.lpszA;
                }
            }
        }
    }

注意:这些是上面代码中使用的魔术字符串:


    #define dispidEmailOriginalDisplayName 0x8084
    const GUID PSETID_Address = {0x00062004, 0x0000, 0x0000, {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}};

问题是如何将 Outlook 对象模型与我们现有的代码(如上面的代码块所示)一起使用,以避免 Outlook 安全弹出窗口。

请在这些代码块内的评论中查看我们的发现。

4

1 回答 1

0

查看OutlookSpy的联系人- 单击 IMessage 按钮,查看您尝试检索的属性。

调用 GetProps 时,可以对 PR_GIVEN_NAME 和 PR_SURNAME 进行硬编码(这些不是命名属性)。对于 Email1AddressType 和 Email1Address,您需要使用 OutlookSpy 显示的适当 GUID 和 id 来首先确定属性标签(使用 GetIDsFromNames)。

于 2013-03-28T14:13:01.433 回答