Java,Jacob和Microsoft Outlook事件:接收“找不到事件iid”错误

时间:2010-06-16 11:55:48

标签: java com outlook events jacob

我正在编写一个Java程序,它使用Jacob library(桥接COM和Java)与Microsoft Outlook交互。该程序为用户创建了一个新的MailItemdisplayingInspector窗口。我希望订阅检查员的Close event,以了解用户何时完成了邮件的编辑。

要订阅该活动,我按照Jacob's documentation中的说明(关于页面上的 2 / 3 ):

  

当前[事件]模型在概念上   类似于Visual Basic WithEvents   构造。基本上,我提供了一个   上课了   com.jacob.com.DispatchEvents有   一个获取源的构造函数   对象(类型   com.jacob.com.Dispatch)和目标   对象(任何类型)。来源   对象被查询   IConnectionPointContainer界面   我试图获得一个   IConnectionPoint为默认值   源接口(我从中获取)   IProvideClassInfo)。同时,   我还创建了DISPID的映射   对于默认的源接口   实际的方法名称。然后我用   获取jmethodID的方法名称   来自目标Java对象的句柄。   目前必须拥有所有事件方法   相同的签名:一个论点   是一个变种的Java数组,和   void return type。

这是我的InspectorEventHandler课程,符合雅各布的文件:

public class InspectorEventHandler {

    public void Activate(Variant[] arguments) {

    }

    public void BeforeMaximize(Variant[] arguments) {

    }

    public void BeforeMinimize(Variant[] arguments) {

    }

    public void BeforeMove(Variant[] arguments) {

    }

    public void BeforeSize(Variant[] arguments) {

    }

    public void Close(Variant[] arguments) {
        System.out.println("Closing");
    }

    public void Deactivate(Variant[] arguments) {

    }

    public void PageChange(Variant[] arguments) {

    }

}

以下是我使用此InspectorEventHandler类订阅事件的方式:

Object outlook = new ActiveXComponent("Outlook.Application");
Object mailItem = Dispatch.call(outlook, "CreateItem", 0).getDispatch();
Object inspector = Dispatch.get(mailItem, "GetInspector").getDispatch();

InspectorEventHandler eventHandler = new InspectorEventHandler();

// This supposedly registers eventHandler with the inspector
new DispatchEvents((Dispatch) inspector, eventHandler);

但是,最后一行失败,出现以下异常:

Exception in thread "main" com.jacob.com.ComFailException: Can't find event iid
    at com.jacob.com.DispatchEvents.init(Native Method)
    at com.jacob.com.DispatchEvents.(DispatchEvents.java)
    at cake.CakeApplication.run(CakeApplication.java:30)
    at cake.CakeApplication.main(CakeApplication.java:15)
couldn't get IProvideClassInfo

According to Google,其他一些人也收到了这个错误。不幸的是,他们都没有得到答案。

我正在使用雅各布库的1.7版,它声称可以防止这个问题:

  

1.7版还包括要读取的代码   直接来自的类型库   进程id。这使得工作成为可能   与所有Microsoft Office   应用程序事件,以及IE5   事件。有关示例,请参阅   samples / test / IETest.java示例。

我注意到前面提到的IETest.java文件订阅了这样的事件:

new DispatchEvents((Dispatch) ieo, ieE,"InternetExplorer.Application.1");

因此,我尝试以类似的方式订阅我的活动:

new DispatchEvents((Dispatch) inspector, eventHandler, "Outlook.Application");
new DispatchEvents((Dispatch) inspector, eventHandler, "Outlook.Application.1");
new DispatchEvents((Dispatch) inspector, eventHandler, "Outlook.Application.12");

所有这些尝试都失败并出现同样的错误。

3 个答案:

答案 0 :(得分:2)

经过一些实验,我决定通过订阅MailItem's Close event而不是Inspector's Close event来达到预期的效果。我现在有一个MailItemEventHandler类来处理所有MailItem events

public class MailItemEventHandler {

    public void AttachmentAdd(Variant[] arguments) {
        System.out.println("AttachmentAdd");
    }

    public void AttachmentRead(Variant[] arguments) {
        System.out.println("AttachmentRead");
    }

