MailItem.save() Method

MailItem.save() Method

Post by QXVzdGluIF » Sat, 12 Feb 2005 11:25:02


I am new to the groups. However I did read for two days (Sue does seem to
answer 90 percent of the questions)
I realize this is a VBA group but I am sure my C# code does not enter into
my question.
I create a new MailItem and just want to save it into a Folder other than
the olFolderDrafts.

Here is my starting code:

ApplicationClass o = new ApplicationClass();
NameSpace outlookNS = o.GetNamespace("MAPI");
MAPIFolder folder =
outlookNS.GetDefaultFolder(OlDefaultFolders.olFolderInbox);
Outlook.MailItem newItem = o.CreateItem(OlItemType.olMailItem) as MailItem;
newItem.Save();

I would like: |newItem.SaveAs(?? myFolder);| to work but,
SaveAs wants a string Path, plus the Object Type: OlDefaultFolders.


Thanks...
Austin
 
 
 

MailItem.save() Method

Post by Michael Ba » Sat, 12 Feb 2005 14:28:00

Hi Austin,

just call the Move after the Save method.

--
Viele Gre
Michael Bauer


"Austin Stephens" < XXXX@XXXXX.COM > wrote in

seem to
into >> my question. >> I create a new MailItem and just want to save it into a Folder other
than >> the olFolderDrafts. >> >> Here is my starting code: >> >> ApplicationClass o = new ApplicationClass(); >> NameSpace outlookNS = o.GetNamespace("MAPI"); >> MAPIFolder folder = >> outlookNS.GetDefaultFolder(OlDefaultFolders.olFolderInbox); >> Outlook.MailItem newItem = o.CreateItem(OlItemType.olMailItem) as
MailItem; >> gt; > newItem.Save();> >> > I would like: |newItem.SaveAs(?? myFolder);| to work bu>,
> SaveAs wants a string Path, plus the Object Type: OlDefaultFolder>. >> >>
> Thanks.>.
> Aust>n
>

 
 
 

MailItem.save() Method

Post by Dmitry Str » Sun, 13 Feb 2005 02:14:47

Or use MAPIFolder.Items.Add instead of Application.CreaterItem to begin
with.
Also don't forget that Move is a fucntion that returns the newly created
item in the target folder; it is not a sub.

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

MailItem.save() Method

Post by QXVzdGluIF » Sun, 13 Feb 2005 05:01:58

Michael,

Thank you! It now:
newItem.Save();
MAPIFolder targetFolder = outlookNS.PickFolder();
newItem.Move(targetFolder);
Dmitry,
It is an honor, sir!
For now Il let the user pick the folder. However, after beta I think Il
implement your suggestion and pick the folder myself.

As to the t is not a subreference; I in C# so it will be a try/catch
and Il ignore the return.

Thanks...
Austin



>> Or use MAPIFolder.Items.Add instead of Application.CreaterItem to begin >> with. >> Also don't forget that Move is a fucntion that returns the newly created >> item in the target folder; it is not a sub. >> >> Dmitry Streblechenko (MVP) >> http://www.yqcomputer.com/ >> OutlookSpy - Outlook, CDO >> and MAPI Developer Tool >>

>>>> Hi Austin, >>>> >>>> just call the Move after the Save method. >>>> >>>> -- >>>> Viele Gre >>>> Michael Bauer >>>> >>>> >>>> "Austin Stephens"<< XXXX@XXXXX.COM >> wrote in
>>>>> I am new to the groups. However I did read for two days (Sue does >>>> seem to >>>>> answer 90 percent of the questions) ?. >>>>> I realize this is a VBA group but I am sure my C# code does not enter >>>> into >>>>> my question. >>>>> I create a new MailItem and just want to save it into a Folder other >>>> than >>>>> the olFolderDrafts. >>>>> >>>>> Here is my starting code: >>>>> >>>>> ApplicationClass o = new ApplicationClass(); >>>>> NameSpace outlookNS = o.GetNamespace("MAPI"); >>>>> MAPIFolder folder = >>>>> outlookNS.GetDefaultFolder(OlDefaultFolders.olFolderInbox); >>>>> Outlook.MailItem newItem = o.CreateItem(OlItemType.olMailItem) as >>>> MailItem; >>>>> . >>>>> newItem.Save(); >>>>> >>>>> I would like: |newItem.SaveAs("???", myFolder);| to work but, >>>>> SaveAs wants a string Path, plus the Object Type: OlDefaultFolders. >>>>> >>>>> >>>>> Thanks... >>>>> Austin >>>>> >>>> >> >> >>
 
 
 

