Get All Contacts using Lync ContactManager - c#

Right now I'm using the the LyncClient.ContactManager.BeginSearch method to find contacts. However, I haven't been able to figure out how to get all the contacts. I've tried passing "*" and "%" as wild-card characters but that has not worked. Right now here is my function call.
_lyncClient.ContactManager.BeginSearch("*", SearchProviders.GlobalAddressList, SearchFields.DisplayName, SearchOptions.ContactsOnly, 400, SearchCallback, "Searching Contacts");

Lync contacts are organised into groups, so you need to start at the Groups level. Once you've got a group, you can then enumerate through it's Contacts
foreach(var group in _client.ContactManager.Groups)
{
foreach (var contact in group)
{
MessageBox.Show(contact.Uri);
}
}
This article is good for background, and more advanced features
Edit: Specifically, for the distribution groups expansion question, I think the sample here is flawed.
Instead of calling BeginExpand and waiting on the WaitHandle, provide a callback method to handle the Expand callback. So, instead of:
asyncOpResult = DGGroup.BeginExpand(null, null);
asyncOpResult.AsyncWaitHandle.WaitOne();
DGGroup.EndExpand(asyncOpResult);
try this:
...
asyncOpResult = DGGroup.BeginExpand(ExpandCallback, DGGroup);
...
public void ExpandCallback(IAsyncResult ar)
{
DistributionGroup DGGroup = (DistributionGroup)ar.AsyncState;
DGGroup.EndExpand(ar);
etc...
}
This works perfectly for me.

I ended up doing multiple searches for now to get all the contacts. I go through each letter of the alphabet to find them. The load time is quick enough and I'll just show a loading image on the grid for a little while when it fires up. This worked well for the 200 or so contacts we have though I would recommend Paul's solution for 150 or less. Here is what I did:
private static char[] Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
...
public void GetAllContacts()
{
int initialLetterIndex = 0;
_lyncClient.ContactManager.BeginSearch(
Alphabet[initialLetterIndex].ToString();
SearchProviders.GlobalAddressList,
SearchFields.FirstName,
SearchOptions.ContactsOnly,
300,
SearchAllCallback
new object[] { initialLetterIndex, new List<Contact>() }
);
}
private void SearchAllCallback(IAsyncResult result)
{
object[] parameters = (object[])result.AsyncState;
int letterIndex = (int)parameters[0] + 1;
List<Contact> contacts = (List<Contact>)parameters[1];
SearchResults results = _lyncClient.ContactManager.EndSearch(result);
contacts.AddRange(results.Contacts);
if (letterIndex < Alphabet.Length)
{
_lyncClient.ContactManager.BeginSearch(
Alphabet[letterIndex].ToString(),
SearchAllCallback,
new object[] { letterIndex, contacts }
);
}
else
{
//Now that we have all the contacts
//trigger an event with 'contacts' as the event arguments.
}
}

Related

Move outlook item to archive

