События Java, Jacob и Microsoft Outlook: ошибка «Не удается найти событие» - PullRequest
2 голосов
/ 16 июня 2010

Я пишу программу на Java, которая взаимодействует с Microsoft Outlook, используя библиотеку Jacob (соединяет COM и Java).Эта программа создает новое MailItem , , отображающее его Инспектор для пользователя.Я хочу подписаться на Закрыть событие инспектора , чтобы знать, когда пользователь закончит редактирование своего почтового элемента.

Чтобы подписаться на событие, я следовал инструкциям Документация Джейкоба (около 2 3 вниз по странице):

Текущая модель [события] концептуально похожа на конструкцию Visual Basic WithEvents,По сути, я предоставляю класс с именем com.jacob.com.DispatchEvents, который имеет конструктор, который принимает исходный объект (типа com.jacob.com.Dispatch) и целевой объект (любого типа).Исходный объект запрашивается для его интерфейса IConnectionPointContainer, и я пытаюсь получить IConnectionPoint для его исходного интерфейса по умолчанию (который я получаю из IProvideClassInfo).В то же время я также создаю отображение DISPID для исходного интерфейса по умолчанию на фактические имена методов.Затем я использую имена методов, чтобы получить jmethodID дескрипторы от целевого объекта Java. В настоящее время все методы событий должны иметь одну и ту же сигнатуру: один аргумент, представляющий собой массив вариантов Java, и возвращаемый тип void.

Вот мой класс 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

Согласно Google , некоторые другие также получили эту ошибку.К сожалению, никто из них не получил ответа.

Я использую версию 1.7 библиотеки Jacob, которая утверждает, что предотвращает эту проблему:

Версия 1.7 также включает код для чтениябиблиотека типов прямо из проги.Это позволяет работать со всеми событиями приложения 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 ]

2 голосов
/ 16 июня 2010

После некоторых экспериментов я решил, что могу достичь желаемого результата, подписавшись на 1003 * Close событие вместо Inspector Close . Теперь у меня есть класс MailItemEventHandler, который обрабатывает все MailItem события :

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 голос
/ 13 октября 2012

Джейкоб, возможно, изменился с тех пор, как вы пытались выполнять свою работу.Сегодня с 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
0 голосов
/ 08 сентября 2012

Я хотел присоединиться к событию Close экземпляра Word и получил похожую ошибку, если не поместил нужный объект 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");
    }
}
...