MyGroups not implemented in Communicator.UIAutomation

隐身守侯 提交于 2019-12-02 10:34:14

The problem here is that the MyGroups property is marked as NotScriptable, meaning you can't call it in the way you are doing i.e. using the AutomationFactory. For security reasons, some properties and methods in the Automation API are not scriptable - this is to avoid malicious pages automating Communicator and carrying out certain tasks without you knowing.

It looks like the COM interop in Silverlight is treated in the same way as e.g. creating and calling the API from VBScript, so you won't be able to access any of the non-scriptable properties and methods. See the reference for details of which properties and methods are not scriptable.

I'm guessing this is going to seriously hobble your app. I think what's hurting you is the decision to go with Silverlight OOB. Is there any way you could use WPF (or even winforms) rather than Silverlight? If you did this, you could reference the API directly, and have full access to all properties/methods.

Otherwise, I can't think of too many options. You can't trap the OnContactAddedToGroup event, as this is not scriptable.

It might be possible to wrap the API with a .NET assembly, and expose it via COM, then instantiate it in the same way - but the Not Scriptable might still be respected in that case, so it won't buy you anything. Hard to say without trying it, and still a fairly horrible solution.

Edit: I've just given the wrapper method a try (needed to do something similar as a proof of concept for a customer), and it seems to work. This is the way I did it:

Create a new .NET class library. Define a COM interface:

[ComVisible(true)]
[Guid("8999F93E-52F6-4E29-BA64-0ADC22A1FB11")]
public interface IComm
{
    string GetMyGroups();
}

Define a class that implements that interface (you'll need to reference CommunicatorAPI.dll from the SDK):

[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[GuidAttribute("C5C5A1A8-9BFB-4CE5-B42C-4E6688F6840B")]
[ProgId("Test.Comm.1")]
public class Comm : IComm
{
    public string GetMyGroups()
    {
        var comm = new CommunicatorAPI.MessengerClass();

        var groups = comm.MyGroups as IMessengerGroups;
        return string.Join(", ", groups.OfType<IMessengerGroup>().Select(g => g.Name).ToArray());
    }
}

Build, and register using RegAsm. Then call from the OOB silverlight app:

dynamic communicator = AutomationFactory.CreateObject("Test.Comm.1");
MessageBox.Show(communicator.GetMyGroups());

Note, the same technique also works using the Lync API:

public string GetMyGroups()
{
    var comm = LyncClient.GetClient();
    return string.Join(", ", comm.ContactManager.Groups.Select(g => g.Name).ToArray());
}

Although this works, I can't really say whether it's a good practice, as it's working around a security restriction which was presumably there for a good reason. I guess the worst that could happen is that a malicious web page could potentially use the component, if it knew the ProgId of the control.

Edit: Also, using this method you'd need to be careful about memory leaks, e.g. make sure you're releasing COM objects when you're finished with them - easy enough to do, just needs a little discipline ;o)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!