Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Howto: Create contact programmatically from ExchClientExt?

0 views
Skip to first unread message

Jim Irwin

unread,
Jan 17, 2007, 1:38:01 PM1/17/07
to
I have an exchange client extension, and I'm using the outlook object model
successfully within it. However, creating a contact is causing problems:

Given: _ApplicationPtr m_pOutlookApp;

and making this call:

IDispatch* pContact = m_pOutlookApp->CreateItem(olContactItem);

creating the contact fails. I've also tried:

HRESULT hr = m_pOutlookApp->raw_CreateItem(olContactItem, &pDispatch);

Using this I can see that the error code is 0x9ac1010e (what is that?). If
I use the same code (either style) with olMailItem or olAppointmentItem, the
code succeeds.

Any thoughts? As an alternate solution, does anyone have sample code that
shows the creation of a contact using MAPI? I already have the Contact Table
(I have an advise sink on it). I'm guessing it's not too tough from there,
but I'm not a MAPI programmer.

Regards, Jim

Dmitry Streblechenko

unread,
Jan 17, 2007, 3:52:02 PM1/17/07
to
What kind of store are you using and when exactly do you call this?

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool

"Jim Irwin" <JimI...@discussions.microsoft.com> wrote in message
news:C27D8D6C-8C16-4E54...@microsoft.com...

Jim Irwin

unread,
Jan 17, 2007, 4:13:00 PM1/17/07
to
The store is an ost. The call is being made from its own thread. That
thread waits a little while after Outlook starts before attempting the
operation.

More info -- As part of my project, my client wished to extend the standard
Outlook "Contacts" form. I created that form, and I figured out how to
install it as the default form for Contacts. If I do not have that form
installed as the default form, then CreateItem does succeed. But then
pContact->Save() fails <sigh>.

I did find this snippet of code on the Internet. It seems to be creating a
contact via MAPI:

hr = m_pAddrBook->OpenEntry(ulEntryID, lpEntryID, NULL,
MAPI_MODIFY, &ulObjType, &lpUnk);

lpContainer = (LPABCONT)lpUnk;

//
char szDisplayName[128] = "test";
char szGivenName[128]= "test";
char szAddrType[]= "SMTP";
char szMailAddr[128]= "te...@test.net";

SPropValue arrProp[4];
memset(arrProp, 0, sizeof(SPropValue)*4);

arrProp[0].ulPropTag = PR_ADDRTYPE;
arrProp[0].Value.lpszA = szAddrType;
arrProp[1].ulPropTag = PR_DISPLAY_NAME;
arrProp[1].Value.lpszA = szDisplayName;
arrProp[2].ulPropTag = PR_EMAIL_ADDRESS;
arrProp[2].Value.lpszA = szMailAddr;
arrProp[3].ulPropTag = PR_SURNAME;
arrProp[3].Value.lpszA = szGivenName;

//
LPMAPIPROP lpProp = NULL;
hr = lpContainer->CreateEntry(0, NULL, 0, &lpProp);

Unfortunately the call to CreateEntry fails...

Regards, Jim

Dmitry Streblechenko

unread,
Jan 17, 2007, 5:52:19 PM1/17/07
to
That code creates an *address book entry* (IMailUser) which is not at all
the same as an IPM.Contact *message* (IMessage) in one of the Contact
folders.
You will need to use IMAPIFolder::CreateMessage(), then set all the
undocumented named properties - look at existing contact with MFCMAPI or
OutlookSpy, also see http://www.cdolive.com/cdo10.htm andd scroll to
"Outlook Contact Properties"

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool

"Jim Irwin" <JimI...@discussions.microsoft.com> wrote in message

news:660FDF93-3B24-43F0...@microsoft.com...

Jim Irwin

unread,
Jan 18, 2007, 1:55:01 PM1/18/07
to
Thanks, Dmitry. I now have basic code that works (it even works when my
custom form is in place):

Outlook::_NameSpacePtr pMapi = m_pOutlookApp->GetNamespace(_T("MAPI"));
ATLASSERT(pMapi);

Outlook::MAPIFolderPtr pContactsFolder =
pMapi->GetDefaultFolder(Outlook::olFolderContacts);
ATLASSERT(pContactsFolder);

LPMAPIFOLDER pFolder = NULL;
HRESULT hr = pContactsFolder->get_MAPIOBJECT((IUnknown**)&pFolder);

LPMESSAGE pContact = NULL;
hr = pFolder->CreateMessage(NULL, 0, &pContact);

#define NUMPROPS 5
SPropValue props[NUMPROPS];
memset(props, 0, sizeof(SPropValue)*NUMPROPS);

props[0].ulPropTag = PR_SURNAME;
props[0].Value.LPSZ = _T("Irwin");
props[1].ulPropTag = PR_GIVEN_NAME;
props[1].Value.LPSZ = _T("Rocky");
props[2].ulPropTag = PR_DISPLAY_NAME;
props[2].Value.LPSZ = _T("Rocky Irwin");
props[3].ulPropTag = PR_MESSAGE_CLASS;
props[3].Value.LPSZ = _T("IPM.Contact");
props[4].ulPropTag = PROP_TAG(PT_TSTRING, 0x8041);
props[4].Value.LPSZ = _T("Irwin, Rocky");

hr = pContact->SetProps(NUMPROPS, props, NULL);

if(SUCCEEDED(hr))
{
hr = pContact->SaveChanges(0);
}

if(hr == MAPI_E_OBJECT_CHANGED)
{
hr = pContact->SaveChanges(FORCE_SAVE);
}

if(pContact) pContact->Release();
if(pFolder) pFolder->Release();

I obviously have more properties to add. I can see one significant problem
already, and that's the email addresses. Email1Address, for example, has an
Email1EntryID property. What is that, and how do I handle it?

Dmitry Streblechenko

unread,
Jan 18, 2007, 7:07:35 PM1/18/07
to
For an SMTP one-off adrress, you can either create the entry id
programmatically (it format is dpcumented on MSDN) or call
IAddrBook::CreateOneOff.

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool

"Jim Irwin" <JimI...@discussions.microsoft.com> wrote in message

news:BDE7F47F-49B3-409C...@microsoft.com...

Jim Irwin

unread,
Jan 19, 2007, 5:46:03 PM1/19/07
to
Thanks, Dmitry. It's been a bit of a struggle today, but it appears that I
finally have everything working. I appreciate your help.
0 new messages