Outlook MAPI in C++ application: Find contacts by name RRS feed

  • Question

  • Hi,

    I am not sure this is the correct forum, sorry if it is not...

    I have a C++ application to retrieve Outlook contacts: (local & exchange) users & distribution lists)

    I got an interface file 'msoutl.tlh' by using :

    #import "C:\Program Files (x86)\Common Files\microsoft shared\OFFICE15\mso.dll" named_guids
    #import "c:\Program Files (x86)\Microsoft Office\Office15\MSOUTL.OLB" no_namespace rename("Folder", "OlkFolder") rename("CopyFile", "OlkCopyFile") rename("GetOrganizer", "GetOrganizerAE")

    There I have all Outlook MAPI classes I can use

    With that, I can get all contacts from Outlook client(removed NULL and HRESULT checks) :

    _ApplicationPtr pApp;
    _NameSpacePtr _nsPtr = pApp->GetNamespace(_bstr_t("MAPI"));
    AddressListsPtr lists = _nsPtr->GetAddressLists();
    AddressListPtr list;
    char s[256];

    for (int i = 1; i <= lists->GetCount(); i++)
    list = lists->Item(i);
    AddressEntries* pAddrEntries = nullptr;
    AddressEntryPtr addEntryPtr = pAddrEntries->GetFirst();
    while (addEntryPtr)
    _ExchangeUserPtr pExchangeUser = nullptr;
    BSTR bstrPropName = nullptr;
    BSTR bstrPropAddr = nullptr;
    BSTR bstrSMTPAddr = nullptr;
    OlAddressEntryUserType userType;
    AddressEntriesPtr pAaddrEntries = nullptr;

    userType = addEntryPtr->GetAddressEntryUserType();

    switch (userType)
    case olExchangeUserAddressEntry: // 0
    sprintf(s, "EXCHANGE USER: %S (%S) \n", (WCHAR*)bstrPropName, (WCHAR*)bstrSMTPAddr);
    case olExchangeDistributionListAddressEntry: // 1
    if (S_OK == addEntryPtr->get_Members(&pAaddrEntries))
    _ExchangeDistributionListPtr exchangeDistrList = nullptr;
    sprintf(s, "EXCHANGE DISTRIBUTION LIST: %S (%S) - %d members \n", (WCHAR*)bstrPropName, (WCHAR*)bstrSMTPAddr, pAaddrEntries->GetCount());

    case olOutlookContactAddressEntry: // 10
    sprintf(s, "OUTLOOK CONTACT: %S (%S) \n", (WCHAR*)bstrPropName, (WCHAR*)bstrPropAddr);
    case olOutlookDistributionListAddressEntry: // 11
    sprintf(s, "OUTLOOK DISTRIBUTION LIST: %S - %d members \n", (WCHAR*)bstrPropName, pAaddrEntries->GetCount());
    default: break;

    This works perfectly (i have all contacts retrieved from Outlook).

    My problem is to resolve names (i need to filter by text), to list only those users which match.

    I could do it loading all users & looping, but with lots of contacts would be really slow

    And I can see there are methods for that, such as Find or Restrict. But I have no success.

    Once i have a list, i have:

    MAPIFolderPtr mapiFolder = list->GetContactsFolder();
    if (mapiFolder)
    _ItemsPtr folderItems = mapiFolder->Items;
    if (folderItems)
    _Item* pItems;
    BSTR bstrPropID = A2BSTR("*");
    HRESULT hr = folderItems->raw_Restrict(bstrPropID, &pItems);

    I have 2 problems:
        - Only in the Outlook Local contacts list i get a valid MAPIFolderPtr item (other lists such as exchange users returns NULL)
        - When I have MAPIFolderPtr, mapiFolder->Items returns a valid value (number of contacts in this list), but pItems is NULL

    I tried also with 
    but i got an exception ('Condition is not valid') in both cases

    And with 
    IDispatch * pDisp;
    folderItems->raw_Find(bstrPropID, &pDisp);
    but pDisp is NULL;

    Any help to resolve names in Outlook Contact lists?


    • Edited by ddonate Wednesday, August 21, 2019 11:27 AM
    Wednesday, August 21, 2019 11:18 AM