Lync client state invalid

When using the Lync 2010 API the LyncClient can get in the Invalid state. This occurs if for instance the Lync process is shut down. When Lync is started again a call to Lync.GetClient() returns a Lync client reference in an Invalid state. Reading the MSDN documentation is not very useful - the Invalid state is not described: http://msdn.microsoft.com/en-us/library/microsoft.lync.model.clientstate_di_3_uc_ocs14mreflyncclnt.aspx

My question is; how can I retrieve a Lync client reference which is not in an Invalid state?

Thanks!

Upvotes: 5

Views: 1505

Answers (2)

Mahdi Jafarkhani
Mahdi Jafarkhani

Reputation: 1

After numerous tries, I reached a not-so-pretty workaround:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Threading;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using Microsoft.Lync.Model;
using ContactAvailability = Microsoft.Lync.Controls.ContactAvailability;

namespace LyncService
{
    public class MicrosoftLyncService : IMicrosoftLyncService
    {
        private readonly string _password = "1234";
        private readonly object _syncObj = new object();
        private readonly string _username = "[email protected]";
        private volatile LyncClient _lyncClient;

        public SkypeContactInfoViewModel GetSkypeContactInfo(string emailAddress)
        {
            try
            {
                lock (_syncObj)
                {
                    Process.Start(new ProcessStartInfo
                    {
                        FileName = "taskkill",
                        Arguments = "/im lync.exe /f /t",
                        CreateNoWindow = true,
                        UseShellExecute = false
                    })?.WaitForExit();

                    _lyncClient = LyncClient.GetClient(true);

                    if (_lyncClient.State == ClientState.Uninitialized)
                    {
                        _lyncClient.BeginInitialize(ar =>
                            {
                                _lyncClient.EndInitialize(ar);
                                _lyncClient.StateChanged += ClientStateChanged;
                            },
                            null);
                    }
                    else
                    {
                        _lyncClient.StateChanged += ClientStateChanged;
                        SignIn(_username, _username, _password);
                    }

                    while (_lyncClient.State != ClientState.SignedIn)
                        switch (_lyncClient.State)
                        {
                            case ClientState.Invalid:
                                _lyncClient = LyncClient.GetClient(true);
                                Thread.Sleep(100);
                                break;
                            case ClientState.Uninitialized:
                                _lyncClient.BeginInitialize(ar =>
                                {
                                    _lyncClient.EndInitialize(ar);
                                    _lyncClient.StateChanged += ClientStateChanged;
                                },
                                null);
                                break;
                            case ClientState.SigningIn:
                                Thread.Sleep(100);
                                break;
                            case ClientState.SignedOut:
                                SignIn(_username, _username, _password);
                                Thread.Sleep(100);
                                break;
                        }

                    var contact = _lyncClient.ContactManager.GetContactByUri(emailAddress);
                    Thread.Sleep(1000);
                    var contactInfo = contact.GetContactInformation(new List<ContactInformationType>
                    {
                        ContactInformationType.Availability,
                        ContactInformationType.ContactEndpoints,
                        ContactInformationType.Title,
                        ContactInformationType.Company,
                        ContactInformationType.Department
                    });

                    return ConvertToSkypeViewModel(emailAddress, contactInfo);
                }
            }
            catch (Exception e)
            {
                // Handle exception
            }
        }

        private SkypeContactInfoViewModel ConvertToSkypeViewModel(string emailAddress,
            IDictionary<ContactInformationType, object> contactInfo)
        {
            var result = new SkypeContactInfoViewModel();
            if (contactInfo.TryGetValue(ContactInformationType.Availability, out var availability))
                result.AvailabilityStatus = (ContactAvailability) availability switch
                {
                    ContactAvailability.Invalid => Enums.ContactAvailabilityStatus.Invalid,
                    ContactAvailability.None => Enums.ContactAvailabilityStatus.None,
                    ContactAvailability.Free => Enums.ContactAvailabilityStatus.Free,
                    ContactAvailability.FreeIdle => Enums.ContactAvailabilityStatus.FreeIdle,
                    ContactAvailability.Busy => Enums.ContactAvailabilityStatus.Busy,
                    ContactAvailability.BusyIdle => Enums.ContactAvailabilityStatus.BusyIdle,
                    ContactAvailability.DoNotDisturb => Enums.ContactAvailabilityStatus.DoNotDisturb,
                    ContactAvailability.TemporarilyAway => Enums.ContactAvailabilityStatus.TemporarilyAway,
                    ContactAvailability.Away => Enums.ContactAvailabilityStatus.Away,
                    ContactAvailability.Offline => Enums.ContactAvailabilityStatus.Offline,
                    _ => Enums.ContactAvailabilityStatus.Invalid
                };
            if (contactInfo.TryGetValue(ContactInformationType.ContactEndpoints, out var endPoints))
                ((List<object>) endPoints).ForEach(endPointObject =>
                {
                    if (endPointObject is ContactEndpoint endPoint && endPoint.Type == ContactEndpointType.WorkPhone)
                        result.WorkPhone = endPoint.DisplayName;
                });
            if (contactInfo.TryGetValue(ContactInformationType.Title, out var title)) result.JobTitle = (string) title;
            if (contactInfo.TryGetValue(ContactInformationType.Company, out var company))
                result.CompanyName = (string) company;
            if (contactInfo.TryGetValue(ContactInformationType.Department, out var department))
                result.Department = (string) department;

            return result;
        }

        private void ClientStateChanged(object source, ClientStateChangedEventArgs data)
        {
            if (data.NewState != ClientState.SignedOut) return;
            if (_lyncClient.InSuppressedMode)
                SignIn(_username, _username, _password);
        }

        public void SignIn(string userUri, string domain, string password)
        {
            _lyncClient.CredentialRequested += CredentialRequested;
            if (_lyncClient.State == ClientState.SignedOut)
                _lyncClient.BeginSignIn(
                    userUri,
                    domain,
                    password,
                    callback => { _lyncClient.EndSignIn(callback); },
                    null);
        }

        private void CredentialRequested(object sender, CredentialRequestedEventArgs e)
        {
            if (e.Type == CredentialRequestedType.SignIn)
                e.Submit(_username, _password, true);
        }
    }
}

Upvotes: 0

The answer to my question/problem is to call the GetClient() from the same thread as it is called from the first time. This seems to never get a client in the Invalid state.

Upvotes: 4

Related Questions