События Java, Jacob и Microsoft Outlook: ошибка "Не удается найти событие"

Я пишу программу на 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);

Однако последняя строка завершается с ошибкой:

Исключение в потоке "main" com.jacob.com.ComFailException: не удается найти событие iid
    на com.jacob.com.DispatchEvents.init(собственный метод)
    в com.jacob.com.DispatchEvents.(DispatchEvents.java)
    at cake.CakeApplication.run(CakeApplication.java:30)
    на торт.CakeApplication.main(CakeApplication.java:15)
не удалось получить IProvideClassInfo

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

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

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

Решение

После некоторых экспериментов я решил, что смогу достичь желаемого результата, подписавшись на MailItem "s Close событие, а не Inspector "s 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 регистрация объекта...

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

Я хотел присоединиться к событию 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");
    }
}
Другие вопросы по тегам