2014-01-30 2 views
1

http://code.msdn.microsoft.com/office/CppAutomateOutlook-55251528 состояния:Office Automation с #import вредным?

[...] Это очень мощный, но часто не рекомендуется из-за проблем подсчета ссылок, которые обычно возникают при использовании с приложений Microsoft Office. [...]

Какие конкретно проблемы с подсчетом конкретно упоминаются здесь? Например, применим ли он к конкретному примеру?

Как и в примере, я просто хочу открыть Outlook, создать встречу, сделать.

Я хотел использовать #import, но это заявление заставляет меня бояться об этом ...

ответ

1

circular reference происходит, когда у вас есть два или более объектов, удерживающих ссылки друг на друг, прямо или косвенно. В COM это означает, что связанные с кругом объекты вызвали IUnknown::AddRef друг на друга.

В случае автоматизации Excel это может произойти, если вы подключите обработчик событий (приемник) к событиям поиска источников Excell (через IConnectionPoint::Advise). Таким образом, вы можете хранить ссылку, например, на объект Application, а объект Application хранит ссылку на вашу раковину.

Эта проблема не относится к интеллектуальным указателям, сгенерированным директивой VC++ #import. Речь идет о том, как вы обрабатываете завершение работы COM-объектов, когда они вам больше не нужны. Вы должны явно разорвать все сделанные вами соединения (т. Е. Сделать IConnectionPoint::Unadvise) и вызвать любой явный API выключения, который объект может выставить (например, Workbook::Close или Application::Quit). Затем вы должны явно освободить ссылку (например, вызвать workbookPtr.Release() по умному указателю).

При этом, если вы не обрабатываете какие-либо события COM, полученные от Excel, вам не следует беспокоиться, вероятность того, что вы можете создать круговую ссылку, будет низкой. Кроме того, Excel - это COM-сервер вне процесса обработки, а COM имеет около garbage collection logic, чтобы управлять временем жизни внепроцессных серверов. Однако, пока ваше приложение все еще открыто, процесс Excel будет поддерживаться до тех пор, пока все ссылки на его объект не будут выпущены, или вызывается Application::Quit.

+1

Отлично, спасибо! Я знаю о круговых ссылках, но я не знал, что это было причиной этого утверждения. Поэтому я могу безопасно использовать #import с этим. – divB

+1

@divB, выполните «нормальный уровень предосторожности», если вы не обрабатываете события. В противном случае выполните «высокий уровень предосторожности» и явно освободите любые интеллектуальные указатели, когда закончите с определенным объектом Excel. ** Если ваше приложение завершается, но Excel.exe все еще зависает в списке процессов более чем на несколько секунд, это будет плохой знак. ** – Noseratio

1

Это довольно бессмысленно. Программирование Interop с помощью #import - это шаблон и рекомендуемый способ. Типы интеллектуальных указателей, которые он автоматически генерирует, явно предназначены для автоматического подсчета ссылок, поэтому вы не можете забыть вызвать Release(). Есть несколько острых краев, вам нужно понять, что умные указатели могут делать и не делать.

В противном случае это относится к курсу для команды, которая находится за рамкой кода «все-в-одном». Образцы создаются группой поддержки в Шанхае, изначально нанятой для помощи на форумах MSDN. Эти ребята не имеют таких учетных данных, которые вы ожидаете от программиста Microsoft, который работает в Редмонде, и их фрагменты не проверяются. Некоторые из них совершенно задуманы. Если вы когда-либо задавали вопросы на форумах MSDN и видели ответы, которые они публикуют, тогда вы знаете, что я имею в виду.

Образец Solution2.cpp использует последнее связывание через IDispatch. Это определенно трудный способ взаимодействовать с Office, вы не получаете никакой помощи, когда пишете код. IntelliSense не может предоставить вам какую-либо полезную информацию при написании вызова метода, а также не может компилятор сказать вам, что вы пропустили аргумент или неправильно присвоили тип аргумента.Ваша программа не работает во время выполнения с непрозрачным кодом ошибки, например DISP_E_BADVARTYPE или DISP_E_BADPARAMCOUNT. И вызовы Release() должны быть сделаны явно, что, конечно, делает проще пропустить один. Проблемы, которых у вас нет, когда вы используете интеллектуальные указатели, они дают вам автоматическое завершение и проверку типов. Вы сами можете видеть, насколько меньше и читается Solution1.cpp.

Диагностика пропущенного вызова Release() в противном случае легко, ваша программа завершается, но вы все равно увидите, что Outlook.exe запущен в диспетчере задач. Что-то вы привыкнете к проверке в любом случае, это также произойдет, когда вы отлаживаете свою программу, находите ошибку и останавливаете программу для исправления. Который, конечно, также запрещает вызывать Release(), чтобы Outlook продолжал работать. Вы должны убить его самостоятельно.

Рассмотрите возможность написания такого кода на управляемом языке, таком как C# или VB.NET. Вы получите дополнительную скидку , если у вас есть проблема, и вы найдете много примеров кода. И сборщик мусора никогда не забыл сделать звонок на освобождение. Это просто немного медленно при этом.

Смежные вопросы