    public void AttachmentRemove(Variant[] arguments) {
        System.out.println("AttachmentRemove");
    }

    public void BeforeAttachmentAdd(Variant[] arguments) {
        System.out.println("BeforeAttachmentAdd");
    }

    public void BeforeAttachmentPreview(Variant[] arguments) {
        System.out.println("BeforeAttachmentPreview");
    }

    public void BeforeAttachmentRead(Variant[] arguments) {
        System.out.println("BeforeAttachmentRead");
    }

    public void BeforeAttachmentSave(Variant[] arguments) {
        System.out.println("BeforeAttachmentSave");
    }

    public void BeforeAttachmentWriteToTempFile(Variant[] arguments) {
        System.out.println("BeforeAttachmentWriteToTempFile");
    }

    public void BeforeAutoSave(Variant[] arguments) {
        System.out.println("BeforeAutoSave");
    }

    public void BeforeCheckNames(Variant[] arguments) {
        System.out.println("BeforeCheckNames");
    }

    public void BeforeDelete(Variant[] arguments) {
        System.out.println("BeforeDelete");
    }

    public void Close(Variant[] arguments) {
        System.out.println("Close");
    }

    public void CustomAction(Variant[] arguments) {
        System.out.println("CustomAction");
    }

    public void CustomPropertyChange(Variant[] arguments) {
        System.out.println("CustomPropertyChange");
    }

    public void Forward(Variant[] arguments) {
        System.out.println("Forward");
    }

    public void Open(Variant[] arguments) {
        System.out.println("Open");
    }

    public void PropertyChange(Variant[] arguments) {
        System.out.println("PropertyChange");
    }

    public void Read(Variant[] arguments) {
        System.out.println("Read");
    }

    public void Reply(Variant[] arguments) {
        System.out.println("Reply");
    }

    public void ReplyAll(Variant[] arguments) {
        System.out.println("ReplyAll");
    }

    public void Send(Variant[] arguments) {
        System.out.println("Send");
    }

    public void Unload(Variant[] arguments) {
        System.out.println("Unload");
    }

    public void Write(Variant[] arguments) {
        System.out.println("Write");
    }

}

我使用以下方式订阅活动:

Object outlook = new ActiveXComponent("Outlook.Application");
Object mailItem = Dispatch.call(outlook, "CreateItem", 0).getDispatch();

MailItemEventHandler eventHandler = new MailItemEventHandler();
new DispatchEvents((Dispatch) mailItem, eventHandler);

我对COM知之甚少,但看来Inspector对象注册有问题......

答案 1 :(得分:1)

雅各布可能在你努力完成工作后发生了变化。今天,使用Jacob 1.15-M3,我设法从Excel接收事件,但只使用了4个参数构造函数:

DispatchEvents de = new DispatchEvents(
  sh,
  new Sink(), 
  "Excel.Sheet",
  "C:\\Program Files (x86)\\Microsoft Office\\OFFICE11\\EXCEL.EXE"
);

给可执行文件的路径是非常不可移植的,但我想有可能以某种方式解决它。我只是在做测试,所以硬编码的可执行文件对我来说还可以。

参数越少,我就会收到与您相同的错误:

Exception in thread "main" com.jacob.com.ComFailException: Can't find event iid
(...)
GetEventIID: couldn't get IProvideClassInfo

答案 2 :(得分:0)

我想附加到Word实例的Close事件,并且如果没有将正确的Dispatch对象放在DispatchEvents的参数列表中,则会出现类似错误,但现在这种情况适用于我的情况。

ActiveXComponent oWord = new ActiveXComponent("Word.Application");
oWord.setProperty("Visible", new Variant(true));
Dispatch oDocuments = oWord.getProperty("Documents").toDispatch();
Dispatch oDocument = Dispatch.call(oDocuments, "Open", strInputDoc).toDispatch();
WordEventHandler w = new WordEventHandler();
new DispatchEvents(oDocument, w);

import com.jacob.com.*;

public class WordEventHandler {
    public void Close(Variant[] arguments) {
        System.out.println("closed word document");
    }
}