События Java, Jacob и Microsoft Outlook: при получении не удается найти событие iid Error

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

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

Текущая модель [event] концептуально похожа на конструкцию 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, несколько другие также получили эту ошибку. К сожалению, ни один из них не получил ответа.

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

Версия 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");

Все эти попытки заканчивались одной и той же ошибкой.


person Adam Paynter    schedule 16.06.2010    source источник


Ответы (3)


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

person Adam Paynter    schedule 16.06.2010

Джейкоб, возможно, изменился с тех пор, как вы пытались выполнять свою работу. Сегодня с 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
person Jarekczek    schedule 13.10.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");
    }
}
person Nick    schedule 08.09.2012