Outlook Addin (VSTO) and Exchange Public Folders

  • Thread starter Thread starter Berkley
  • Start date Start date
B

Berkley

Hello all,

I am in the process of creating an Outlook addin using VSTO, which
will involve contact information stored in Exchange Public Folders. I
have successfuly been able to create new contacts in these folders and
work with them, but am encountering a problem when I try to do this
while operating in cached mode and the folders in question have been
added to my Favorites folder.

I have had success adding a single new contact in this scenario, but
when performing a batch addition (looping through an external database
and attempting to add new contacts into my Public Folder heirarchy), I
later look at the new contacts (in VB .NET) and find that
their .Parent.FullFolderPath returns "\\Public Folders\Favorites
\Contacts" as opposed to the actual folder where they are stored. I do
not have a "Favorites\Contacts" folder (as least not that I can see
through Outlook).

If I perform the same batch addition but first remove these folders
from my Favorites, the contact items' .Parent.FullFolderPath property
returns the correct path. As I mentioned above, I have been successful
adding single contacts without first removing the folders from
Favorites.

Does anyone have an explanation as to what might be going on here, or
possibly some ideas on where to research it further? Any assistance
would be greatly appreciated.

Thank you,
Berkley Barnard
 
What version of Outlook? What version of VB.NET, Framework, etc.? Show the
code you're using. More information is needed to see what's going on.
 
This is on Outlook 2003, VB .NET 2005. The code to add in the contacts
is as follows:

Dim source As Outlook.MAPIFolder
source = g_App.GetFolderFromID(g_TempFolder.EntryID,
g_TempFolder.StoreID)
Dim dest As Outlook.MAPIFolder
dest = g_App.GetFolderFromID(g_ContactsFolderDest.EntryID,
g_ContactsFolderDest.StoreID)

lblProgress.Visible = True

For i As Integer = 1 To source.Items.Count

lblProgress.Text = "Contact " & i.ToString & " of " &
source.Items.Count.ToString
Dim cs As Outlook.ContactItem
cs = source.Items.Item(i)

Dim cd As Outlook.ContactItem =
dest.Items.Add("IPM.Contact.WERPS Contact")

With cd
.FullName = cs.FullName
.CustomerID = cs.CustomerID
.UserProperties("Contact Type").Value =
cs.UserProperties("Contact Type").Value
.UserProperties("Shared Contact ID").Value =
cs.UserProperties("Shared Contact ID").Value
.UserProperties("Is Buying Group").Value =
cs.UserProperties("Is Buying Group").Value
.UserProperties("Dealer Number").Value =
cs.UserProperties("Dealer Number").Value
.Save()
End With

cs = Nothing
cd = Nothing
GC.Collect()
System.Windows.Forms.Application.DoEvents()

Next

lblProgress.Text = "Transfer Complete"
 
So where are you getting the folder g_ContactsFolderDest from?

Are you using OlDefaultFolders.olPublicFoldersAllPublicFolders as the
argument when getting to the public folders tree before you instantiate
g_ContactsFolderDest?

If g_ContactsFolderDest is a valid folder why are you re-instantiating it
again as dest?
 
g_ContactsFolderDest is actually an instance of one of my own classes (I
called it "ExchangeFolder") which, among other things, keeps track of the
EntryID and StoreID of the public folder it represents within the Public
Folders heirarchy.

To instantiate it (and others like it), I have been pretty much doing the
following:

Dim f1 as Outlook.MAPIFolder = g_app.Folders.Item("Public Folders")
Dim f2 as Outlook.MAPIFolder = f1.Folders.Item("All Public Folders")
Dim f3 as Outlook.MAPIFolder = f2.Folders.Item("TopOfHeirarchy")
g_ContactsFolderDest = New ExchangeFolder(f3.Folders.Item("Dest"), "Contact")

