6

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");
skeletank
  • 2,880
  • 5
  • 43
  • 75
  • Here is the link for my forum post on MS regarding the limitations of DistributionGroup size for BeginExpand and BeginGetAllMembers: http://social.msdn.microsoft.com/Forums/en-US/communicatorsdk/thread/b9f64c96-524a-45db-a544-16e4f3a5a693 – skeletank Mar 31 '11 at 13:01

2 Answers2

8

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.

Paul Nearney
  • 6,965
  • 2
  • 30
  • 37
  • I used the BeginSearch method to get groups instead and searched for a distribution group with everyone's email address. It returns the correct distribution group but no contacts are returned in the collection. – skeletank Mar 28 '11 at 16:09
  • Have you tried searching using SearchOptions.IncludeContactsWithoutSipOrTelUri, instead of SearchOptions.ContactsOnly? – Paul Nearney Mar 28 '11 at 16:15
  • IncludeContactsWithoutSipOrTelUri had the same result. I tried to expand the distribution group using the sample on the MS site but it it just hung on asyncOpResult.AsyncWaitHandle.WaitOne() and never finishes (http://msdn.microsoft.com/en-us/library/gg436849.aspx). The group should have about 200 people but the MS link only says that there should be problems with 1,000+ – skeletank Mar 28 '11 at 18:41
  • I edited answer with the solution. Not sure about a UCMA option, but hopefully you won't need to go down that route now – Paul Nearney Mar 29 '11 at 16:27
  • I used this code but it has only worked on smaller groups. I'm getting an OperationException from the EndExpand Method coming from Microsoft.Lync.Model.Internal.CBWBase.BlockUntilDone(). I tried to use the BeginGetAllMembers method as well and I got the same results. It would work for smaller groups (one with 90 members) but not with the one with about 200. I was also getting the same error. I think maybe it could be related to the MaxSizeGroupSize to expand property here http://social.technet.microsoft.com/Forums/en-US/ocsclients/thread/9c6fa06e-adfc-420a-a253-0c061dc16c83/ – skeletank Mar 29 '11 at 19:12
  • Sounds like either a bug or a limitation in that call. I'd try and open a support call with MS if you're able to – Paul Nearney Mar 29 '11 at 19:14
  • I'll definitely mark this as the right way to do things though I'm going to use my method till I get a response back from MS. – skeletank Mar 30 '11 at 18:08
  • Cool - let us know if you get a definitive answer – Paul Nearney Mar 30 '11 at 22:18
  • I got a response back from my forum post and it sounds like the SDK is constrained by the limit on the server of 150 users. – skeletank Apr 14 '11 at 21:10
  • Off topic : Is it possible to get the contact _ALIAS_ instead of _URI_ ? – Angshuman Agarwal Mar 12 '17 at 18:52
1

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.
  }
}
skeletank
  • 2,880
  • 5
  • 43
  • 75