MailItem.save() Method

Post by Michael Ba » Mon, 14 Feb 2005 03:51:27

Hi Austin,

try/catch >> and Il ignore the return.

thats ok if you dont need to handle the item after it is moved.

--
Viele Gre
Michael Bauer


"Austin Stephens"<< XXXX@XXXXX.COM >> wrote in
>> Michael, >> >> Thank you! It now: >> newItem.Save(); >> MAPIFolder targetFolder = outlookNS.PickFolder(); >> newItem.Move(targetFolder); >> Dmitry, >> It is an honor, sir! >> For now Il let the user pick the folder. However, after beta I
think Il >> implement your suggestion and pick the folder myself. >> >> >> Thanks... >> Austin >> >>
>> >>>> Or use MAPIFolder.Items.Add instead of Application.CreaterItem to
begin >>>> with. >>>> Also don't forget that Move is a fucntion that returns the newly
created >>>> item in the target folder; it is not a sub. >>>> >>>> Dmitry Streblechenko (MVP) >>>> http://www.yqcomputer.com/ >>>> OutlookSpy - Outlook, CDO >>>> and MAPI Developer Tool >>>>

>>>>>> Hi Austin, >>>>>> >>>>>> just call the Move after the Save method. >>>>>> >>>>>> -- >>>>>> Viele Gre >>>>>> Michael Bauer >>>>>> >>>>>> >>>>>> "Austin Stephens"<< XXXX@XXXXX.COM >> wrote
in
>>>>>>> I am new to the groups. However I did read for two days (Sue
does >>>>>> seem to >>>>>>> answer 90 percent of the questions) ?. >>>>>>> I realize this is a VBA group but I am sure my C# code does not
enter >>>>>> into >>>>>>> my question. >>>>>>> I create a new MailItem and just want to save it into a Folder
other >>>>>> than >>>>>>> the olFolderDrafts. >>>>>>> >>>>>>> Here is my starting code: >>>>>>> >>>>>>> ApplicationClass o = new ApplicationClass(); >>>>>>> NameSpace outlookNS = o.GetNamespace("MAPI"); >>>>>>> MAPIFolder folder = >>>>>>> outlookNS.GetDefaultFolder(OlDefaultFolders.olFolderInbox); >>>>>>> Outlook.MailItem newItem = o.CreateItem(OlItemType.olMailItem) as >>>>>> MailItem; >>>>>>> . >>>>>>> newItem.Save(); >>>>>>> >>>>>>> I would like: |newItem.SaveAs("???", myFolder);| to work but, >>>>>>> SaveAs wants a string Path, plus the Object Type:
OlDefaultFolders. >>>>>>> >>>>>>> >>>>>>> Thanks... >>>>>>> Austin >>>>>>> >>>>>> >>>> >>>> >>>>
 
 
 

MailItem.save() Method

Post by Dmitry Str » Mon, 14 Feb 2005 08:05:22

nless of course you don't want to depend on the GC to release all COM
objects. I am not sure that an implicit COM object will be immediately
released. If you however store the returned object in a variable, you will
be able to call Marshal.ReleaseCOMObject.

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

"Michael Bauer" < XXXX@XXXXX.COM > wrote in message
news: XXXX@XXXXX.COM ...


 
 
 

