Re: SaveChanges problem

Tech Tip: Click here to run a free scan for Windows Errors and optimize PC performance



Actually, I've trimmed down the success case even more. I don't have to
re-open the item, I just have to reapply the change and then call Save
again.

Mark

"Mark Smith" <sti@xxxxxxxxxxxxx> wrote in message
news:%23Qq1YggfIHA.484@xxxxxxxxxxxxxxxxxxxxxxx
Yup, I went into the addin dialog and unchecked every addin except for
OutlookSpy. I also closed down all running programs and even went into
the
process list and killed several to make sure as best I can that no other
programs would be talking to Outlook.

Some other things I discovered while testing this issue:
- If I edit the e-mail using OutlookSpy, then select another e-mail and go
back to the one in question, the problem doesn't occur. This makes it
sound
like the changes get made to disk or the cache and the other (disk or
cache) doesn't get changed. Then when I open up the item I get the out
of date one and thus generate an error when trying to save. And by
selecting a different e-mail the disk or cache gets flushed.
- Say you wrap up the sample code as a function: testSaveEmail(). Then
change the fail case to recurse, as follows:

if (FAILED(hr = pMailItem->Save())) {
testSaveEmail();
}

If I do this, the code works as expected, though the first Save() still
fails. Again, it sounds like a caching issue where re-opening the item
gets
the latest copy and then the Save() can succeed. I did try just calling
Save() again, but that didn't do the trick - it would succeed but the
changes wouldn't get saved. I do actually have to open the item again to
successfully change the item.

Mark

"Henry Gusakovsky" <h.ghusakovsky@xxxxxxxxx> wrote in message
news:a2957bbc-53ce-4b21-8879-014501a126fa@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Have you tried to disable all addins and extensions
Just to be sure that problem is reproduced with pure Outlook and your
code?

Regards
Henry
On Feb 28, 5:53 pm, "Mark Smith" <s...@xxxxxxxxxxxxx> wrote:
Thank you Charles for looking into this issue.

Unfortunately, Charles was unable to duplicate my problem. So I'm
hoping
someone else has some ideas. Here is the code for my trimmed down test
scenario. Note that all error handling was removed for clarity. Note
also
that no MAPI code is used here - it's all using OOM.

I'd like to point out that for some reason Charles' type libraries were
different than mine in that his GetItemFromID prototype only took 2
arguments. He was able to run my sample code by changing GetItemFromID
to
raw_GetItemFromID.

CComPtr<Outlook::_Application> pApplication;
CComPtr<Outlook::_NameSpace> pNamespace;
COleDispatchDriver oleDispDriver;
CLSID clsid;
LPUNKNOWN pUnk = NULL;
// attach to object in memory
if ((S_OK ==
CLSIDFromProgID(CString("Outlook.Application").AllocSysString(),
&clsid))
&&
(S_OK == GetActiveObject(clsid, NULL, &pUnk))) {
LPDISPATCH pDispatch = NULL;
pUnk->QueryInterface(IID_IDispatch, (void**)&pDispatch);
oleDispDriver.AttachDispatch(pDispatch);
pUnk->Release();
}
// otherwise initialize and attach to a new object
else {
oleDispDriver.CreateDispatch("Outlook.Application");
}

pApplication =
CComQIPtr<Outlook::_Application>(CComPtr<IUnknown>(oleDispDriver.m_lpDispatch));
pApplication->get_Session(&pNamespace);
CComPtr<IDispatch> pDisp;

pNamespace->GetItemFromID(CComBSTR("00000000DF185A07A45B30449EB33BA0D8CED2E864B15500"),
CComVariant(""), &pDisp);
CComQIPtr<Outlook::_MailItem> pMailItem(pDisp);
CComBSTR subject;
pMailItem->get_Subject(&subject);
pMailItem->put_Subject(subject);
HRESULT hr = S_OK;
if (FAILED(hr = pMailItem->Save())) {
CString str;
str.Format("Failed: 0x%x", hr);
MessageBox(str);
}

Here is the procedure to generate this error (this does require
OutlookSpy):
[] Start Outlook
[] Determine the entry ID of an item to test (I used one in the default
store - note the empty string for the store ID in the GetItemFromID
call)
[] Use OutlookSpy to modify a property of the item in question - I was
modifying PR_CONVERSATION_TOPIC, though I also tried modifying a custom
MAPI
property with the same result
[] Edit the sample code to use the entry ID selected.
[] Build and run the sample code - Save will fail with
MAPI_E_OBJECT_CHANGED
[] If you run the sample code again the Save call will succeed.

Note that this problem occurs the very first time you run the sample
code,
so it can't have anything to do with a leak in my code.

It's possible that this is being caused by OutlookSpy, however, I tested
this code and procedure with Outlook 2007, 2003, and 2000. In the first
two
cases the error occurred, but with Outlook 2000, no error occurred.
This
strongly suggests that the problem is occurring within Outlook and was
introduced sometime in Outlook XP or 2003.

Mark Smith

"Mark Smith" <s...@xxxxxxxxxxxxx> wrote in message

news:u0mhGLabIHA.4880@xxxxxxxxxxxxxxxxxxxxxxx

