Accessing Outlook while addin is running

  • Thread starter Thread starter Pradeep Singh
  • Start date Start date
P

Pradeep Singh

I'm trying to process all the emails of a folder using a COM addin. I
get the folder (MAPIFolderPtr). From that I can get mails using
GetItems. This whole loop of going through mails takes quite a while.
And unfortunately Outlook does not respond to keyboard commands ( e.g.
ctrl N) during this, also the preview pane does not change even if I choose
another e-mail ( mouse is working). Is this a known issue with COM
addins or I need to take care of something special to avoid this.

Another issue is, if I fire print (->PrintOut) on any item this call
is not honoured until I finish all the processing of the folder and
return from my COM adding control.
It would be great if someone could help me or point me to right
direction.


Kind Regards,
Pradeep
 
If you're running a tight code loop that takes a lot of time that's to be
expected. Either call the process a number of times with a smaller count of
items to work with or place strategic DoEvents calls in your looping code.
 
Hi Ken,

Thanks a lot for response. I can place DoEvents in the loop( say after
completing processing of each mail in the loop). But I could not find
ApplicationPtr->DoEvents for Outlook's ApplicationPtr. Can you please help
me in achieving DoEvents in C++ COM Addin for Outlook.

Regards,
Pradeep
 
Thanks Dmitry for interest in this topic.
Basically I need to get the information from each mail in the folder and
dump it some place, and then print the mail if certain condtion is met.

The code is extension of comaddin.exe from
(http://support.microsoft.com/kb/230689)

The ButtonHandler is extended as follows:
STDMETHODIMP CButtonHandler::Invoke(DISPID dispIdMember, REFIID riid, LCID
lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO*
pExcepInfo, UINT* puArgErr)
{
if (IID_NULL != riid)
return DISP_E_UNKNOWNINTERFACE;

if (dispIdMember != 0x00000001)
return DISP_E_MEMBERNOTFOUND;

if (NULL == pDispParams) return E_POINTER;
if (pDispParams->cArgs != 2) return DISP_E_BADPARAMCOUNT;

ProcessItems();
return S_OK;
}
void CButtonHandler::ProcessItems()
{
// get the MAPIFolderPtr pFolder from user provided foldername;
_ItemsPtr pItems = NULL;
pItems = pFolder->GetItems();

long nItems = pItems == NULL ? 0 : pItems->GetCount();

for ( long i=0; i<nItems; i++)
{
IDispatchPtr pDispItem = NULL;
try { pDispItem = pItems->Item(_variant_t((long)(i+1))); } catch(...){}
if (pDispItem != NULL)
{
ProcessItemType(pDispItem);
}
else
break;
}

}


void CButtonHandler::ProcessItemType(IDispatch* pDispItem)
{
if (pDispItem == NULL)
return;

_MailItemPtr pMailItem;
pDispItem->QueryInterface(__uuidof(_MailItem), (LPVOID*)&pMailItem);
if (pMailItem != NULL)
{
//get many things from pMailItem such as body , subject, to from , and
dump it to
// some place

if ( some condition is met in subject)
pMailItem->PrintOut();

}
}

Two problems:
1) while this code is being executed I can not have keyboard controls and
preview pane is fixed ( does not change)
2) the .PrintOut call is actually executed when control returns from this
code. This problem is not seen in Outlook 2007, but I can see it in Outlook
2003. surprisingly in Outlook 2003 also this works fine provided the
selected mail is text only mail ( no html body)

I read in many threads in this forum that Outlook executes COM addin in it's
main thread. Ideal solution will be to release this thread in for loop of
CButtonHandler::ProcessItems() once, so that Outlook can process the
keyboard requests and print requests. Solution proposed by Ken regarding use
of DoEvents would have solved this issue provided that could be achieved in
C++.

Hope this explains the problem. Please let me know how can this be solved.


Regards,
Pradeep
 
If you are processing and printing only some items in the folder, why do you
loop though all of them instead of applying a restriction and using
ITems.Find/Restrict?

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
 
Thanks Dmitry, yes this would be useful if I had to process few items (
based on some filter) but I need to process all items in the folder ( to
dump the info and some more actions involved on those items). The changes of
workflow does not seem to be a viable option for me. On doing some homework
I found that CoIntialize might have a role to play here. Can I somehow move
my COM Addin to different thread than Outlook's main thread so that Outlook
is free to process it's events ( if yes, how). Though while running in
different thread I would want to disable my COM adding button ( to avoid
concurrency issues) which I can do by putting some global flag ( a better
approach is welcome here).
So my basic aim is to:
1) let user freely use Outlook's regular features while I'm doing my
processing, though user might not start another process in my COM addin
while one request is being processed.
2) From within my COM addin I should be able to .PrintOut() on any item and
get the print fired immediately ( instead of being fired after COM addin
returns). I need to check if the mail print was successful as it is being
printed on file ( print to file).

My suspiscion is, both things might be related i.e if we can achieve (1)
i.e. freeing up the outlook to process it's events, then probably (2) can
automatically be achieved.

I have tried using PeekMessage and DispatchMessage in the loop, but was not
able to achieve desired result.

Regards,
Pradeep
 
Back
Top