How to get Outlook contact groups using MAPI? - c#

In Outlook 2010, you can create contacts and add them to groups. Is there any way to get the list of such groups and the contacts in them? Here's how I access the contacts:
var outlook = new Outlook.Application().GetNamespace("MAPI");
var folder = outlook.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderContacts);
foreach (var curr in folder.Items.OfType<Outlook.ContactItem>())
{
...
}
I do not mean default contact folders, such as "Contacts" and "Suggested contacts".

The contact groups are represented by DistListItem Interface. DistListItem interface has MemberCount property and GetMember() method to iterate through the group members.
var outlook = new Application().GetNamespace("MAPI");
var folder = outlook.GetDefaultFolder(OlDefaultFolders.olFolderContacts);
foreach (var curr in folder.Items.OfType<DistListItem>())
{
Console.WriteLine(curr.DLName);
for (int memberIdx = 1; memberIdx <= curr.MemberCount; memberIdx++)
{
var member = curr.GetMember(memberIdx);
Console.WriteLine(member.Name);
}
}

You can try this one
DataTable dt = new DataTable();
dt.Columns.Add("FirstName");
dt.Columns.Add("MiddleName");
dt.Columns.Add("LastName");
dt.Columns.Add("Email");
Microsoft.Office.Interop.Outlook.Items OutlookItems;
Microsoft.Office.Interop.Outlook.Application outlookObj = new Microsoft.Office.Interop.Outlook.Application();
MAPIFolder Folder_Contacts = (MAPIFolder)outlookObj.Session.GetDefaultFolder(OlDefaultFolders.olFolderContacts);
OutlookItems = Folder_Contacts.Items;
foreach (var item in OutlookItems)
{
var contact = item as ContactItem;
if (contact != null)
{
DataRow dr = dt.NewRow();
dr["FirstName"] = contact.FirstName;
dr["MiddleName"] = contact.MiddleName;
dr["LastName"] = contact.LastName;
dr["Email"] = contact.Email1Address;
dt.Rows.Add(dr);
}
}

Related

Connecting Outlook into Visual Studio

