Reputation: 1258
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
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
Reputation: 1258
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