How do I find the contents of a specific Outlook Contacts subfolder? - c#
I need to extract the contacts (Employees) listed in a specified (by name) subfolder in Outlook Contacts. I've been at it for days, and tried every scrap of code I can find on the internet, but to no avail. I have seen suggestions about how it could be done, but none of them actually work.
Here's my running code. You can drop it in a console app in Visual Studio as-is. I can find the contents of my "Contacts" folder, and I can find the list of folders, but can't work out how to get the contents of a sub folder.
We're using Outlook 365.
using System;
using System.Collections.Generic;
using Outlook = Microsoft.Office.Interop.Outlook;
namespace OutlookTest
{
public class OutlookDataRetriever
{
public static int Main(string[] args)
{
try
{
Outlook.Application oApp = new Outlook.Application();
Console.WriteLine("\n\nShow Contacts folders:");
Outlook.MAPIFolder folderContacts = oApp.Session.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderContacts);
foreach (Outlook.MAPIFolder subfolder in folderContacts.Folders)
{
Console.WriteLine("folder::: " + subfolder.Name + " ::: " + subfolder.FolderPath);
}
Console.WriteLine("\n\nShow members of Contacts folder:");
Outlook.MAPIFolder fldContacts = (Outlook.MAPIFolder)oApp.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderContacts);
Outlook.Items contactsFolder = fldContacts.Items;
foreach (var contact in contactsFolder)
{
if (contact is Outlook.ContactItem)
{
Outlook.ContactItem thisContact = (Outlook.ContactItem)contact;
Console.WriteLine("contact::: " + thisContact.FullName + " ::: " + thisContact.Email1DisplayName);
}
else
{
Console.WriteLine("I'm guessing this is a folder, but can't figure out how to cast it to access its contents.");
}
}
}
catch (Exception e)
{
Console.WriteLine("{0} Exception caught.", e);
}
return 0;
}
}
}
My References:
snapshot of the solution explorer showing references
Here's the output I get:
Show Contacts folders:
folder::: {06967759-274D-40B2-A3EB-D7F9E73727D7} ::: \\KNye#myOrganization.com\Contacts\{06967759-274D-40B2-A3EB-D7F9E73727D7}
folder::: {A9E2BC46-B3A0-4243-B315-60D991004455} ::: \\KNye#myOrganization.com\Contacts\{A9E2BC46-B3A0-4243-B315-60D991004455}
folder::: Companies ::: \\KNye#myOrganization.com\Contacts\Companies
folder::: GAL Contacts ::: \\KNye#myOrganization.com\Contacts\GAL Contacts
folder::: Kristy Nye[1] ::: \\KNye#myOrganization.com\Contacts\Kristy Nye[1]
folder::: Kristy Nye ::: \\KNye#myOrganization.com\Contacts\Kristy Nye
folder::: Recipient Cache ::: \\KNye#myOrganization.com\Contacts\Recipient Cache
folder::: PeopleCentricConversation Buddies ::: \\KNye#myOrganization.com\Contacts\PeopleCentricConversation Buddies
folder::: Kristy's Addresses ::: \\KNye#myOrganization.com\Contacts\Kristy's Addresses
folder::: Organizational Contacts ::: \\KNye#myOrganization.com\Contacts\Organizational Contacts
Show members of Contacts folder:
contact::: Matt Smith ::: Matt Smith (ESmith#myOrganization.com)
contact::: Kristy J Nye ::: Kristy J Nye (KNye#myOrganization.com)
I'm guessing this is a folder, but can't figure out how to cast it to access its contents.
Here's a screenshot of my Contacts folder:
Screenshot of Contacts folder
Here's the contents of my folder, "ThisIsATestGroup":Contents of "ThisIsATestGroup" folder
My objective:
I want to query "Find all contacts in "ThisIsATestGroup", and get back:
Edgar B
Kristy J N
Rey G M
Richard D N
How do I get the contacts in this specific subfolder only??? Thank you!
All you really need is
Outlook.MAPIFolder fldContacts = (Outlook.MAPIFolder)oApp.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderContacts);
Outlook.MAPIFolder fldEmployees = fldContacts.Folders["Employees"];
foreach (var item in fldEmployees.Items)
{
Outlook.ContactItem contact = item as Outlook.ContactItem;
if (contact != null)
{
Console.WriteLine("contact::: " + contact .FullName + " ::: " + contact .Email1DisplayName);
}
else
{
Outlook.DistListItem distList = item as Outlook.DistListItem;
if (distList != null)
{
Console.WriteLine("distList ::: " + distList.DLName);
}
}
}
After much pulling of hair and gnashing of teeth, I found my own answer. Here 'tis:
using System;
using Outlook = Microsoft.Office.Interop.Outlook;
namespace OutlookTest
{
public class OutlookDataRetriever
{
public static int Main(string[] args)
{
string myFolder = "ThisIsATestGroup";
try
{
Console.WriteLine("Show members of '" + myFolder + "' list:");
Outlook.Application oApp = new Outlook.Application();
/* Get a list of items in the contactsfolder */
Outlook.MAPIFolder fldContacts = (Outlook.MAPIFolder)oApp.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderContacts);
Outlook.Items contactsFolder = fldContacts.Items;
/* Find the contacts folder with the name I'm looking for. MS documentation calls this a DistListItem. Baffled me for a long time because their UI calls it a contact group. */
string filter = "[Subject] = '" + myFolder + "'";
var targetFolder = contactsFolder.Find(filter);
Outlook.DistListItem myDistList = (Outlook.DistListItem)targetFolder;
Console.WriteLine("myDistList::: " + myDistList.Subject);
/* List all the members in my list */
for (int i = 1; i <= myDistList.MemberCount; i++) // Index starts at 1, not 0 !!!
{
var aMember = myDistList.GetMember(i);
Console.WriteLine(" member::: " + i.ToString() + " " + aMember.Name + " ::: " + aMember.Address);
}
}
catch (Exception e)
{
Console.WriteLine("{0} Exception caught.", e);
}
return 0;
}
}
}
On my way to the above solution, I found another solution which has the added benefit of allowing you to look through everything in your contacts folder. Both solutions return the correct result, but I suspect the top one runs faster.
namespace OutlookTest
{
public class OutlookDataRetriever
{
public static int Main(string[] args)
{
try
{
Outlook.Application oApp = new Outlook.Application();
Console.WriteLine("Show members of 'ThisIsATestGroup' list:");
Outlook.MAPIFolder fldContactsX = (Outlook.MAPIFolder)oApp.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderContacts);
Outlook.Items contactsFolder = fldContactsX.Items;
foreach (var contact in contactsFolder)
{
if (contact is Outlook.ContactItem)
{
Outlook.ContactItem thisContact = (Outlook.ContactItem)contact;
Console.WriteLine("contact::: " + thisContact.FullName + " ::: " + thisContact.Email1DisplayName);
}
else
{
if (contact is Outlook.DistListItem)
{
Outlook.DistListItem thisDistList = (Outlook.DistListItem)contact;
Console.WriteLine("distList::: " + thisDistList.Subject);
if (thisDistList.Subject == "ThisIsATestGroup")
{
for (int i = 0; i < thisDistList.MemberCount; i++)
{
var aMember = thisDistList.GetMember(i + 1);
Console.WriteLine(" member::: " + i.ToString() + " " + aMember.Name + " ::: " + aMember.Address);
}
}
}
else
{
Console.WriteLine("Should never reach this line.");
}
}
}
}
catch (Exception e)
{
Console.WriteLine("{0} Exception caught.", e);
}
return 0;
}
}
}
Enjoy!
Related
I use ManagementClass to run a Process, but I want that process to run in Background instead of UI console
I'm using Mangement class to create a process, but That starts a UI console - I want to console to run in background. public uint LaunchProcess(string sIPAddress, string sPort) { uint iPid = 0; try { logger.AddLog("LaunchProcess : " + sIPAddress + " " + sPort); object[] PlugInRunnerInfo = { StaticUtils.GetLocation(AgilentPluginCommonConstants.PlugInRunnerPath) + "\\" + "PlugInRunner.exe" + " " + sIPAddress + " " + sPort, null, null, 0 }; //ManagementClass is a part of Windows Management Intrumentation,namespaces. One of its use is to provides access to manage applications. //Here this class is used to launch PlugInRunner as detached process.By setting the ManagementClass object's property 'CreateFlags' to value 0x00000008 //we can start the PlugInRunner as detached one. using (var mgmtObject = new ManagementClass("Win32_Process")) { var processStartupInfo = new ManagementClass("Win32_ProcessStartup",null); processStartupInfo.Properties["CreateFlags"].Value = 0x00000008;//DETACHED_PROCESS. var result = mgmtObject.InvokeMethod("Create", PlugInRunnerInfo); if (result != null) { logger.AddLog("Process id " + Convert.ToUInt32(PlugInRunnerInfo[3])); iPid = Convert.ToUInt32(PlugInRunnerInfo[3]); } } } catch (Exception ex) { logger.AddLog("Exception " + ex.Message); } return iPid; } The above code what I have got. Please help me.
Populate a (winforms) Treeview recursively
I have a TreeView which I need to populate dynamically. The contents would be similar to directory structure (Refer attached pic). Now, in order to fetch these 'folders' I use a command, which would list out only 'top-level' folders (refer pic). (Please note this is not OS directory / folders.. I am only just using directory / folder analogy to make things understandable) So, for e.g. I have Root, Folder1, Sub_Folder1, Sub_Folder2, Sub-sub_folder_1, Folder2, then issuing command with a '/' option will give me a list: Folder1, Folder2. If I need Level-2 folders (Sub_Folder_1 and Sub_Folder_2), I again need to issue the command with option "/Folder1".. I need to repeatedly issue these commands, until I get the last sub.. folder and use the list to populate a TreeView. I am using the below C# (4.5) code, but I am able to list only 2-levels. Any help in correcting would be much appreciated! try { BuildInfaCmd(InfaCmdType.ListFolders, folder); InfaCmd icmd = CallInfaCmd(InfaCmdExe, InfaCmdArgs); if (icmd.ExitCode() == 0) { List<string> folders = icmd.GetFolders(); if (folders.Count > 0) topFolderFound = true; foreach (string f in folders) { if (node == null) // Add to 'root' of Treeview { TreeNode p = new TreeNode(f); treeView1.Nodes.Add(p); PopulateFoldersRecursive(f, null); } else { callLvl += 1; //MessageBox.Show("Calling recursive " + callLvl.ToString()); TreeNode p = new TreeNode(f); node.Nodes.Add(p); // Add to calling node as children string fold = node.Text + "/" + f; // The sub-folder to be provided to ListFolder command like -p /RootFolder/SubFolder1/SubFolder2/... PopulateFoldersRecursive(fold, p, callLvl); } } } else { MessageBox.Show(icmd.GetError(), "Error while executing InfaCmd", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
The answers provided were more specific to populating 'Files' / 'Directories'. As conveyed, the 'folders' in my query was not OS-specific, so the answers did not provide much help. I found out a way to recursively add nodes to Treeview. void PopulateFolders() { int callLvl = 1; BuildInfaCmd(InfaCmdType.ListFolders); int timeout = 60000; if (lstProjects.SelectedItem.ToString().ToLower().StartsWith("hdp")) timeout = 600000; InfaCmd icmd = CallInfaCmd(InfaCmdExe, InfaCmdArgs,null,timeout); if (icmd.ExitCode() == 0) { List<string> folders = icmd.GetFolders(); foreach (string f in folders) { TreeNode p = new TreeNode(f); treeView1.Nodes.Add(p); PopulateFoldersRecursive(f, p, 1); } lstFolders.DataSource = folders; } else { MessageBox.Show(icmd.GetError(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } void PopulateFoldersRecursive(string folder, TreeNode node, [Optional]int callLevel) { int timeout = 60000; if (lstProjects.SelectedItem.ToString().ToLower().StartsWith("hdp")) timeout = 600000; int callLvl = callLevel; string fold = ""; try { BuildInfaCmd(InfaCmdType.ListFolders, folder); InfaCmd icmd = CallInfaCmd(InfaCmdExe, InfaCmdArgs,null, timeout); if (icmd.ExitCode() == 0) { List<string> folders = icmd.GetFolders(); if (folders.Count > 0) topFolderFound = true; foreach (string f in folders) { callLvl += 1; //MessageBox.Show("Calling recursive " + callLvl.ToString()); TreeNode p = new TreeNode(f); node.Nodes.Add(p); // Add to calling node as children // MessageBox.Show(callLvl.ToString() + "; Node.text : " + node.Text + " ; f : " + f); dirTree.Add(p.FullPath); if (String.IsNullOrEmpty(folderFullPath)) { //fold = node.Text + "/" + f; // The sub-folder to be provided to ListFolder command like -p /RootFolder/SubFolder1/SubFolder2/... fold = folder + "/" + f; // ORIGINAL folderFullPath = fold; } else { fold = folder + "/" + f; // TEST folderFullPath = fold; // ORIGINAL } PopulateFoldersRecursive(fold, p, callLvl); } } } else { MessageBox.Show(icmd.GetError(), "Error while executing InfaCmd", MessageBoxButtons.OK, MessageBoxIcon.Error); } } catch (Exception ex) { MessageBox.Show(ex.Message + Environment.NewLine + ex.InnerException, "Error"); } }
Outlook 2007: Reading Pane is not updated when an encrypted Email is imported
we use Redemptiontools to develop a Addin for Outlook. At first we create Emailstubs from a Metadataset. When the User select a Mail we load a msg file from the Network and import it into the Emailstub. We dont have any problems in Outlook 2010/2013/2016. But in Outlook 2007 the reading pane doesnt refresh if the mail has a Signature. I have deselect and reselect the Mail and then i can see the new mail. Creating the Emailstub from an metadataset: using (ComObjectWrapper<RDOFolder> rdoFolder = RDOSession.Resource.GetFolderFromID(folderEntryID).WithComCleanup()) { using (ComObjectWrapper<RDOMail> mailstub = rdoFolder.Resource.Items.Add().WithComCleanup()) { mailstub.Resource.Sent = true; mailstub.Resource.SenderName = metadatamail.SenderName + " "; mailstub.Resource.SenderEmailAddress = metadatamail.SenderEmailAddress + " "; mailstub.Resource.SentOnBehalfOfName = metadatamail.SentOnBehalfOfName + " "; mailstub.Resource.SentOnBehalfOfEmailAddress = metadatamail.SentOnBehalfOfEmailAddress + " "; mailstub.Resource.Subject = metadatamail.Subject + " "; mailstub.Resource.ReceivedTime = metadatamail.ReceivedTime; mailstub.Resource.Body = metadatamail.Body + " "; mailstub.Resource.To = metadatamail.To + " "; mailstub.Resource.ReceivedByName = metadatamail.ReceivedByName + " "; mailstub.Resource.UnRead = metadatamail.UnRead; if (metadatamail.ContainsAttachments) { var Attach = mailstub.Resource.Attachments.Add(new char[0]); Attach.FileName = "Attachment.txt"; } mailstub.Resource.Save(); } } Importing the msg file in the selection change Event of the Explorer (expl): void expl_SelectionChange() { using (var selection = expl.Selection.WithComCleanup()) { foreach (var item in selection.Resource) { if (item is Outlook.MailItem) { string entryID = (item as Outlook.MailItem).EntryID; GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); GC.WaitForPendingFinalizers(); if (!string.IsNullOrEmpty(entryID)) { using (var researchEntry = RDOSession.Resource.GetMessageFromID(entryID).WithComCleanup()) { string mailpath = GetEmailFromNetwork(entryID); if (!string.IsNullOrEmpty(mailpath)) { Redemption.SafeMailItem sItem = new Redemption.SafeMailItem(); sItem.Item = researchEntry.Resource; sItem.Import(mailpath, (int)rdoSaveAsType.olMSG); sItem.ReleaseComObject<Redemption.SafeMailItem>(); researchEntry.Resource.Save(); } } } } } } } RDOSession: private ComObjectWrapper<RDOSession> RDOSession { get { try { var rdoSession = Activator.CreateInstance(Type.GetTypeFromProgID("Redemption.RDOSession")) as RDOSession; if (rdoSession != null) { rdoSession.MAPIOBJECT = this.Application.Session.MAPIOBJECT; return rdoSession.WithComCleanup(); } } catch { } return null; } } Does anyone have a hint or a solution?
Getting all the items from the listbox winform
Good day! I am having troubles on getting all the items, selected or not, from the listbox. Whenever I click the send button, the only items that I could get is the ones I selected (This is the current results of my code below: http://imgur.com/jA94Bjm). What I want is to get all the items from the textbox not just from the selected ones and which is not repeating. private void cmd_send_Click_1(object sender, EventArgs e) { for (int i = 0; i < listBox1.Items.Count; i++) { try { String pno = textBox4.Text.ToString(); String path = textBox5.Text.ToString(); String name = textBox6.Text.ToString(); String user = textBox7.Text.ToString(); output.Text += "\n Sent data : " + pno + " " + user + " " + name + " " + path; } catch (Exception ex) { wait.Abort(); output.Text += "Error..... " + ex.StackTrace; } NetworkStream ns = tcpclnt.GetStream(); String data = ""; data = "--++" + " " + textBox4.Text + " " + textBox5.Text + " " + textBox6.Text + " " + textBox7.Text; if (ns.CanWrite) { byte[] bf = new ASCIIEncoding().GetBytes(data); ns.Write(bf, 0, bf.Length); ns.Flush(); } } }
If you want to access all your items from your listbox, you have to iterate all of the items and access the value of that item. Here's a sample how you can achieve this: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace ConsoleApplication1 { class Program { class Process { public int ProcessId { get; set; } public string FilePath { get; set; } public string FileName { get; set; } public string User { get; set; } } static void Main(string[] args) { Process p1 = new Process(); p1.ProcessId = 1; p1.FileName = "Tool.exe"; p1.FilePath = #"C:\Tool.exe"; p1.User = "User1"; Process p2 = new Process(); p2.ProcessId = 2; p2.FileName = "Tool2.exe"; p2.FilePath = #"C:\Tool2.exe"; p2.User = "User2"; Process p3 = new Process(); p3.ProcessId = 3; p3.FileName = "Tool3.exe"; p3.FilePath = #"C:\Tool3.exe"; p3.User = "User3"; ListBox listBox = new ListBox(); listBox.Items.Add(p1); listBox.Items.Add(p2); listBox.Items.Add(p3); for (int i = 0; i < listBox.Items.Count; i++) { Process p = (Process)listBox.Items[i]; //Access the value of the item Console.WriteLine("Process id: {0}", p.ProcessId); Console.WriteLine("Process filename: {0}", p.FileName); Console.WriteLine("Process file path: {0}", p.FilePath); Console.WriteLine("Process user: {0}", p.User); } Console.ReadLine(); } } } We have a sample class Process with different properties. Each Process is added on ListBox which is later accessed inside the loop.
Need to access Outlook contact details from multiple Mail IDs using C#
Using an application, I'm fetching the contact details stored in the Micosoft Office Outlook using C#. I achieved it through the Microsoft.Office.Interop namespace. The issues I'm facing now is when Outlook has multiple mail IDs configured to the same system I need to fetch contacts of the Individual mail IDs seperately. How do I do this? Here is the sample code: /// <summary> /// Getting the contacts by passing the folder name. /// </summary> /// <param name="folderName"></param> /// <returns></returns> private List<MyContact> GetContactsFromFolder(string folderName) { List<MyContact> contacts = null; object missing = System.Reflection.Missing.Value; //Create instance of Outlook application and Outlook Contacts folder. try { OutLook.MAPIFolder fldContacts = null; contacts = new List<MyContact>(); OutLook._Application outlookObj = new OutLook.Application(); /* if (folderName == "Default") { fldContacts = (OutLook.MAPIFolder)outlookObj.Session.GetDefaultFolder(OlDefaultFolders.olFolderInbox); } else { OutLook.MAPIFolder contactsFolder = (OutLook.MAPIFolder) outlookObj.Session.GetDefaultFolder(OlDefaultFolders.olFolderInbox); //VERIFYING THE CUSTOM FOLDER IN OUT LOOK . foreach (OutLook.MAPIFolder subFolder in contactsFolder.Folders) { if (subFolder.Name == folderName) { fldContacts = subFolder; break; } } } * */ fldContacts = (OutLook.MAPIFolder)outlookObj.Session.GetDefaultFolder(OlDefaultFolders.olFolderInbox); //LOOPIN G THROUGH CONTACTS IN THAT FOLDER. foreach (Microsoft.Office.Interop.Outlook._MailItem contactItem in fldContacts.Items) { MyContact contact = new MyContact(); contact.FromAddress = contactItem.SenderEmailAddress; contact.ToAddress = contactItem.To; contact.Subject = contactItem.Subject; contact.MailSize = contactItem.Size.ToString(); contact.Received = contactItem.ReceivedTime.ToString(); System.Data.SqlClient.SqlConnection con; con = new System.Data.SqlClient.SqlConnection(); con.ConnectionString = "Initial Catalog=sample;Integrated Security=True;Server=Test;Connect Timeout=900"; try { con.Open(); string to_address = ""; string Cc = ""; foreach (Microsoft.Office.Interop.Outlook.Recipient olRecipient in contactItem.Recipients) { if (contactItem.To.ToLower().Contains(olRecipient.Address.ToLower()) == true || contactItem.To.ToLower().Contains(olRecipient.Name.ToLower()) == true) { if (to_address != "") { to_address = to_address + ";" + olRecipient.Name + " <" + olRecipient.Address + ">"; } else { to_address =olRecipient.Name+" <"+olRecipient.Address+">"; } } else if (contactItem.CC != null && contactItem.CC.ToString() != "") { if (contactItem.CC.ToLower().Contains(olRecipient.Address.ToLower()) == true || contactItem.CC.ToLower().Contains(olRecipient.Name.ToLower()) == true) { if (Cc != "") { Cc = Cc + ";" + olRecipient.Name + " <" + olRecipient.Address + ">"; } else { Cc = olRecipient.Name + " <" + olRecipient.Address + ">"; } } } } //contact. contacts.Add(contact); } }
The point is in this call of your code: fldContacts = (OutLook.MAPIFolder)outlookObj.Session.GetDefaultFolder(OlDefaultFolders.olFolderInbox); Here you are always opening the default folder. You should try to enumerate the available folders and call another method of the Session object to open the one you need to use. I don't know the answer right now, but this is the direction to go.