New to programming and trying to create this project for work. I have a text file inputted that has a list of usernames. I want the code to take the usernames from the text file and look them up in Outlook to give me a "true" or "false" if there is a match for the user in the system. How do I connect Outlook to the code with MAPI or an API? The code I have so far is below.
namespace QC_OUTLOOK
{
internal class Program
{
private static object MessageBox;
private static object objFile;
private static int i;
private static object Strings;
private static object response;
static int Main(string[] args)
{
string filePath = #"C:\Users\Documents\QC\User_list.txt";
// string[] lines = File.ReadAllLines(filePath);
List<string> lines = new List<string>();
lines = File.ReadAllLines(filePath).ToList();
using (StreamWriter streamWriter = File.CreateText(filePath));
foreach (String line in lines)
{
Console.WriteLine(line);
}
Console.ReadLine();
{
Outlook._Application oApp = new OutLook.Application();
//Get MAPI namespace
Outlook.AddressLists oNS = oNS.AddressLists;
Outlook.AddressList oGal = oALs.Item("Global Address List");
//Get all entries
Outlook.AddressEntries oEntries = oGal.AddressEntries;
// Get first user found
Outlook.AddressEntry oEntry = oEntries.GetFirst();
Outlook_UserName_Output = "";
response = sa.GetAllUsers;
Console.WriteLine(response);
//
UserCount = 0;
UsersFound = 0;
LastNameMatches = 0;
InactiveUser_Count = 0;
Inconsistent_EmailAddrs = 0;
GIS_UserCount = 0;
TodaysDate = DateTime.Today;
object value = objFile.WriteLine("Date:" + TodaysDate);
object value1 = objFile.WriteLine("QC_UserID, QC_FullName, OutLook_Last_Name, OutLook_First_Name");
for (i = 1; i <= Strings.Len(response) ; i++);
Outlook.Application oApp = new Outlook.Application();
// Get the MAPI namespace.
Outlook.NameSpace oNS = oApp.GetNamespace("mapi");
oNS.Logon(Missing.Value, Missing.Value, false, true);
Outlook.MAPIFolder oInbox = oNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
}
DataTable dt = new DataTable();
dt.Columns.Add("FirstName");
dt.Columns.Add("LastName");
Microsoft.Office.Interop.Outlook.Items OutlookItems;
Microsoft.Office.Interop.Outlook.Application outlookObj = new Microsoft.Office.Interop.Outlook.Application();
Microsoft.Office.Interop.Outlook.MAPIFolder Folder_Contacts = (MAPIFolder)outlookObj.Session.GetDefaultFolder(OlDefaultFolders.olFolderContacts);
OutlookItems = Folder_Contacts.Items;
foreach (var item in OutlookItems)
{
var contact = item as ContactItem;
if (contact != null)
{
DataRow dr = dt.NewRow();
dr["FirstName"] = contact.FirstName;
dr["LastName"] = contact.LastName;
dt.Rows.Add(dr);
}
First of all, creating a new Outlook Application instance multiple times in the code is not the best way to go:
Microsoft.Office.Interop.Outlook.Application outlookObj = new Microsoft.Office.Interop.Outlook.Application();
Outlook is a singleton. You can't run two instances of Outlook on the system at the same time. So, I'd suggest keeping the application object and re-use it where possible.
Iterating over all items in the Outlook folder is not really a good idea. Instead, use the Find/FindNext or Restrict methods of the Items class. Read more about these methods in the following articles:
How To: Retrieve Outlook Contact items using Restrict method
How To: Use Find and FindNext to retrieve Outlook Contact items
But better is to use the NameSpace.CreateRecipient method which creates a Recipient object and can be used to verify a given name against an address book. The Recipient.Resolve method attempts to resolve a created Recipient object against the Address Book. That's exactly what you are looking for!

How to loop through a data table and get the current row/index if the value match with a variable?

My WPF application contains a form which when loaded, obtains two variables which contain a PID (procid) and a processname (procname) of a certain process currently running on the local computer.
I have a data table which contains netstat -ano data outputs in each column. Now i will need to compare either (procid) or (procname) with the associated data contained in the datatable, if both variable matches, store the current index/row number and use that index to get the remote ip address (remoteIp) of the associated datarow to be stored as variables.
How would i achieve this?
Pageone.xaml.cs
public partial class Pageone : Page
{
public Pageone(MainWindow mainWindow)
{
InitializeComponent();
}
private string remoteIp;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
//instantiate the MainWindow and assign it to the 'window' variable
var window = (MainWindow)Application.Current.MainWindow;
string procName = window.proc1;
int subprocPid = window.proc2;
string procPID = subprocPid.ToString();
MessageBox.Show(procPID);
using (Process ns = new Process())
{
DataTable dt = new DataTable();
dt.Columns.AddRange(new DataColumn[] {
new DataColumn("Protocol"),
new DataColumn("Local Address"),
new DataColumn("Foreign Address"),
new DataColumn("State"),
new DataColumn("PID"),
new DataColumn("Process Name"),
});
ProcessStartInfo psi = new ProcessStartInfo("netstat.exe", "-ano");
psi.RedirectStandardOutput = true;
psi.UseShellExecute = false;
ns.StartInfo = psi;
// Run it, and read the results
ns.Start();
using (StreamReader r = ns.StandardOutput)
{
string output = r.ReadToEnd();
ns.WaitForExit();
//Parse those results into a DataTable, polling the Process info
string[] lines = output.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
foreach (string line in lines)
{
string[] elements = line.Split(' ');
if (elements.Length < 5) continue;
if (elements.Contains("Proto")) continue;
DataRow dr = dt.NewRow();
List<string> validElements = new List<string>();
//Weed out empty elements.
foreach (string element in elements)
{
//skip blanks
if (element.Trim() == "") continue;
validElements.Add(element);
}
foreach (string element in validElements)
{
foreach (DataColumn dc in dt.Columns)
{
// fill in the buckets. Note that UDP doesn't have a state
if (dr["Protocol"].ToString() == "UDP" && dc.ColumnName == "State") continue;
if (dr[dc] == DBNull.Value)
{
dr[dc] = element;
break;
}
}
}
dr["Process Name"] = Process.GetProcessById(int.Parse(dr["PID"].ToString())).ProcessName;
dt.Rows.Add(dr);
}
for (int i = 0; i < dt.Rows.Count; i ++)
{
DataRow dr = dt.Rows[i];
///if cellprocPid and procPID matches, get the current index of the row and
///store it in the remoteIp variable
///
}
}
}
MessageBox.Show(remoteIp);
}
}
DataTable has select method, where you can pass fiterexpression to select rows matching filter condition
string expression = "PID= " + procPID.ToString();
var foundRows = table.Select(expression);
// Access rows
for (int i = 0; i < foundRows.Length; i++)
Console.WriteLine(foundRows[i][0]);
Hope it helps.

Messagebox.show method not working with an int variable?

My WPF application contains a form which when loaded, obtains two variables which contain a PID (procid) and a processname (procname) of a certain process currently running on the local computer.
I have a data table which contains netstat -ano data outputs in each column. Now i will need to compare either (procid) or (procname) with the associated data contained in the datatable, if both variable matches, store the current index/row number and use that index to get the remote ip address (remoteIp) of the associated datarow to be stored as variables.
But for some reason when i try to test the variable remoteIp the messagebox does not show up or just displays nothing. Is there something wrong with my code?
Pageone.xaml.cs
public partial class Pageone : Page
{
public Pageone(MainWindow mainWindow)
{
InitializeComponent();
}
private string remoteIp;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
//instantiate the MainWindow and assign it to the 'window' variable
var window = (MainWindow)Application.Current.MainWindow;
string procName = window.proc1;
int subprocPid = window.proc2;
string procPID = subprocPid.ToString();
MessageBox.Show(procPID);
using (Process ns = new Process())
{
DataTable dt = new DataTable();
dt.Columns.AddRange(new DataColumn[] {
new DataColumn("Protocol"),
new DataColumn("Local Address"),
new DataColumn("Foreign Address"),
new DataColumn("State"),
new DataColumn("PID"),
new DataColumn("Process Name"),
});
ProcessStartInfo psi = new ProcessStartInfo("netstat.exe", "-ano");
psi.RedirectStandardOutput = true;
psi.UseShellExecute = false;
ns.StartInfo = psi;
// Run it, and read the results
ns.Start();
using (StreamReader r = ns.StandardOutput)
{
string output = r.ReadToEnd();
ns.WaitForExit();
//Parse those results into a DataTable, polling the Process info
string[] lines = output.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
foreach (string line in lines)
{
string[] elements = line.Split(' ');
if (elements.Length < 5) continue;
if (elements.Contains("Proto")) continue;
DataRow dr = dt.NewRow();
List<string> validElements = new List<string>();
//Weed out empty elements.
foreach (string element in elements)
{
//skip blanks
if (element.Trim() == "") continue;
validElements.Add(element);
}
foreach (string element in validElements)
{
foreach (DataColumn dc in dt.Columns)
{
// fill in the buckets. Note that UDP doesn't have a state
if (dr["Protocol"].ToString() == "UDP" && dc.ColumnName == "State") continue;
if (dr[dc] == DBNull.Value)
{
dr[dc] = element;
break;
}
}
}
dr["Process Name"] = Process.GetProcessById(int.Parse(dr["PID"].ToString())).ProcessName;
dt.Rows.Add(dr);
}
foreach (DataRow row in dt.Rows)
{
int index = dt.Rows.IndexOf(row);
object cellprocPid = row["PID"];
object cellprocName = row["Process Name"];
object cellprocremoteIp = row["Foreign Address"];
if(cellprocPid.ToString() == procPID)
{
//MessageBox.Show(dt.Rows[index]["Process Name"].ToString());
//MessageBox.Show(index.ToString());
remoteIp = dt.Rows[index]["Foreign Address"].ToString();
}
}
}
}
MessageBox.Show(remoteIp);
}
}
It seems like the if statement condition did not match due to both of the variable having different process Id's, which resulting in the messagebox displaying nothing.

DataTable Row Count is Empty

I'm attempting to take a list of Contacts that are retrieved from an OleDB query, add them to a List and then load the List into a DataTable. When I count the number of items in the list it results in the correct number (27000).
However, when I count the number of rows in the DataTable, it results in 0. After doing this I want to write the DataTable to CSV using FileHelpers, however the CSV file is empty.
This is the code I am using;
var listOfContacts = new List<Contact>();
using (OleDbConnection dbfCon = new OleDbConnection(dbfConstr))
{
dbfCon.Open();
var dbfCmd = new OleDbCommand(#"SELECT ct_id, ct_cmpid, ct_empid,
ct_pplid, ct_cntid, ct_pplnm, ct_date, ct_time, ct_type, ct_doneby, ct_desc
FROM contacts", dbfCon);
using (var myReader = dbfCmd.ExecuteReader())
{
while (myReader.Read())
{
var newContact = new Contact()
{
ContactID = Convert.ToInt32(myReader[0]),
CompanyID = Convert.ToInt32(myReader[1]),
EmployeeID = Convert.ToInt32(myReader[2]),
PersonID = Convert.ToInt32(myReader[3]),
ContractID = Convert.ToInt32(myReader[4]),
PersonName = myReader[5].ToString(),
ContactDate = Convert.ToDateTime(myReader[6]),
ContactTime = Convert.ToDateTime(myReader[7]),
TypeOfContact = myReader[8].ToString(),
ContactMadeBy = myReader[9].ToString(),
ContactDescription = myReader[10].ToString(),
};
listOfContacts.Add(newContact);
}
}
DataTable dTable = new DataTable();
dTable.Columns.Add("ContactID");
dTable.Columns.Add("CompanyID");
dTable.Columns.Add("EmployeeID");
dTable.Columns.Add("PersonID");
dTable.Columns.Add("ContractID");
dTable.Columns.Add("PersonName");
dTable.Columns.Add("ContactDate");
dTable.Columns.Add("ContactTime");
dTable.Columns.Add("TypeOfContact");
dTable.Columns.Add("ContactMadeBy");
dTable.Columns.Add("ContactDescription");
MessageBox.Show(listOfContacts.Count.ToString());
foreach (var contact in listOfContacts)
{
var newRow = dTable.NewRow();
newRow["ContactID"] = contact.ContactID;
newRow["CompanyID"] = contact.CompanyID;
newRow["EmployeeID"] = contact.EmployeeID;
newRow["PersonID"] = contact.PersonID;
newRow["ContractID"] = contact.ContractID;
newRow["PersonName"] = contact.PersonName;
newRow["ContactDate"] = contact.ContactDate;
newRow["ContactTime"] = contact.ContactTime;
newRow["TypeOfContact"] = contact.TypeOfContact;
newRow["ContactMadeBy"] = contact.ContactMadeBy;
newRow["ContactDescription"] = contact.ContactDescription;
}
MessageBox.Show(dTable.Rows.Count.ToString());
You can see the two MessageBox that result in the numbers, am I loading the Data into the DataTable incorrectly?
You have to add the new row to the DataTable:
foreach (var contact in listOfContacts)
{
var newRow = dTable.NewRow();
newRow["ContactID"] = contact.ContactID;
newRow["CompanyID"] = contact.CompanyID;
newRow["EmployeeID"] = contact.EmployeeID;
newRow["PersonID"] = contact.PersonID;
newRow["ContractID"] = contact.ContractID;
newRow["PersonName"] = contact.PersonName;
newRow["ContactDate"] = contact.ContactDate;
newRow["ContactTime"] = contact.ContactTime;
newRow["TypeOfContact"] = contact.TypeOfContact;
newRow["ContactMadeBy"] = contact.ContactMadeBy;
newRow["ContactDescription"] = contact.ContactDescription;
dTable.Rows.Add(newRow); // YOU NEED THIS LINE TO ADD THE NEWROW TO DATATABLE
}
In your foreach loop add this at the end :
dTable.Rows.Add(newRow);

add SPListItem to a SPListItemCollection

I have the following code for load a list from sharepoint site.
ALl is working well exept a SPList item to SPListItemCollection.
private void Data_load()
{
DataTable dt = new DataTable();
string currentName = SPContext.Current.Web.CurrentUser.Name;
SPQuery query = new SPQuery();
query.Query = "<Where><Eq><FieldRef Name='Editor'/><Value Type='Person or Group'>" + currentName + "</Value></Eq></Where>";
using (SPSite site = new SPSite("http://spdev-6/"))
{
using (SPWeb web = site.OpenWeb())
{
SPList lists = web.GetList("Lists/Advertisements");
SPListItemCollection items = lists.GetItems(query);
if (items.Count > 0)
{
DataRow dr=null;
SPListItemCollection ITEM = null;
foreach(SPListItem item in items)
{
string A = item["Approval Status"].ToString();
if(A== "2")
{
ITEM.Add(item);
}
}
if(dt.Rows.Count==0)
lbldata.Text = "No data to show";
// dt = items.GetDataTable();
}
else
lbldata.Text = "No data to show";
GridViewD.DataSource = dt;
GridViewD.DataBind();
HttpContext.Current.Session["Advertisement"] = dt;
}
}
}
Now in if(A== "2"){ ITEM.Add(item); }
I want to add SPListItem to a SPListItemCollection. Please help.
You are trying to add an item into null because your ITEM is null. I don't know what error you are getting ( your don't write it) but you must initialize your collection:
if (items.Count > 0)
{
DataRow dr=null;
SPListItemCollection ITEM = ... //
foreach(SPListItem item in items)
{
string A = item["Approval Status"].ToString();
if(A== "2")
{
SPListItem myItem = ITEM.Add();
// set your item's fields here
// Use indexers on this object for each field to assign specific values, and then call the Update method on the item to effect changes in the database.
myItem["Approval Status"] = item["Approval Status"];
...
myItem.Update();
}
}
if(dt.Rows.Count==0)
lbldata.Text = "No data to show";
// dt = items.GetDataTable();
}

Categories