I have a C# program (actually it's just a C# library that is being used by NUnit) that I wish to modify slightly which is based off of this article: How to Programmatically move items in outlook. I'm currently faced with a folder that has bout 3500 messages all around 350kb and is taking FOREVER to move to my archive so I can send and receive emails again (since my inbox is currently at 1.5Gb out of 500Mb... lol) but for the life of me I can't figure out how to get my archive folder. I'm a little bit multitasking since I'm at work so I can edit as I go. So if you have any code readily available that finds the archive folder that would be great. Thank you
EDIT
ok to show that I do have some work in progress (based on negative feedback) here is the code I have in place right now (since yes I know I have a give me teh codez)
here is my NUnit test case that looks at a folder and gives me specific information
[Test]
public void CheckMessages()
{
List<EmailMessage> messages = new List<EmailMessage>();
using (var target = new EmailMessageProvider())
{
messages.AddRange(target.GetEmailMessages("UnexpectedErrors\\NotFindImage"));
}
Dictionary<int, string> asdf = new Dictionary<int, string>();
foreach (var item in messages)
{
var line = item.Body.Split(new string[] { Environment.NewLine }, StringSplitOptions.None)[2];
var revisionId = int.Parse(Regex.Match(line, #"\-*\d+").Value);
var path = line.Substring(line.IndexOf("\\\\"));
if (asdf.ContainsKey(revisionId))
{
Assert.That(path, Is.EqualTo(asdf[revisionId]));
}
else
{
asdf.Add(revisionId, path);
}
}
foreach (var item in asdf.OrderBy(x => x.Key))
{
Console.WriteLine($"{item.Key} {item.Value}");
}
}
I use the same class to find messages (in another test) and move it to that subfolder which that test is using.
here is the code I have that does the moving
public void MoveSurveyPrintComponentsNotFound()
{
var destination = _baseFolder.Folders["UnexpectedErrors"].Folders["NotFindImage"];
foreach (var mailItem in _baseFolder.Folders["UnexpectedErrors"].Items.OfType<MailItem>())
{
mailItem.UseMailItem(x =>
{
if (x.Body.Contains("Foobar.Common.Exceptions.ImageNotFound"))
x.Move(destination);
});
}
}
EDIT 2
looks like I may have just about got it. I found that in the MAPI Namspace one of the subfolders is Archives. I'm going to try to change a few of the variables and see if it moves. Problem is just checking one folder takes over 31 seconds. oh well. better than never.
I figured it out. It wasn't as hard as I had thought either so I'll share what i have just incase someone else has this problem. In my program I did 2 things. One was to set _basefolder as my default email address's Folder. Second was to to set _mapi to the Outlook.GetNamespace("MAPI"). Those two thinsg I already had in my constructor.
private readonly OutlookApplication _outlook;
private readonly NameSpace _mapi;
private MAPIFolder _baseFolder;
public EmailMessageProvider()
{
_outlook = new OutlookApplication();
_mapi = _outlook.GetNamespace("MAPI");
_baseFolder = _mapi.Folders["robert#defaultEmail.com"];
}
Archives works just like any other MAPIFolder so it's just a matter of getting said folder. For me it was in _mapi.Folders["Archive"]. I would imagine this is fairly standard so if you copy and paste it should work just fine.
So now to list out all of my emails I want to go through and move tham appropriatly.
public void MoveSpecificEmailsToArchives()
{
var destination = _mapi.Folders["Archives"];
foreach (var mailItem in _baseFolder.Folders["Unexpected Error"].Items.OfType<MailItem>())
{
mailItem.UseMailItem(x =>
{
if (x.Body.Contains("offensiveProgram.exe ERROR "))
x.Move(destination);
});
}
Release(destination);
}
fyi the UseMailItem is an extension method. Looks like this
public static void UseMailItem(this MailItem item, Action<MailItem> mailItemAction)
{
mailItemAction(item);
Marshal.ReleaseComObject(item);
}

C# foreach count doesn't count correctly with Amrykid.Web.IRC API

I have a problem with counting the total users in my irc channel.
If my IRC bot joins after all the users, it counts them all. If someone leave, it counts correctly. But, when someone join, it doesn't add a user to the count somehow.
What could be wrong with my code? Thanks!
if (message.Replace("!", "").StartsWith("users"))
{
try
{
int count = ch.UserCount = 0;
foreach (string u in ch.Users)
{
count += 1;
}
_irc.SendMessage("Users Online: " + count, IRC.SupportedColors.Red, ch.Channel);
}
catch (Exception ee)
{
_irc.SendMessage("Error: " + ee.Message, IRC.SupportedColors.Red, ch.Channel);
}
}
Looking at Amrykid.Web.IRC, ch.Users (where ch is an IRCChannel) is a string[]:
public string[] Users {
get {
return this._users;
}
}
foreach is perfectly capable of looping over an array correctly, although if all you want to do is count the users, .Length would be more efficient.
Whatever the problem is: it has nothing to do with foreach, and everything to do with one of:
the library being buggy
incorrect expectations about the library
incorrect usage of the library
It seems, however, a support question for Amrykid.Web.IRC.
Glancing at AddUser, it seems that it only adds unique users:
internal void AddUser(string user)
{
Collection<string> source = new Collection<string>();
try
{
foreach (string str in this._users)
{
source.Add(str);
}
}
catch (Exception)
{
}
if (!source.Contains(user))
{
source.Add(user);
}
this._users = null;
this._users = source.ToArray<string>();
}
While this implementation isn't particularly good, it would appear to be functional.
When I created this library, I was a novice programmer so I would expect that this library would be buggy. While it's been a while since I've viewed the code, I do recommend that you use a better written library such as https://github.com/meebey/SmartIrc4net.

Fill one textbox with the IP-Host relation in a list

I'm just blocked with this one, searched everywhere but there is a tough one to find
In my windowsform C# application that I'm developing in VS Express 2012 I'm trying to achieve the following:
I've a list of IP hostname relation in plain text, like this:
99999 10.10.10.10
88888 10.10.10.11
etc
1567 lines in total
In the form I've two textbox's, one with autocomplete (the list of items are only the hostnames), the second one should display the IP regarding the hostname entered, as soon as the user select the hostname from the autocomplete sugestion.
Sorry but I'm stuck with this one, help please
Thanks in advance
cant you just create a class ? like this
class ips
{
public int ident;
public string ip;
public ips(int Ident, string Ip)
{
this.ident = Ident;
this.ip = Ip;
}
}
//fill the List
const int MAXELEMENTS = 512;
ips[] ipList = new ips[MAXELEMENTS];
ips ipa = new ips(1111, "10.10.10.1");
ips ipb = new ips(2222, "20.20.20.1");
and then fire SelectionChangeCommitted event ?
public Form1()
{
ipList[0] = ipa;
ipList[1] = ipb;
InitializeComponent();
cBox1.AutoCompleteMode = AutoCompleteMode.Append;
for(int i = 0; i < ipList.Count(); i++)
{
if(ipList[i] != null)
cBox1.Items.Add(ipList[i].ip);
}
}
private void cBox1_SelectionChangeCommitted(object sender, EventArgs e)
{
tBox1.Text = Convert.ToString(ipList[cBox1.SelectedIndex].ident);
}
i hope this helped you
Right, so we'll take your examples:
99999 10.10.10.10
88888 10.10.10.11
and parse those into a dictionary, like this:
private Dictionary<string, string> ParseText(string text)
{
Dictionary<string, string> hostnameDictionary= new Dictionary<string, string>();
foreach(var line in text.Trim().Split(Environment.NewLine)))
{
string[] textParts = line.Trim().Split(' ');
if(textParts.Length == 2 && !hostnameDictionary.ContainsKey(textParts[0])
{
hostnameDictionary.Add(textParts[0], textParts[1]);
}
}
return hostnameDictionary;
}
Note that the above will work only if there aren't spaces elsewhere, so if the hostname has a space in it, then the above won't parse it.
Using the method above, you'll get a dictionary which uses the hostnames as keys, so you can very easily find what ip belongs to what dictionary, so for example typing hostnameDictionary["99999"] will return the string "10.10.10.10"
If this wasn't clear, or you need help with another part, let me know and I'll update the answer.

Read all phone contacts and update them. windows phone 8

I want to get all contacts stored in phone and update them as per requirement.
http://www.silverlightshow.net/items/Windows-Phone-8-Contacts-Integration.aspx
This link shows to get contacts but I'm not getting all contacts. I'm only getting contacts that have been created using my app.
Is there any way I can get all contacts and change mobile numbers.
Thanks
From the link you provided (emphasis added):
With Windows Phone 8, Microsoft introduces a new concept of "custom
contact stores" [2]. In addition to the read-only access to the user's
contact list and the above demonstrated way to use a separate task for
creating new entries (both of which available in 7.x) we now are able
to write our own data to the people hub silently and without user
consent. However apps still cannot manipulate existing contacts that
originate from somewhere else. In this sense, the data that belongs to
an app is somewhat isolated from the rest.
This is by design, you can't edit contacts you didn't create.
try something like this
void GetContact()
{
cons = new Contacts();
//Identify the method that runs after the asynchronous search completes.
cons.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(ContactsSearchCompleted);
//Start the asynchronous search.
cons.SearchAsync(String.Empty, FilterKind.None, "Contacts Test #1");
}
private void ContactsSearchCompleted(object sender, ContactsSearchEventArgs e)
{
cons.SearchCompleted -= ContactsSearchCompleted;
//e.Results should be the list of contact, since there's no filter applyed in the search you shoul have all contact here
}
not this is a copy paste of an old not tested code of mine so you might have to change something
You cant' - stupid crappy MS don't even support contact import from vcard file. ALL MS want that you put every your data to their servers so they own it.
At first you should at Contact Capability
for wp8 add from WMAppManifest.xml
for wp8.1 add from Package.appxmanifest
Now define a class PhoneContact to store the data
public class PhoneContact {
public string Name { get; set; }
public string Number { get; set; }
public string Email { get; set; }
}
Create a ObservableCollection and Call the following action from constructor to read the contact list. N.B use the following namespace also
using Microsoft.Phone.UserData;
using System.Collections.ObjectModel;
ObservableCollection<PhoneContact> phoneContact;
public MainPage() {
InitializeComponent();
phoneContact = new ObservableCollection<PhoneContact>();
ReadPhoneContact();
}
void ReadPhoneContact(){
Contacts cnt = new Contacts();
cnt.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(Contacts_SearchCompleted);
cnt.SearchAsync(String.Empty, FilterKind.None, "Contacts Test #1");
}
After reading all contact fire the following event. you can read multiple contact number, email etc.
void Contacts_SearchCompleted(object sender, ContactsSearchEventArgs e)
{
foreach (var item in e.Results) {
var contact = new PhoneContact();
contact.Name = item.DisplayName;
foreach (var pn in item.PhoneNumbers)
contact.Number = string.IsNullOrEmpty(contact.Number) ? pn.PhoneNumber : (contact.Number + " , " + pn.PhoneNumber);
foreach (var ea in item.EmailAddresses)
contact.Email = string.IsNullOrEmpty(contact.Email) ? ea.EmailAddress : (contact.Email + " , " + ea.EmailAddress);
phoneContact.Add(contact);
}
}

Searching public Outlook contacts folder from C#

We have a large public contacts folder in Outlook called Global Contacts, I'd like to be able to search through it and return a number of results that match certain criteria, ideally wildcard-style.
E.g. if someone puts "je" in the 'name' textbox, it will return all contacts whose names contain 'je'. This may be coupled as an AND with a companyname textbox.
Most of the examples I've seen are either in VB, or are concerned with doing this form a web app - I'm doing a winforms app, and every machine has Outlook 2002 installed (yeah, I know, update long overdue).
Can anyone point me in the right direction? Some code would be nice as a place to start.
Cheers
I ended up doing this:
Microsoft.Office.Interop.Outlook._Application objOutlook; //declare Outlook application
objOutlook = new Microsoft.Office.Interop.Outlook.Application(); //create it
Microsoft.Office.Interop.Outlook._NameSpace objNS = objOutlook.Session; //create new session
Microsoft.Office.Interop.Outlook.MAPIFolder oAllPublicFolders; //what it says on the tin
Microsoft.Office.Interop.Outlook.MAPIFolder oPublicFolders; // as above
Microsoft.Office.Interop.Outlook.MAPIFolder objContacts; //as above
Microsoft.Office.Interop.Outlook.Items itmsFiltered; //the filtered items list
oPublicFolders = objNS.Folders["Public Folders"];
oAllPublicFolders = oPublicFolders.Folders["All Public Folders"];
objContacts = oAllPublicFolders.Folders["Global Contacts"];
itmsFiltered = objContacts.Items.Restrict(strFilter);//restrict the search to our filter terms
Then just looping through itmsFiltered to add it to an ObjectListView. Hopefully this will be of use to someone else looking to do the same - it took me a while to cobble this together from various sources.
to find contacts folder you can iterate items of olFolderContacts. Here is the code
using System;
using Microsoft.Office.Interop.Outlook;
using Application = Microsoft.Office.Interop.Outlook.Application;
namespace RyanCore
{
public class Loader
{
public static ContactsViewModel LoadModel(Application objOutlook)
{
var viewModel = new ContactsViewModel();
MAPIFolder fldContacts = objOutlook.Session.GetDefaultFolder(OlDefaultFolders.olFolderContacts);
foreach (object obj in fldContacts.Items)
{
if (obj is _ContactItem)
{
var contact = (_ContactItem) obj;
viewModel.Contacts.Add(new Contact(contact.FirstName + " " + contact.LastName, contact.Email1Address));
}
else if (obj is DistListItem)
{
var distListItem = (DistListItem) obj;
var contactGroup = new ContactGroup(distListItem.Subject);
viewModel.Groups.Add(contactGroup);
for (Int32 i = 1; i <= distListItem.MemberCount; i++)
{
Recipient subMember = distListItem.GetMember(i);
contactGroup.Contacts.Add(new Contact(subMember.Name, subMember.AddressEntry.Address));
}
}
}
return viewModel;
}
}
}

Categories

Resources