MailItem.save() Method

Post by Jim Vierr » Tue, 15 Feb 2005 04:49:57

have found that you have to be careful on the release. If the object is
still processing a request it seems to get hung if release via
ReleaseComObject. The explicit calls shouldn't need releasing as the GC
will get them as soon as the reference count drops to zero but I don't
believe late bound objects are manages by the GC. Only the reference you
hold is under management. You shouldn't have to do the release under NET
1.1. Wouldn't you agree that the COM subsystem should handle all of that.

In my testing I found that an explicit call to the "release" would often
crash the object if it was Word, Outlook or Excel. I believe that there are
discussions in the KB about this but can't remember how to find them.

--
Jim Vierra
"Dmitry Streblechenko" < XXXX@XXXXX.COM > wrote in message
news: XXXX@XXXXX.COM ...


 
 
 

MailItem.save() Method

Post by Dmitry Str » Tue, 15 Feb 2005 05:15:39

o on all counts:
1. all languages have the ability to release COM objects immediately (e.g.
by setting a variable to Nothing in VB). If one of the objects hangs,
something's wrong with the object. I cannot recall any bugs in Office
related to COM objects hanging when released. Do you have any examples?
2. Explicit release calls are very much needed, especially if you are
running against an Exchange server and you are limited to 255 RPC
channels/process. Just try interating through a folder with a large number
of items... COM is not a native .Net API, and manual tweaking (such as using
ReleaseCOMObjects) is often needed.
3. Both early and late bound objects are managed by the GC in .Net. There is
absolutely no difference between the two kinds when it comes to their
lifetime management.
4. GC will release the COM objects whenever it feels like it, which may be
minutes later. And COM subsystem does not handle "all of that", GC and the
object itself do.
5. What KB articles do you refer to? Any sample code?

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

"Jim Vierra" < XXXX@XXXXX.COM > wrote in message
news: XXXX@XXXXX.COM ...


 
 
 

MailItem.save() Method

Post by Jim Vierr » Tue, 15 Feb 2005 05:30:38

imity - OK
Why then does a release - not an assignment to "Nothing" - cause the object
to hang in memory if there is a pending request.?
If I do this
'some language
dim o as object
set o = createobject("some.object") ' such as Word.Application

I have a "what" relationship to the actual object?
Is "o" the object - no.
Can I destroy "o" - yes - it's mine.
Why then do some objects - particularly Office object accessed via Interop -
refuse to shut down when released in this way if an operation is pending? If
no operation pending then they shut down correctly.

Same scenario not using NET (such as scripting) the issue seems to not
happen.

--
Jim Vierra
"Dmitry Streblechenko" < XXXX@XXXXX.COM > wrote in message
news:% XXXX@XXXXX.COM ...


 
 
 

MailItem.save() Method

Post by Dmitry Str » Tue, 15 Feb 2005 06:31:03

ee below

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

"Jim Vierra" < XXXX@XXXXX.COM > wrote in message
news: XXXX@XXXXX.COM ...

In VB6, setting an object to Nothing results in an immediate call to
IUnknown::Release. In .Net it simply adds the object to an internal GC list.
When GC feels it is time to release it (whenever that might be), it will
call IUnknown::Release. It is then up to the COM object's implementation
what it wants to do (GC has no say in this matter) - if the reference count
drops to 0, the COM object can kill itself. Or it can do something entirely
different.


It is a pointer to IDispatch. Or, to be fully precise, a pointer to an
inproc IDispatch proxy (furnished by the COM runtime) that talks to the
object's implementation in the word.exe process space.


Yes, it is.


It depends. If by "destroy" you mean release *your* reference to that
object - sure. If Word knows that there are outstanding references (some
other app can be referencing it), it will simply decrement its internal
reference counter (see above).


