lynclync-2013lync-client-sdk

Exception raised attempting to access Lync.DeviceManager.AudioDevices - but not the Count property


Trying to set the active Lync Audio device to one of the available audio devices. Lync_Client.DeviceManager.AudioDevices.Count returns a number greater than 0 but statements like Lync_CLient.DeviceManager.AudioDevices[i] in a for loop from i = 0 to i < count or foreach (AudioDevice dev in Lync_Client.DeviceManager.AudioDevices) immediately raises an exception when run on Windows 10 PC - but not on Windows 7 PC. Windows 10 version produces an exception with the Message: "Exception has been thrown by the target of an invocation.

Any suggestions? Could this be a privilege issue?

Below is the StackTrace:

...at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
...at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
...at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
...at Microsoft.Lync.Model.Internal.UCWCache.CreateUCW(Object source, CCOMInfo ccomInfo)
...at Microsoft.Lync.Model.Internal.UCWCache.GetITTargetNS(Object source)
...at Microsoft.Lync.Model.Internal.UCEnumerator`2.get_Current()
...at ...Microsoft.Lync.Model.Internal.UCEnumerator`2.System.Collections.Generic.IEnumerator<S>.get_Current()

The stack from here on out points to my code that attempts to access the Lync AudioDevices elements enumeration


Solution

  • The problem is that Microsoft stop releasing the Lync Client SDK for Lync 2013 Client. Even though the SDK still works so the latest version of the Skype for Business Client, it is actually slowly breaking due to incompatibilities between the current Skype for Business client and the older Lync Client SDK.

    The AudioDevice area of the SDK is a one of the known areas of the SDK where the Client SDK is breaking. There is a workaround where you can drop down to the actual the raw COM interfaces that the Lync Client SDK uses and then use those COM objects directly get access to the API.

    You can escape the Lync Client SDK into the raw COM objects by accessing the "InnerObject" field of the Lync Client SDK object.

    eg:

        static bool SetClientAudioDevice(LyncClient client, string name)
        {
            var innerClient = (ILyncClient)client.InnerObject;
            var deviceManager = innerClient.DeviceManager;
    
            Console.WriteLine("Current audio device: [{0}]", client.DeviceManager.ActiveAudioDevice.Name);
            Console.WriteLine("Lync Client Audio Devices List:");
            var ok = false;
            foreach (var device in deviceManager.AudioDevices.OfType<Microsoft.Office.Uc.AudioDevice>())
            {
                Console.WriteLine("    AudioDevice: [{0}], Active[{1}], ID[{2}], IsCertified[{3}], Priority[{4}], Type[{5}]", device.Name, device.IsActive, device.Id, device.IsCertified, device.Priority, device.Type);
    
                if (device.Name.IndexOf(name, StringComparison.InvariantCultureIgnoreCase) >= 0)
                {
                    Console.WriteLine("        Setting active device!");
                    deviceManager.ActiveAudioDevice = device;
                    ok = true;
                }
            }
            return ok;
        }
    

    As pointed out in the comments, you also have to add a reference to "Microsoft.Office.Uc" and also set the Embed InteropType to False.