Programmatically finding calendar folders for Exchange server users

  • Thread starter Thread starter Tony Gravagno
  • Start date Start date
T

Tony Gravagno

I'm writing a Windows Service that retrieves appointment data from a
separate application, and it posts this data into the calendar for
individual exchange users. I'm using PIA with C# for all work so far
and it seems OK. The problem is ensuring I'm posting new appointments
to the right folders. I can easily open the default calendar folder
in a PST, but I don't know the approach for Exchange.

One of the admin users manually opens other people's calendars in his
own client instance. I'm wondering what the best technique would be
for doing this programmatically. How do I discover what accounts are
available and then attach to their shared calendar?

Do I need to .Login to a user to post to their folder? Is the
password required? (They're using active directory.) Once I login
I'm sure I can use the user's namespace to navigate to their calendar.

We could setup Outlook on the server running this process so that it
is aware of all calendars that it needs to update, then I think
posting to a folder would be as simple as doing a lookup on the local
namespace for a folder with the user name. But there are (at least)
two issues here: 1) I'd rather not have to put someone through that
manual exercise. 2) I don't know how I would translate a Windows user
ID to a name as we see when we look under "Other Calendars" when
sharing - I guess I'd have to store that name and use it as the folder
name when doing the search.

I hope that's not too confusing.
Thanks!
 
See Namespace.GetSharedDefaultFolder.
Keep in mind that Outlook cannot be used from a Windows service.

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
 
Thanks Dmitry! Well, a licensed instance of Outlook can be used from
a Windows service, it's just not a good idea. What's the alternative?
I've written apps that ran in the Windows tray to keep them
unobtrusive, but my users didn't like them because they needed to have
a user logged-in all the time in order to use them. I can easily
shift this code into an add-in (it's already encapsulated for this
sort of thing) which only gets run when someone is running Outlook,
maybe when they click a button. But what if that person is on
vacation? - These tasks may not get done for a couple weeks. As an
unattended service this process is independent of individuals.

Does anyone know if Outlook 2007 or some other tool (VSTO?) is better
for doing this sort of unattended, user-independent operation?

Regards,
Tony

Dmitry Streblechenko" said:
See Namespace.GetSharedDefaultFolder.
Keep in mind that Outlook cannot be used from a Windows service.

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

"Tony Gravagno" wrote in message
[snip]
 
No version of Outlook should ever be run in a Windows service. It's not that
it's not a good idea, it's a really bad idea. Outlook puts up all sorts of
user prompts and there's no way to disable them. That's aside from the user
impersonation issues. You'll never find anyone who recommends using Outlook
in a service. If you must do something like that use CDO 1.21 or Extended
MAPI or Redemption instead in the service.
 
Heeding the advice of respected authorities I'll switch the internals
to Redemption as soon as possible. For now I'll migrate my code into
an add-in.

Thank you kindly.
 
Dmitry Streblechenko said:
See Namespace.GetSharedDefaultFolder.

My code to update Exchange Server shared calendars is working.
Thanks! At this point I'm confused about why it's actually working.
(That's a new one, eh?) I login to the namespace and created a
recipient for the shared folder (doesn't seem to be a need to resolve
it). I then get a reference to the MAPIFolder:
olRemoteCalendar = olns.GetSharedDefaultFolder(
olRecipient,
PIA.Outlook.OlDefaultFolders.olFolderCalendar);

I create the AppointmentItem with no reference to the folder.
olAppointmentItem =
(PIA.Outlook.AppointmentItem)
olapp.CreateItem(
PIA.Outlook.OlItemType.olAppointmentItem);
And then I post it with the .Save() method.

It goes where it should, but I don't understand how it knows where to
save the item. I thought I would have to explicitly tell it, so I
spent hours playing with the MAPIFolder.Items.Add(object) method, but
it never seemed to accept whatever Type I put in there - including an
appointment item.

Is it correct that we're not just setting references but that we're
actually setting state when we create certain objects? The following
is my understanding based on what I'm seeing:
The Namespace comes from the App.
When the Namespace is logged into a user, it's the app that's
logged-in to that user.
Creating a MAPIFolder using GetSharedDefaultFolder doesn't just
return a reference to the folder, it sets the current folder for the
namespace and the app for subsequent operations.
The Save method on items (all of them?) saves to wherever the
application is currently pointed.

Right track?

Thanks again!
 
Are you sure about that? Application.CreateItem() creates new item in the
corresponding default fodler, which would be current user's Calendar folder
in your case.
How did you call MAPIFolder.Items.Add? It eother takes a message class
(string, in your case "IPM.Appointment") or one of the OlItemType enums
(olAppointmentItem in your case).

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
 
Dmitry Streblechenko said:
Are you sure about that? Application.CreateItem() creates new item in the
corresponding default fodler, which would be current user's Calendar folder
in your case.
How did you call MAPIFolder.Items.Add? It eother takes a message class
(string, in your case "IPM.Appointment") or one of the OlItemType enums
(olAppointmentItem in your case).

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


I did my homework and as (almost) always Dmitry, you're right. :)

Once again I was confused. For anyone else trying to do this, here is
the code for creating an appointment in different folders, depending
on whether it's the local PST (same as local user on Exchange), or a
shared folder. I've removed all error handling and hacked up the code
to make it a little more explanatory - this will not run as-is but
almost. I recommend anyone else who's doing this definitely handle
all issues, and be sure to close, displose, and null all objects where
possible.

PIA.Outlook.Recipient olRecipient =
olns.CreateRecipient(sharename);
// resolution not necessary with correct name
// casing on name doesn't matter.

if (olRecipient != null)
{
olRemoteCalendar =
olns.GetSharedDefaultFolder(
olRecipient,
PIA.Outlook.OlDefaultFolders.olFolderCalendar);
// handle errors!
}
if (olRemoteCalendar == null)
// local PST
olAppointmentItem =
(PIA.Outlook.AppointmentItem)
olapp.CreateItem(
PIA.Outlook.OlItemType.olAppointmentItem);
// handle errors!
} else {
olAppointmentItem =
(PIA.Outlook.AppointmentItem)
olRemoteCalendar.Items.Add(
Microsoft.Office.Interop.
Outlook.OlItemType.olAppointmentItem);
// that line split for readability
// did I mention you must handle errors?!
}

At this point we have a good olAppointmentItem, the .Save method will
save it wherever it belongs. (Ignore my misunderstanding one posting
up in this thread.)

Yes, I could have organized differently depending on whether I had a
shared folder name or not. Next time.

People in these forums have given so much to me with their time and
advice, I hope this gives back just a bit.

Tony Gravagno
Nebula Research and Development
TG@ remove.anti-spam.mungingNebula-RnD.com
 
Back
Top