Because somee of them think that a user might still be working with the
object: imagine that your code creates an instance of Word.Application, a
user then starts a new document, then your app releases the COM object. Most
users will be extremely upset if Word were to disappear simply because your
app decided that it no longer needed a pointer.
You can argue what the exact behavior should be, but the important point is
that the COM object itself decides what to do based on whatever it thinks it
appropriate, .Net or GC has no say.



 
 
 

MailItem.save() Method

Post by Jim Vierr » Tue, 15 Feb 2005 11:47:56

xactly what I was getting at.

Now consider what happens when "I" have an outstanding call to an "o" and I
destroy it.

If I reference that object or if I trap on the call the COM thinks I am
still busy and COM does not release the object.

This happens frequently with Word and Outlook when called through Interop.
I don't know if it's supposed to do that or if it's a bug/mismatch in the
Interop when called from C#.

I haven't played with it as much as I should so I can't really give a good
set of examples. I decided to stay away from latebound access due to the
effect on Outlook 2003 and Word 2003.
I agree. GC should have no affect on COM objects only on the reference to
the proxy. The COM object should clean up any outstanding calls where the
caller has gone away.

If I set up a callback to Outlook - say "Item_Send" and erase the
application object at the end of the callback Outlook will never shutdown.
Shouldn't be able to do that wouldn't you agree?

--
Jim Vierra
"Dmitry Streblechenko" < XXXX@XXXXX.COM > wrote in message
news: XXXX@XXXXX.COM ...


 
 
 

MailItem.save() Method

Post by Dmitry Str » Tue, 15 Feb 2005 13:57:51

Below

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




I don't really understand what you mean by "I have an outstanding call to an
"o" and I destroy it.". To be able to call a method on a COM object, you
need to keep a reference to it, which means it is still referenced.
Unlike regular classes (.Net, C++, Delphi, etc), you do not destroy COM
objects. There is simply no way to do that. One of the basic COM principles
is that the COM object itself is responsible for its own destruction. Again,
COM object is not a class. Even if it looks like one (v-table, etc). You can
dereference the object, but you cannot destroy it.


I am not sure what you mean.. COM has absolutely no notion of "busy". You
call AddRef, the object increments its internal reference counter. You call
Release, it decrements it. If it drops down to 0, the object is supposed to
destroy itself. Or do whatever it pleases. There is no such thing as "busy",
especially when it comes to the code that consumes the COM object.


Again, it has nothing to do with .Net or COM. It is Office trying to be
smart and figure out whether it should kill itself or keep itself alive even
if you completely dereference it.
That logic is different in different versions of the Office or maybe
Windows, but it absolutely does not depend on who the caller is. COM objects
neither know nor care.



This is a sideeffect of how COM events are supported in .Net. Your event
handler is an object that keeps an internal reference to the COM object in
question. So even if you release your explicit variable, the object is still
referenced by the event handler. Strictly speaking GC should be able to
detect circular references (it does that for the .Net objects), but
apparently it does not work quite well with the COM objects.
 
 
 

MailItem.save() Method

Post by Michael Ba » Tue, 15 Feb 2005 16:43:26

Thanks, Dmitry. I forgot that wee talking about c# and I should have
been quiet, because I don know anything about c# :-)

--
Viele Gre
Michael Bauer




will
 
 
 

MailItem.save() Method

Post by Dmitry Str » Wed, 16 Feb 2005 02:08:10

Neither do I :-)
I just know not to use it in anything Outlook related...

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

MailItem.save() Method

Post by Jim Vierr » Wed, 16 Feb 2005 04:32:50

So we shouldn't use C# with Outlook? I was beginning to think the same
thing.

If you don't try to do late bound calls the C# access works well. The MS
examples don't work well as each of them has a missing piece of information
it seems. Took me 3 days to find the correct way to call
"MailIItem.Send()".

I also suspect that the misbehavior might be due to running under the
de *** in C#. Is this a good guess?

--
Jim Vierra