События 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");
}
}