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

发布于 2024-09-06 01:12:05 字数 3658 浏览 9 评论 0 原文

我正在编写一个 Java 程序,它使用 Jacob 库(桥接 COM 和 Java)与 Microsoft Outlook 交互。此程序创建一个新的 MailItem显示检查器 窗口给用户。我希望订阅检查员的关闭活动 了解用户何时完成编辑邮件项目。

为了订阅该活动,我按照 Jacob 文档 中的说明进行操作(关于 23 下一页):

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

这是我的 InspectorEventHandler 类,符合 Jacob 的文档:

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

根据Google 以及其他一些网站也收到了此错误。不幸的是,他们都没有收到答复。

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

版本 1.7 还包含可读取的代码 直接从类型库 前辈。这使得工作成为可能 与所有 Microsoft Office 应用程序事件,以及 IE5 事件。有关示例,请参阅 示例/测试/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");

所有这些尝试都因相同的错误而失败。

I am writing a Java program that interacts with Microsoft Outlook using the Jacob library (bridges COM and Java). This program creates a new MailItem, displaying its Inspector window to the user. I wish to subscribe to the inspector's Close event to know when the user is finished editing their mail item.

To subscribe to the event, I followed the instructions in Jacob's documentation (about 23 down the page):

The current [event] model is conceptually
similar to the Visual Basic WithEvents
construct. Basically, I provide a
class called
com.jacob.com.DispatchEvents which has
a constructor that takes a source
object (of type
com.jacob.com.Dispatch) and a target
object (of any type). The source
object is queried for its
IConnectionPointContainer interface
and I attempt to obtain an
IConnectionPoint for its default
source interface (which I obtain from
IProvideClassInfo). At the same time,
I also create a mapping of DISPID's
for the default source interface to
the actual method names. I then use
the method names to get jmethodID
handles from the target Java object.
All event methods currently must have
the same signature: one argument which
is a Java array of Variants, and a
void return type.

Here is my InspectorEventHandler class, conforming to Jacob's documentation:

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) {

    }

}

And here is how I subscribe to the events using this InspectorEventHandler class:

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);

However, the last line fails with the following exception:

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, a few others have also received this error. Unfortunately, none of them have received an answer.

I am using version 1.7 of the Jacob library, which claims to prevent this problem:

Version 1.7 also includes code to read
the type library directly from the
progid. This makes it possible to work
with all the Microsoft Office
application events, as well as IE5
events. For an example see the
samples/test/IETest.java example.

I noticed that the aforementioned IETest.java file subscribes to events like this:

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

Therefore, I tried subscribing to my events in a similar manner:

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

All these attempts failed with the same error.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

小情绪 2024-09-13 01:12:05

经过一番实验,我确定通过订阅 MailItemClose 事件 而不是 检查器关闭 事件。我现在有一个 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< 似乎有问题/code> 对象注册...

After some experimentation, I determined that I could achieve the desired result by subscribing to the MailItem's Close event rather than the Inspector's Close event. I now have a MailItemEventHandler class that handles all 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");
    }

}

I subscribe to the events using:

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

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

I don't know much about COM, but it appears that there is something wrong with the Inspector object registration...

傲世九天 2024-09-13 01:12:05

自从你努力做好你的工作以来,雅各布可能已经改变了。今天,使用 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

Jacob may have changed since you were trying to do your job. Today, with Jacob 1.15-M3, I managed to receive events from Excel, but only using 4 argument constructor:

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

Giving the path to the executable is quite unportable, but I guess it's possible to workaround it somehow. I was only doing tests, so hardcoded executable was ok for me.

With fewer arguments I was receiving the same errors as you:

Exception in thread "main" com.jacob.com.ComFailException: Can't find event iid
(...)
GetEventIID: couldn't get IProvideClassInfo
红墙和绿瓦 2024-09-13 01:12:05

我想附加到 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");
    }
}

I wanted to attach to the Close event of an Word instance and got similar error if didn't put the right Dispatch object in the parameter list of DispatchEvents, but this works in my case, now.

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);

and

import com.jacob.com.*;

public class WordEventHandler {
    public void Close(Variant[] arguments) {
        System.out.println("closed word document");
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文