Our program integrates with Outlook both via MAPI and OOM for a couple
different reasons. The primary of which is that we are using both
MAPI
custom properties and OOM user defined fields (the user defined fields
code is not hit in this example). So I am unlikely to be able to
abandon
either.

We are experiencing this problem in house. However, the person who
experiences has not been able to duplicate it reliably. I have not
been
able to duplicate it normally, but I can when using Outlook Spy to
muck
around with them item in question's properties.

Both computers that we've seen this on are using Oultook 2007 without
Exchange - one with SP1 and one without. I have not yet tried older
Outlooks.

This code is in C++.

The basic scenario is very simple:
[] I open up both a MAPI and OOM connection to Outlook
[] Using NameSpace::GetItemFromID(), I open up the item in question
directly by entry and store IDs, which returns an IDispatch
[] Then I attach a MailItem using CComQIPtr<Outlook::_MailItem>
[] Then I retrieve the MAPI object for the item in question using
get_MAPIOBJECT()
[] I set a custom property to the MAPI object using
IMapiProp::SetProps()
[] Then call IMessage::SaveChanges(KEEP_OPEN_READWRITE)
[] Then call MailItem::Save()
[] Then all objects go out of scope, thus cleaning them up (every
object
is wrapped with a smart pointer (CComPtr or CComQIPtr, so it's
unlikely
that I'm leaking any of them)

In some cases SaveChanges() returns 0x80040109 and Save() returns
0xf7a40109. I understand 0x80040109 to indicate that the object has
been
changed and so the save will not happen. And I'm guessing that
0xf7a40109
is the same or similar.

This all executes very quickly - there is no UI in the middle or
anything
else blocking execution to introduce a large window of opportunity for
the
object to actually get changed out from under me.

As stated above, in order for me to reliably duplicate this I have to
use
Outlook Spy to go in and make changes to the item in question after
this
code executes once, but before the next time it is run on the same
item.
If I try to make changes using Outlook's UI I haven't been able to
generate this error. Here's the crazy part: in order to rule out a
leak
of an object on my part I've tried closing down my program completely,
restarting and attempting the same operation again. The error still
happens. And if I shut down Outlook at this point, it does completely
shut down on its own. Sometimes this is within a second or two, other
times it can take up to 20 seconds or so. So it doesn't look like a
leak
of an object on my part. In order to get this error to quit happening
once it starts, I have to shut Outlook down.

I haven't determined yet if the item is actually getting changed
between
the time the object is opened and the save occurs (which, as stated
before, should be a very short time).

As a quick fix, I tried changing SaveChanges() to take FORCE_SAVE.
That
does make the custom property get written to the item in question, but
then the next time I try to update this item I get an access denied
error.

I did also figure out that I don't have to call both SaveChanges() and
Save(). Calling just Save() is sufficient to save the properties to
the
item, but doing so does not alleviate the problem.

I also tried using MailItem::Close(olSave) instead of Mailtem::Save().
This results in the error occuring every other time the procedure is
run.
This is better, but still not a fix. What is different about using
MailItem::Close(olSave) instead of MailItem::Save() followed by
closing
the object?

This situation really does sound like I'm leaking something, but I've
carefully checked over my code and can't find any leaks. Plus the
reasons
described above lead me to conclude that this is not the issue. The
other
possibility that I've considered is that Outlook may be caching the
object
and then returning the same one back to me the next time around,
without
the changes made by Outlook Spy.

So the questions are:
1) Am I doing something obviously wrong?
2) Is there some known problem with mixing OOM and MAPI?
3) If Outlook is caching objects, is there some way to guarantee I get
the
latest copy of the object when I open it? I would think this would be
automatic, but something weird is happening here.
4) Is there some other possibility that I am missing?

I can provide code if that will help. I didn't initially because
there
is
a lot of it in several functions, so it will take a bit of work to get
it
consolidated and trimmed down enough for a post.

Mark Smith






.



Relevant Pages

  • Re: emailing attachments
    ... From the sample code, it ... looks like MAPI can create and send an email with attachments. ... I was a little worried with interfacing directly with Outlook, ... Amber ...
    (borland.public.delphi.thirdpartytools.general)
  • Re: How to replace an attachment from a file.wav to a winmail.dat
    ... And it will not have Outlook installed on. ... when the code tries to convert back from MAPI to MIME using the ... we created one stream object with the contents of the file using the ... and we created the new tnef stream using the OpenTnefStreamEx ...
    (microsoft.public.win32.programmer.messaging)
  • Re: What is next step to extracting PST contact items
    ... IMO mode doesn't really support Extended MAPI. ... We cut IMO mode in Outlook 2002. ... and MAPI Developer Tool ... An unexpected error has occurred. ...
    (microsoft.public.win32.programmer.messaging)
  • Re: SaveChanges problem
    ... Currently we have not found any known issue regarding using OOM and MAPI ... OutlookSpy - Outlook, CDO ... been able to duplicate it normally, but I can when using Outlook Spy ...
    (microsoft.public.win32.programmer.messaging)
  • Re: SaveChanges problem
    ... Currently we have not found any known issue regarding using OOM and MAPI ... OutlookSpy - Outlook, CDO ... been able to duplicate it normally, but I can when using Outlook Spy ...
    (microsoft.public.win32.programmer.messaging)