Working with Outlook Accounts, Stores, Folders and Items
Any user of Microsoft Outlook will tell you that you cannot use Outlook without first setting up an account. This account can either be an Exchange server, POP or IMAP account, although Outlook can support any MAPI style account too.
So, an Outlook account is pretty easy to understand but how does it fit within an Outlook Store? In short, an Outlook account cannot really exist without an Outlook Store. The store is used to, well, store the Outlook data, this includes your folders and items (E-mails, Contacts etc.)
In this article, we’ll take a look at how you can access and use these objects in your Outlook add-ins.
Outlook Accounts
The Outlook Accounts object is a collection of Account objects and allows you to get a reference to all the accounts for a given profile, identify the type of account and use a specific account to send e-mails. There are no way to programmatically add or remove an Account using the Outlook object model.
Getting a list of accounts
You can get a reference to the Accounts collection via the NameSpace object. In the following code listing, I enumerated the accounts collection and printed the user name and e-mail associated with the account.
C# code example
Outlook.NameSpace ns = null; Outlook.Accounts accounts = null; Outlook.Account account = null; string accountList = string.Empty; try { ns = OutlookApp.Session; accounts = ns.Accounts; for (int i = 1; i <= accounts.Count; i++) { account = accounts[i]; accountList += String.Format("{0} - {1}{2}", account.UserName, account.SmtpAddress, Environment.NewLine); if (account != null) Marshal.ReleaseComObject(account); } MessageBox.Show(accountList); } finally { if (accounts != null) Marshal.ReleaseComObject(accounts); if (ns != null) Marshal.ReleaseComObject(ns); }
Notable properties
The Account object contains a number of useful properties, some of which are listed below:
Name | Description |
DeliveryStore | Returns the default delivery Store object for the account. |
AccountType | Use this to establish what kind of account it is e.g. Exchange, POP3, IMAP etc. |
CurrentUser | This property is used to get a reference to a Recipient object that represents the current user for the account. |
SmtpAddress | If you only need the e-mail address of the current account, use this property. |
Outlook Stores
Like the Accounts object the Stores object contains a collection that lets you enumerate the stores for a given profile.
Getting a list of stores
The Namespace object contains a reference to the Stores collection, and in the following code I enumerated the said collection, and printed the store name whether it is a .pst or .ost file:
C# code example
Outlook.NameSpace ns = null; Outlook.Stores stores = null; Outlook.Store store = null; string storeList = string.Empty; try { ns = OutlookApp.Session; stores = ns.Stores; for (int i = 1; i <= stores.Count; i++) { store = stores[i]; storeList += String.Format("{0} - {1}{2}", store.DisplayName, (store.IsDataFileStore ? ".pst" : ".ost"), Environment.NewLine); if (store != null) Marshal.ReleaseComObject(store); } MessageBox.Show(storeList); } finally { if (stores != null) Marshal.ReleaseComObject(stores); if (ns != null) Marshal.ReleaseComObject(ns); }
Adding and removing a store
The Outlook object model provides methods to quickly and easily add or remove stores to the profile. The only Store you can add programmatically is a .pst store, as illustrated below:
C# code example
Outlook.NameSpace ns = null; string pstPath = string.Empty; try { pstPath = @"C:\Temp\Backup.pst"; ns = OutlookApp.Session; ns.AddStoreEx(pstPath, Outlook.OlStoreType.olStoreDefault); } finally { if (ns != null) Marshal.ReleaseComObject(ns); }
In the following example, I removed the store in which the current folder was located:
Outlook.NameSpace ns = null; Outlook.Explorer currExplorer = null; Outlook.MAPIFolder currFolder = null; Outlook.Store store = null; Outlook.MAPIFolder storeFolder = null; try { ns = OutlookApp.Session; currExplorer = OutlookApp.ActiveExplorer(); currFolder = currExplorer.CurrentFolder; store = currFolder.Store; storeFolder = store.GetRootFolder(); ns.RemoveStore(storeFolder); } finally { if (storeFolder != null) Marshal.ReleaseComObject(storeFolder); if (store != null) Marshal.ReleaseComObject(store); if (currFolder != null) Marshal.ReleaseComObject(currFolder); if (currExplorer != null) Marshal.ReleaseComObject(currExplorer); if (ns != null) Marshal.ReleaseComObject(ns); }
Notable methods
GetRootFolder
The Store object contains a number of useful methods. The first we’ll look at is the GetRootFolder method. This method, as its name suggests, returns a MAPIFolder object that contains reference to the root folder of the Store. You can then use this folder to access any child folders.
GetSearchFolders
The GetSearchFolders method returns a collection of all the search folders for a specific Store. A search folder is a folder that contains a view of all items that match a specific criteria.
GetRules
By calling the GetRules method of the Store object, you receive a collection of Rule objects for the current session. Be warned though, to call the GetRules method can take a long time on slow connections to an Exchange server!
Outlook Store events
The Store object provides two events, one to let you know when a Store object has been added and another before a Store object is removed.
The StoreAdd event occurs when you add a new store to the profile and sends a reference to the new store as a parameter:
void stores_StoreAdd(Outlook.Store Store) { MessageBox.Show("You've added store called " + Store.DisplayName); }
The BeforeStoreRemove event is fired just before a Store is removed. A parameter containing a reference to the store that is being removed is passed as well as a Boolean parameter with which you can cancel the remove action.
void stores_BeforeStoreRemove(Outlook.Store Store, ref bool Cancel) { if (MessageBox.Show("You are about to remove a store called " + Store.DisplayName + ". Are you sure?", "Confirm removal", MessageBoxButtons.YesNoCancel) != DialogResult.Yes) { Cancel = true; } }
Outlook Folders
The Folders object contains a collection of Folder objects for either a Store or a Folder. Each Folder object in turn also has its own Folders property, you can use this to access the folders’ child folders.
Getting a list of folders
The following code listing illustrates how to get the root folder of a store and display all its child folders.
C# code example
Outlook.NameSpace ns = null; Outlook.Stores stores = null; Outlook.Store store = null; Outlook.MAPIFolder rootFolder = null; Outlook.Folders folders=null; Outlook.MAPIFolder folder = null; string folderList = string.Empty; try { ns = OutlookApp.Session; stores = ns.Stores; store = stores[1]; rootFolder = store.GetRootFolder(); folders=rootFolder.Folders; for (int i = 1; i < folders.Count; i++) { folder = folders[i]; folderList += folder.Name + Environment.NewLine; if (folder != null) Marshal.ReleaseComObject(folder); } MessageBox.Show(folderList); } finally { if (folders != null) Marshal.ReleaseComObject(folders); if (folders != null) Marshal.ReleaseComObject(folders); if (rootFolder != null) Marshal.ReleaseComObject(rootFolder); if (store != null) Marshal.ReleaseComObject(store); if (stores != null) Marshal.ReleaseComObject(stores); if (ns != null) Marshal.ReleaseComObject(ns); }
Adding and removing a folder
To add a folder to a Folders collection you first need to get a reference to a folder, and then use the Add method on its Folders collection, as illustrated below:
C# code example
Outlook.NameSpace ns = null; Outlook.Stores stores = null; Outlook.Store store = null; Outlook.MAPIFolder rootFolder = null; Outlook.MAPIFolder folder = null; Outlook.Folders folders = null; try { ns = OutlookApp.Session; stores = ns.Stores; store = stores[1]; rootFolder = store.GetRootFolder(); folders = rootFolder.Folders; folder = folders.Add("My New Folder", ADXOlDefaultFolders.olFolderInbox); } finally { if (folders != null) Marshal.ReleaseComObject(folders); if (folder != null) Marshal.ReleaseComObject(folder); if (rootFolder != null) Marshal.ReleaseComObject(rootFolder); if (store != null) Marshal.ReleaseComObject(store); if (stores != null) Marshal.ReleaseComObject(stores); if (ns != null) Marshal.ReleaseComObject(ns); }
To delete a folder, you can either use the Remove method on the Folder’s object, or you can obtain a reference to the folder and use its Delete method.
Outlook.Explorer currExplorer = null; Outlook.Folder folder = null; try { currExplorer = OutlookApp.ActiveExplorer(); folder = (Outlook.Folder)currExplorer.CurrentFolder; if (MessageBox.Show("Are you sure you want to delete the selected folder?", "Confirm deletion", MessageBoxButtons.YesNoCancel) == DialogResult.Yes) { folder.Delete(); } } finally { if (folder != null) Marshal.ReleaseComObject(folder); if (currExplorer != null) Marshal.ReleaseComObject(currExplorer); }
Folders events
The Folder object has three events, FolderAdd which occurs when a folders is added to the Folders collection. The folder that is added is passed into the event as a parameter.
void folders_FolderChange(Outlook.MAPIFolder Folder) { MessageBox.Show(String.Format("A new folder called {0} is being added.", Folder.Name)); }
FolderRemove is the opposite of the FolderAdd event and occurs when a folder is removed from the Folders collection. Unfortunately, the event does not indicate which folder is removed.
void folders_FolderRemove() { MessageBox.Show("A folder was removed"); }
Lastly FolderChange can be used to determine when a folder in the Folders collection has changed. As with the FolderAdd event a reference to the folder that was changed is passed into the event.
void folders_FolderAdd(Outlook.MAPIFolder Folder) { MessageBox.Show(String.Format("A folder called {0} has changed.", Folder.Name)); }
Outlook Items
The Outlook Items collection object is used for accessing and enumerating items in Outlook folders. Although it is the best practice and far more efficient to use the GetTable method of the Folder object to enumerate items in a folder, you can still use the Items collection to perform a number of tasks.
C# code example
Outlook.Explorer currExplorer = null; Outlook.Folder folder = null; Outlook.Items items = null; Outlook.ContactItem contact = null; string contactList = string.Empty; try { currExplorer = OutlookApp.ActiveExplorer(); folder = (Outlook.Folder)currExplorer.CurrentFolder; items = folder.Items; for (int i = 1; i <= items.Count; i++) { if (items[i] is Outlook.ContactItem) { contact = (Outlook.ContactItem)items[i]; contactList += contact.FullName + Environment.NewLine; if (contact != null) Marshal.ReleaseComObject(contact); } } MessageBox.Show(contactList); } finally { if (items != null) Marshal.ReleaseComObject(items); if (folder != null) Marshal.ReleaseComObject(folder); if (currExplorer != null) Marshal.ReleaseComObject(currExplorer); }
Adding and removing items
To remove an item from the items collection you can invoke the Remove method and pass in the items index. To add an item to the Items collection you can use the Add method. You can specify the type of object to create by passing the type name to the method.
Outlook.Explorer currExplorer = null; Outlook.Folder folder = null; Outlook.Items items = null; Outlook.ContactItem contact = null; try { currExplorer = OutlookApp.ActiveExplorer(); folder = (Outlook.Folder)currExplorer.CurrentFolder; items = folder.Items; contact = items.Add(Outlook.OlItemType.olContactItem) as Outlook.ContactItem; contact.Save(); } finally { if (contact != null) Marshal.ReleaseComObject(contact); if (items != null) Marshal.ReleaseComObject(items); if (folder != null) Marshal.ReleaseComObject(folder); if (currExplorer != null) Marshal.ReleaseComObject(currExplorer); }
Items events
The Items object has similar events as the Folders object. However, there are a couple of things you need to look out for when using these events.
The ItemAdd event occurs when one or more item is added to the collection, however, this event does not fire when a large number of items are added at once.
void items_ItemAdd(object Item) { Outlook.MailItem mail = null; try { if (Item is Outlook.MailItem) { mail = (Outlook.MailItem)Item; MessageBox.Show( String.Format( "A new e-mail has been added, with subject : {0}", mail.Subject)); } } finally { if (mail != null) Marshal.ReleaseComObject(mail); } }
The ItemChange event fires when a new item in the collection is changed. As with the ItemAdd event a reference to the item is passed to the event as a parameter.
void items_ItemChange(object Item) { Outlook.MailItem mail = null; try { if (Item is Outlook.MailItem) { mail = (Outlook.MailItem)Item; MessageBox.Show( String.Format( "An e-mail has been added, with subject : {0}", mail.Subject)); } } finally { if (mail != null) Marshal.ReleaseComObject(mail); } }
Finally, the ItemRemove event occurs when an item is removed from the collection. Unfortunately, a reference to the item that has been removed is not passed into the event.
void items_ItemRemove() { MessageBox.Show("An item was removed"); }
For more information about Outlook Items and Folder events please see Outlook Items and Folders Events explained.
Thank you for reading. Until next time, keep coding!
Available downloads:
This sample Outlook add-in was developed using Add-in Express for Office and .net:
Outlook 2013 add-in development in Visual Studio 2012 for beginners
- Part 1: Outlook add-in development: Outlook Application and base objects
- Part 2: Creating custom Outlook views
- Part 3: Creating custom Outlook forms
- Part 4: Outlook UI – Explorer and Inspector Windows. What is customizable?
- Part 5: Customizing Outlook main menu, context menus and Backstage view
- Part 6: Creating custom Outlook ribbons and toolbars
- Part 7: Advanced view regions for Outlook 2013 – 2003
- Part 8: Advanced form regions for Outlook 2013 – 2003
- Part 9: Working with Outlook Accounts, Stores, Folders and Items
- Part 10: Working with Outlook calendar
- Part 11: Working with Outlook tasks
55 Comments
Good article. Consider correcting the spelling of “Atores” in the title to “Stores”.
I see that you’ve done that now.
Hi Brian,
Thank you for the heads up!
Hi Pieter,
I created a User Store, adding a folder, added the path to the folders in ADXOlFormsCollectionItem.FolderNames and tied with ADXForm, but when i select these folders are not creating form!
If I specify a folder from the outlook store for an exchange account form is created!
How to fix it?
Hi Max,
If I understood you correctly, you want to display a custom region for a folder? Make sure you’ve set the folder path correctly and that you specified the FormClassName.
Also, make sure the ExplorerLayout property is set to the correct value.
Hope this helps.
Yes, you understood me right.
I set, for example:
FormClassName = “…Forms.MainADXForm”
FolderNames = {“\\\\MyStore\\Folder1″,”\\\\mymail@mail.com\\Folder2” }
and ExplorerLayout = ADXOlExplorerLayout.WebViewPane.
But for folder in the user store, outlook region is not created!
for folder in outlook store all fine!
If I set ExplorerLayout = ADXOlExplorerLayout.ReadingPane, for both folder created outlook region.
How can this be?
Hi Max,
Have a look at Andrei’s suggestion. It sounds like this might be your problem.
Thanks for that Andrei!
Pieter, where i can see Andrei’s suggestion?
Whoops! My Bad, it was an email not a comment : )
It sounds like you cannot create a WebViewPane form in a non-default message store. The reason and workarounds are described here:
https://support.microsoft.com/kb/923933
The actual registry key depends on the Outlook version used:
12 – Outlook 2007
14 – 2010
15 – 2013
Pieter, thank you very much!!!
If you create an IMAP account you get a new store for that Account, however “Personal Folders” is still the default store, and if try to get the default store programmatically it will be “Personal Folders”. How then can you programmatically figure out what the IMAP store is?
You can’t simply look for a store named the same as your account email address, as you could go in and change the name of the IMAP store and now you have a name disconnect between your email account and IMAP store.
You also can’t just look at the store type for a particular store because there might be multiple email accounts using IMAP.
Hi Nick,
I’m not sure I understand what you need. Do you need to user to select a store or do you want to get the default store and check if it is an IMAP store?
To get the default store use the DefaultStore property on the Session object : OutlookApp.Session.DefaultStore
You can use the AccountType property of the Account object to check whether the account is an IMAP account.
Hope this helps.
Can you pint me to this functionality in VBA, please?
*point*
Never mind. Translation completed.
I must be missing something. You show this construct:
ns = OutlookApp.Session;
accounts = ns.Accounts;
But I don’t find Accounts as a property of outlook session object. Nor do I find .Stores as a property. I am trying to access account information, specifically for an mailitem about to be sent. I can’t seem to locate any reference Account in the namespaces I see in my project.
Hi Richard,
The Accounts property on the Namespace object is only available on Outlook 2007 and up.
In order to access/create accounts in Outlook 2003 and below, you’ll need to use Extended MAPI – which is not ideal to use in managed code. Take a look at this post on OutlookCode.com for more info.
Hope this helps and good luck!
Mil gracias por este blog, no sabes cuanto me gaste en encontrar esta explicación. Mil gracias!!!
Excellent article!!
I am new to Microsoft office and working on a solution to extract MSG files from a PST file.
Below is the code I got from various helps. However, while running this code, I am getting error on saving the MSG file. To be exact I am getting an error “An unhandled exception of type ‘System.Runtime.InteropServices.COMException’ occurred”
while saving the file
mailItem.SaveAs(@”\extracted\” + mailItem.Subject + “.msg”,OlSaveAsType.olMSG)
Any suggestions what I am doing wrong?
Sample Code:
string pstFilePath = @”C:\Demo\Sample.pst”;
Application app = new Application();
NameSpace outlookNs = app.GetNamespace(“MAPI”);
// Add PST file (Outlook Data File) to Default Profile
outlookNs.AddStore(pstFilePath);
MAPIFolder rootFolder = outlookNs.Stores[1].GetRootFolder();
// Traverse through all folders in the PST file
Folders subFolders = rootFolder.Folders;
foreach (Folder folder in subFolders)
{
Items items = folder.Items;
foreach (object item in items)
{
if (item is MailItem)
{
// Retrieve the Object into MailItem
MailItem mailItem = item as MailItem;
Console.WriteLine(“Saving message {0} ….”, mailItem.Subject);
// Save the message to disk in MSG format
// TODO: File name may contain invalid characters [\ / : * ? ” |]
mailItem.SaveAs(@”\extracted\” + mailItem.Subject + “.msg”, OlSaveAsType.olMSG);
}
}
}
// Remove PST file from Default Profile
outlookNs.RemoveStore(rootFolder);
Hi Ashish,
Looks like the problem might be the path where you’re saving the message file:
mailItem.SaveAs(@”\extracted\” + mailItem.Subject + “.msg”, OlSaveAsType.olMSG);
@”\extracted\” is not a valid file path you would need to change it to something like @”C:\Temp”
Hi Pieter,
Thanks for the quick response. I did tried mentioning the path as you have told, but got the same error.
However, one thing to notice here is that although I have Office 2013 installed on my system, I have not configured it. My mailbox is apparently still on lotus notes :(:( and would be moved to Outlook sooner.
Could that be causing a issue? Although I dont think so considering all supporting files should be there with installation.
Hi Ashish,
Did you start Outlook and does it have at least one mail account yet?
I just setup my outlook with a test account. However, I am getting the same error.
“System.Runtime.InteropServices.COMException (0x800300FC): The operation failed.”
Hi Ashish,
I’ve copied your code and do not get an error on the line you mentioned. I do however get an error on this line:
outlookNs.RemoveStore(rootFolder);
Where are you running the code from?From an add-in? Using VSTO or Add-in Express?
Hi Pieter,
For this application, I just write a console application using VSTS 2013. I have added Microsoft.Office.Interop.Outlook reference to the project.
Also, if the above code throws error while removing the PST from default profile, then any suggestions on what should be done here?
Thanks
Hi Pieter,
Just following up to know if you have any suggestions on the problem above?\
Thanks
Hi Ashish,
Upon closer inspection, the problem with the error you get on the mailItem.SaveAs line is that the mail subject contains invalid character. In order to save it to a local folder, first clean any invalid characters from the mail subject like so:
string cleanedSubject = Regex.Replace(mailItem.Subject, @”[^\w\.@-]”, “”,RegexOptions.None, TimeSpan.FromSeconds(1.5));
mailItem.SaveAs(@”C:\Temp\mails” + cleanedSubject + “.msg”, OlSaveAsType.olMSG);
It seems the RemoveStore method returns an error when emails associated with another account has been pasted into the new store’s Inbox folder. It works if it does not contain any emails or if it contains email associated with its own account.
Hope this helps!
Hi Pieter,
Indeed that was the issue. Thanks much for your help.
I have a similar requirement as above.
Extract Outlook Message files from PST file and then move the PST file to a different folder.
Extracting mails work fine as suggested in above posts, but when I try to move PST using File.Move() to a different location it gives me error:
“The process cannot access the file because it is being used by another process.”
I tried closing the process before file.move() but still its not working.
Process.GetProcessesByName(“outlook”)[0].Close();
Also, when I go to task manager I find outlook.exe process running even though I donot have that opened.
How to do this? I will highly appreciate any help.
Hi Venkat,
Mmm..interesting question. Did you remove the store, using the RemoveStore method, before trying to delete the file?
Hi Pieter,
Yes I am removing the store using nameSpace.RemoveStore menthod. I verified this in opened Outlook and the store is getting successfully removed.
After that I have released all COM objects too.
One thing to notice is that in debugging mode, if I close the outlook.exe process (in task manager) before doing File.Move(), it works perfectly.
Do you want to see the code? I can share that with you.
Hi Venkat,
Sure, please share the code. I can then test it on my side and see if I get the same problem.
Hi Pieter,
Please find the code below. I have used some of the code shared in the above posts:
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Runtime.InteropServices;
using Microsoft.Office.Interop;
using Microsoft.Office.Interop.Outlook;
namespace ExtractMSGfromPST
{
class ExtractMSGfromPST
{
public static string folderPath = @”C:\Venkat\PSTFiles\”;
public static string strBackupFolderPath = @”C:\Venkat\Backup\”;
public static string strExtractedFolderPath = @”C:\Venkat\Extracted\”;
static void Main(string[] args)
{
try {
foreach (string pstFilePath in Directory.EnumerateFiles(folderPath, “*.pst”))
{
#region Extract MSG files from PST Files
string strPSTFileName = fnGetPSTFileName(pstFilePath);
fnExtractMSGFiles(strPSTFileName,pstFilePath);
#endregion
#region Move PST files to backup folder
fnMoveExtractedPSTFiles(pstFilePath, strPSTFileName);
#endregion
}
}
catch (System.Exception ex)
{
//Log exception here
}
}
private static void fnMoveExtractedPSTFiles(string pstFilePath, string strPSTFileName)
{
try
{
//first, delete target file if exists, as File.Move() does not support overwrite
if (File.Exists(strBackupFolderPath + strPSTFileName))
{
File.SetAttributes(strBackupFolderPath + strPSTFileName, FileAttributes.Normal);
File.Delete(strBackupFolderPath + strPSTFileName);
}
//Process.GetProcessesByName(“outlook”)[0].Close();
File.Move(pstFilePath, strBackupFolderPath + strPSTFileName);
}
catch (System.Exception ex)
{
//Log exception here
}
}
private static void fnExtractMSGFiles(string strPSTFileName, string pstFilePath)
{
Application app = new Application();
NameSpace outlookNs = null;
MAPIFolder rootFolder = null;
Folders subFolders = null;
Items items = null;
try
{
outlookNs = app.GetNamespace(“MAPI”);
// Add PST file (Outlook Data File) to Default Profile
outlookNs.AddStore(pstFilePath);
rootFolder = outlookNs.Stores[2].GetRootFolder();
string strStoreName = outlookNs.Stores[2].DisplayName.ToString();
// Traverse through all folders in the PST file
subFolders = rootFolder.Folders;
foreach (Folder folder in subFolders)
{
string stringFolderPath = strExtractedFolderPath + strPSTFileName + @”\” + strStoreName + @”\” + folder.Name.ToString();
items = folder.Items;
foreach (object item in items)
{
if (item is MailItem)
{
if (!Directory.Exists(stringFolderPath))
Directory.CreateDirectory(stringFolderPath);
// Retrieve the Object into MailItem
MailItem mailItem = item as MailItem;
// Save the message to disk in MSG format without invalid characters [\ / : * ? ” |]
string mailSubject = Regex.Replace(mailItem.Subject, @”[^\w\.@-]”, “”, RegexOptions.None, TimeSpan.FromSeconds(1.5));
mailItem.SaveAs(stringFolderPath + @”\” + mailSubject + “.msg”, OlSaveAsType.olMSG);
if (mailItem != null)
Marshal.FinalReleaseComObject(mailItem);
}
}
}
// Remove PST file from Default Profile
outlookNs.RemoveStore(rootFolder);
//Release com objects
if (items != null)
Marshal.ReleaseComObject(items);
if (subFolders != null)
Marshal.ReleaseComObject(subFolders);
if (rootFolder != null)
Marshal.ReleaseComObject(rootFolder);
if (outlookNs != null)
Marshal.ReleaseComObject(outlookNs);
if (app != null)
Marshal.ReleaseComObject(app);
}
catch (System.Exception ex)
{
//Log exception here
}
finally
{
//Release com objects
if (items != null)
Marshal.ReleaseComObject(items);
if (subFolders != null)
Marshal.ReleaseComObject(subFolders);
if (rootFolder != null)
Marshal.ReleaseComObject(rootFolder);
if (outlookNs != null)
Marshal.ReleaseComObject(outlookNs);
if (app != null)
Marshal.ReleaseComObject(app);
}
}
private static string fnGetPSTFileName(string pstFilePath)
{
string strPSTFileName = String.Empty;
int iPSTNameIndex = pstFilePath.LastIndexOf(@”\”);
if (iPSTNameIndex != -1)
{
strPSTFileName = pstFilePath.Substring(iPSTNameIndex).Replace(@”\”, “”);
}
return strPSTFileName;
}
}
}
Hi Pieter,
Were you able to replicate the issue at your end?
Hi Venkat,
I took a quick look at it. Problem is it takes a while for the outlook process to quit. I’ve managed to get it working using the following:
var process = Process.GetProcessesByName(“outlook”);
process[0].Kill();
Thread.Sleep(1000);
File.Move(pstFilePath, strBackupFolderPath + strPSTFileName);
Not sure if there is a better way, but the above worked :)
Hope this helps. Good luck!
Hi Pieter,
I tried that earlier, but the sample files I have are very huge and I am not sure if its contributing to the error. I will try to see if there any other way or else would increase the time. Will keep you all posted on it. Thanks
Hi,
Nice article!!
But why we should use GetTable method of the Folder object to enumerate items in a folder??
And how much performance I lose using Items collection.
Tanks,
Rissardi.
Hi Rissardi,
You certainly do not have to use the GetTable method, using the items collection is perfectly acceptable. However, the Table object was added in Outlook 2007 to address certain performance concerns with the Items collection. So when working with large amounts of data the GetTable method,which returns a Table object, is the prefered choice.
In essence think of the Table object as a readonly rowset, that only allows reading of the data and does not allow any changes to be made. It is a light-weight in memory datasteam. It is comparable to the DataReader object in .Net – which allows for very fast data reading.
Hope this helps!
Hi All,
I am getting the following issue
Outlook failed to add the personal store to this session
Also can you tell me which dll is used here?
Hi Ajay,
Where do you get the error? Can you post the code you’re using?
The dll’s used for this example are:
Microsoft.Office.Interop.Outlook.dll
Office.dll
AddinExpress.MSO.2005
Well, good job, only the part with the folders loop has a little mistake
for (int i = 1; i < folders.Count; i++)
Change it into
for (int i = 1; i <= folders.Count; i++)
The condition was wrong so that the last item was missed
However a very well written
I’m sorry I’m late to the discussion. This is a very helpful article. Is it possible to write this code so that it ran in a standalone Windows exe or service (i.e., versus running only from within Outlook itself)?
Thanks in advance for your help.
Hello Steven,
You can use the Outlook object model in a standalone application; see e.g.
– https://support.microsoft.com/en-us/help/316126/how-to-use-visual-c-to-automate-a-running-instance-of-an-office-program
– https://support.microsoft.com/en-us/help/302084/how-to-automate-microsoft-excel-from-microsoft-visual-c-.net
As to using it in a service, Microsoft doesn’t recommend doing this; see https://support.microsoft.com/en-us/help/257757/considerations-for-server-side-automation-of-office.
My Outlook account is made of two mailbox.
I am able to identify the root of the primary mailbox with the following
Public Sub AppResponse(Item As Outlook.MailItem)
Dim objNameSpace As Outlook.NameSpace
Dim objInboxFolder As Outlook.MAPIFolder
Set objNameSpace = Application.Session
Set objInboxFolder = objNameSpace.GetDefaultFolder(olFolderInbox)
How can I generalize the interception of the specific Inbox root folder to which a processed email belongs?
I have tried with
Set objInboxFolder = Item.Parent
but if the mail belongs to a subfolder then I just get the parent folder, nor the main root.
Thanks
Gim
Hello Gim,
I don’t understand if you process incoming emails, outgoing emails, or some (all) emails. To get the store, the folder is located in, you call Outlook.MAPIFolder.Store, then call Store.GetDefaultFolder() to get the inbox folder on that store.
Hi, where is the class OutlookApp? Don’t know where i can import it. thanks
Peter
Hello Peter,
When an Office add-in gets loaded, Office supplies it with a reference to the Application object (from the host’s object model). OutlookApp is a property that points to such an Application object; the property is declared on the add-in module; the add-in module makes sense only if you use Add-in Express. In all other circumstances, you should replace OutlookApp with an Outlook.Application object that you obtain yourself.
Great Article!! Thank you so much
hey
I have built an add-in for Outlook
and I want it to be active only at a specipic account
how can i do that?
thanks
Hello Zipi,
You can’t do this. Instead, use Outlook events to show/hide the UI of your add-in.
Put an Outlook Events component (ADXOutlookAppEvents) onto the add-in module and use the ExplorerFolderSwitch (or, maybe, ExplorerFolderSwitch) to detect the account and show/hide the UI: Ribbon controls and panes. In addition, you may need to start/stop handling Outlook events (other than ExplorerFolderSwitch).
Thanks for the feedback
The problem is that the add-in is active even without pressing the ribbon
It keeps every email that goes in and I only need a certain expense
You have another idea for me
Hello Zipi,
There’s no way to enable/disable the add-in in this way. The only way the Outlook object model provides is to detect the account used and show/hide the UI and connect to/disconnect from events. BTW, you may prefer to connect to events permanently and use a Boolean flag so that event handlers might choose whether to perform or not to perform related functionality.
thanks for sharing!
I’m trying to get a list of contacts from a .PST file that is not the default.
I can “add” said .PST file to the “stores” but so far haven’t figured out how to access and retrieve a list of contacts from that (non-default) store (.PST file).
By the way, this is a Visual Basic.NET 2022 desktop app NOT a VBA app/macro.
Any suggestions/pointers?
Thanks, Bob
Hello Robert,
See Store.GetDefaultFolder(); https://learn.microsoft.com/en-us/office/vba/api/outlook.store.getdefaultfolder. If contacts are in a non-default Contacts folder(s), you’ll need to scan all folders of that store checking the Folder.DefaultItemType property; see https://learn.microsoft.com/en-us/office/vba/api/outlook.folder.defaultitemtype.