Sub New for ExchangeFolder basically grabs the EntryID, StoreID and then
does some other unrelated things. Later on when I need to work with a
specific folder I do:

Dim dest As Outlook.MAPIFolder
dest = g_App.GetFolderFromID(g_ContactsFolderDest.EntryID,
g_ContactsFolderDest.StoreID)

which gets me the folder without having to climb down my folder heirarchy
again. I'm going to guess at this point though that this isn't the best way
to approach this.

Thanks,
Berkley
 
As an experiment use that enum member to directly instantiate a folder
object and then walk down to where your target folder is and see what you
get then.
 
I tried the experiment as you suggested, and received the same results.
Poking around afterward though I noticed something that appears to indicate
to me that I've been barking up the wrong tree. When I added the contacts
while the folder was not included in my favorites everything looked good. If
I then added the folder to my favorites and looked at the same contacts,
their .Parent.FullFolderPath returned "\\Public Folders\Favorites\Contacts"
consistently. Remove the folder from favorites again, and they go back to
looking good.

My code that uses this looks like:

Private Sub Inspector_New(ByVal sender As Inspector)

Dim o As Object = sender.CurrentItem

If TypeOf (o) Is ContactItem Then
Dim ci As ContactItem
ci = DirectCast(o, ContactItem)
path = ci.Parent.FullFolderPath

' Use path to do stuff......

End If


What this says to me is that when looking at the
Contact.Parent.FullFolderPath property of a contact in a public folder, what
is returned is dependent on whether that folder is included as one of your
Favorites. If it is, it returns "\\Public Folders\Favorites\Contacts"
regardless of where it resides in my heirarchy. If it is not a favorite, an
accurate path is returned.

Does this make any sense? If it does, the next question will be how to get
the true folderpath in this situation.

Thanks again for your time,
Berkley
 
OK, as I recall that's the opposite of how you phrased the problem
originally and that is to be expected. Even if you directly add the item to
the source folder it will still show up as in Favorites if the folder is in
Favorites. That's the way it works and why storing EntryID for a folder in
Favorites may not always work in a different or later session.

I forget the exact byte, maybe byte 20<?> but if you look at EntryID for the
folder for a folder in Favorites and compare it to the same folder's EntryID
when it's not in Favorites one has "00" and the other has "80", so the
difference is really one set bit in the values that make up the EntryID. You
could develop an algorithm that tested for that to do sort of what you want.
 
I took a look at my folders and saw what you described. For a Favorites
folder I had EntryID:

000000001A447390AA6611CD9BC800AA002FC45A0380B11A731BBB8E7D45881373977007D19000000004E9A00200

and the corresponding non-Favorites folder had EntryID:

000000001A447390AA6611CD9BC800AA002FC45A0300B11A731BBB8E7D45881373977007D19000000004E9A00000

The only differences were in the 43'd digit (8 for Favorites, 0 for non) and
the 3rd-last digit (2 for Favorites, 0 for non). I tested this on other
folder pairs and the same differences were there.

Based on all this, and knowing now that items I interact with will always
refer to their Parent folder as the one under the Favorites tree, I'll go
ahead and modify my code to swap those affected digits in the Entry ID
whenever I need to know the actual folder path for the item.

Thank you very much for your help. I'm pretty sure this would have been a
dead-end for me without your assistance.

Berkley Barnard
 
Thinking about this some more over the weekend I realized that this approach
won't work for me when working offline, since I won't have access to the
Favorites folder's corresponding folder on the server.

My folder structure is set up to represent a group of companies, with
subfolders under each to contain that company's contacts and post items. When
an item was opened I was looking at its parent folders to determine which
company it belonged to, and I'm now thinking that I'd be better off just
using a UserProperty on each item to store this instead. Would that make more
sense for what I'm trying to accomplish here?

Thanks,
Berkley
 
You could do that but you can also test for offline status and take actions
based on that, even just a message box "you're offline, go online for this
to work".
 
Back
Top