0

我正在开发一个浏览器外的 Silverlight 应用程序,它提供了一些 MS Office Communicator 2007 控件。我正在使用自动化 SDK。随 SDK 一起安装的文档指出 IMessenger2 接口中有一个 MyGroups 属性,它将返回用户定义的组,但是当我尝试使用它时,我得到一个NotImplementedException. 这是我正在使用的代码:

dynamic communicator = AutomationFactory.CreateObject("Communicator.UIAutomation");
communicator.AutoSignin();
foreach (dynamic g in communicator.MyGroups)
{
    //Do something with the group
}

如果我用 MyContacts 替换 MyGroups,我可以获得联系人列表就好了。我必须做一些不同的事情来访问 IMessenger2 界面中的属性吗?我在网上看到一些事情说 MyGroups 已被 Windows Messenger 弃用,但从文档看来,它似乎应该可用于 MS Office Communicator。

如果我不能使用 MyGroups,是否有其他方法可以获取用户创建的组?

4

1 回答 1

0

这里的问题是 MyGroups 属性被标记为 NotScriptable,这意味着您不能以您正在使用的方式调用它,即使用 AutomationFactory。出于安全原因,自动化 API 中的某些属性和方法不可编写脚本 - 这是为了避免恶意页面使 Communicator 自动化并在您不知情的情况下执行某些任务。

看起来 Silverlight 中的 COM 互操作的处理方式与从 VBScript 创建和调用 API 的方式相同,因此您将无法访问任何不可编写脚本的属性和方法。有关哪些属性和方法不可编写脚本的详细信息,请参阅参考资料。

我猜这会严重阻碍您的应用程序。我认为伤害你的是选择 Silverlight OOB 的决定。有什么方法可以使用 WPF(甚至是 winforms)而不是 Silverlight?如果您这样做了,您可以直接引用 API,并拥有对所有属性/方法的完全访问权限。

否则,我想不出太多选择。您无法捕获该OnContactAddedToGroup事件,因为它不可编写脚本。

可以使用 .NET 程序集包装 API,并通过 COM 公开它,然后以相同的方式对其进行实例化 - 但在这种情况下可能仍会尊重 Not Scriptable,因此它不会给您带来任何好处。如果不尝试就很难说,而且仍然是一个相当可怕的解决方案。

编辑:我刚刚尝试了包装方法(需要为客户做类似的概念证明),它似乎有效。我就是这样做的:

创建一个新的 .NET 类库。定义一个 COM 接口:

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

定义一个实现该接口的类(您需要从 SDK 引用 CommunicatorAPI.dll):

[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());
    }
}

使用RegAsm构建和注册。然后从 OOB silverlight 应用程序调用:

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

请注意,同样的技术也适用于 Lync API:

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

虽然这可行,但我不能说这是否是一个好的做法,因为它正在解决一个安全限制,这可能是有充分理由的。我猜可能发生的最糟糕的情况是,如果恶意网页知道控件的 ProgId,它可能会使用该组件。

编辑:另外,使用这种方法,您需要小心内存泄漏,例如,确保在完成 COM 对象后释放它们 - 很容易做到,只需要一点纪律;o)

于 2010-12-01T17:29:10.983 回答