singlepost

Несколько вопросов по COM (в PHP) << На главную или назад  

У меня есть скрипт который обрабатывает закаченные doc файлы:

$word = new COM("word.application");

$word->Documents->Open($filename);

$word->Selection->Font->Name = 'Verdana';
$word->Selection->Font->Size = 8;

$word->Documents[1]->Save();

$word->quit();

Кто-нибуть знает как реализовать:
1. при выполнении Open не запускать АвтоМакросы (Если честно не знаю открываются они или нет, но недавно удалил тьму вирусов с сервака=)))

2. После безопасного открытия удалить все макросы из файла

3. Как видно из скрипта ворд запускается при каждом обращении к скрипту. Есть ли вариант не запускать новый, а обратиться к уже открытому экземпляру Ворда?(в сессию com-бъект сохранить нельзя, но если ворд не закрыть он продолжит висеть в памяти) При этом надо учитывать что скрипт может одновременно запускаться несколько раз, что бы не было конфликтов при обращении к одному и тому же экземпляру Ворда.

27 ответов в теме “Несколько вопросов по COM (в PHP)”

  1. 14
    Алексей Вишняков ответил:

    Ну ясно, будем капать.=)) Еще раз большое спасибо!

  2. 13
    Дмитрий Гайдамович ответил:

    Эти беды мы пока не победили. У нас правда Word несколько в ином контексте "дёргается": будучи активированным внутри нашего приложения-контейнера. Но подобные ошибки иногда вываливаются, довольно бессистемно, прогресса по ним пока нет. Если будет продвижение – рад буду услышать как Вы это "вылечили" :)

  3. 12
    Алексей Вишняков ответил:

    В общем сделал так. Каждый скрипт устанавливает в БД параметр, если он хочет занять ворд. Если параметр уже установлен, то ждет освобождения какое-то время. В общем все идет нормально. Переодически бывает, что одновременно оказываются запущенными 2 ворда. Не знаю откуда это. На всякий случай написал утилитку на С++ которая выкидывает их памяти всех вордов. Вызываю перед каждым освобождением параметра.

    Дмитрий Гайдамович. Большой-большой респект за помощь.=)))

    Единственная проблема – переодически выскакивают Exeption's:
    1. Unable to lookup `Range': The object invoked has disconnected from its clients.
    2. Unable to lookup `Range': Call was rejected by callee.
    3. Unable to lookup `Range': The interface is unknown.
    (Выскакивали они до того как я добавил killword)
    Строка: $doc->Range->InsertFile($file);
    Но док-файлы на которых это происходит спокойно обрабатываются на второй раз.

  4. 11
    Дмитрий Гайдамович ответил:

    Word фиговый в том плане, что он иногда пытается открывать окна с сообщениями об ошибках, или для подтверждения чего-либо, будучи запущенным в невидимом режиме, вместо того, чтобы генерировать нормальный OLE-exception. Как правило, в этом случае мы намертво встаём в модальном цикле, и закрыть окно мы тоже не можем, так как его нет, как ни странно это прозвучит.

    Лучше взять Range у Document и делать InsertFile прямо у него, а про Selection забыть.

  5. 10
    Алексей Вишняков ответил:

    В общем ситуация такая
    Нашел статью //support.microsoft.com/kb/257757/ru
    в которой микрософт рассказывает почему не следует делать с вордом то, что делаю я.=)) Судя по этой статье "залипания" ворда происходят во время появления каких-то ошибок(точнее сообщений об ошибках).

    В общем решил создавать Word.Document. и делать вставку из файла. Это кстати решает проблему с макросами=) И ворд закрываеться сам по окончании работы скрипта.

    Единственное что не понятно: что будет если 2 скрипта обращаются к одному и тому же $word->Selection:

    $doc = new COM("Word.Document");
    $word = $doc->Application;
    {в этот момент запускается второй скрипт и выполняет предыдущие команды}
    $word->Selection->InsertFile('C:\\file.doc');
    // Тут идет модификация текста
    $doc->SaveAs('C:\\file.doc');
    $doc->Close();

    Получается вставка произойдет не в тот документ, так как обе $word->Selection будут указывать на одно и тоже выделение.

    PS Я понял про прокси процесс и контроль монопольного доступа. Только на php это не так просто сделать, учитывая уже существующую модель приложения. Но если не останется вариантов, то так и сделаю.

  6. 9
    Дмитрий Гайдамович ответил:

    WINWORD.EXE склонен "залипать" в памяти, факт. И порой источник "размножения" winword не совсем ясен.Для борьбы с этим явлением можно применять следующие способы. 1) После отпускания всех объектов, когда необходимость в Word-е отпала – не забывать делать Application.Quit(). Часто эта веточка хотя и предусмотрена в программе, однако не выполняется. К тому же данный подход не спасает, если программа, использующая Word, завершается аварийно. А это в нашем неидеальном мире – распространённое явление. Тогда приходится делать вариант 2): Proxy-процесс. Идея в следующем. Ссылку на созданный Word.Applicatoin получаем не непосредственно от подсистемы COM, а создаём программу, которая создаёт этот объект по требованию, и отдаёт нам ссылку на созданный объект. Кроме того, что она может помочь в предотвращении повторного создания, эта программа также делает следующее: она "следит" за состоянием основного процесса, и когда он "умирает" – то "убивает" тот Word, который был закреплён за ним. При этом неважно, завершается ли основной процесс штатно или аварийно – winword будет выгружен из памяти по-любому.

    Да, и ещё. Если доступ к Word происходит из нескольких потоков – то лучше делать это в критической секции, куда "запускается" единственный поток. В противном случае будут глюки, мы это проходили.

  7. 8
    Алексей Вишняков ответил:

    Выкинул из памяти все процессы WINWORD.EXE Теперь все стало сново работать. Добавил логирование исключений, в файл. теперь буду ждать когда появится ошибка сново.

    Интересно что ошибка добавляеться в php-errors.log файл не сразу, а примерно через 4 часа.

    И еще: В системном логере приложений появилось дикое количество ошибок типа:

    Event Type:Error
    Event Source:Microsoft Office 11
    Event Category:None
    Event ID:2001
    Date:10.04.2008
    Time:20:41:15
    User:N/A
    Description:
    Rejected Safe Mode action : Microsoft Office Word.

    For more information, see Help and Support Center at //go.microsoft.com/fwlink/events.asp.

    но по времени они не очень совпадают с ошибками в php_errors.log

  8. 7
    Дмитрий Гайдамович ответил:

    Отладчика для COM нету, есть всякие утилиты, типа oleview, и т.п. – в популярных книжках по COM они перечисляются. COM-объекты "живут" в обычных dll- и exe-серверах, поэтому их отладка ничем не отличается от отладки обычных программ. Но не думаю, что отладчик здесь поможет. Разве что у Вас есть исходники Word:)) Нужно разбираться, что там за ошибка при старте Word. Он вообще-то запускается, сам по себе?

  9. 6
    Алексей Вишняков ответил:

    А есть какой-нибуть отладчик для COM? что бы можно было видеть что там происходит.
    С какого-то перепугу скрипт стал выдавать ошибку: Failed to create COM object `word.application': Server execution failed

  10. 5
    Алексей Вишняков ответил:

    Ок. Спасибо!!!=))

  11. 4
    Дмитрий Гайдамович ответил:

    Document.VBProject

  12. 3
    Алексей Вишняков ответил:

    А можно поподробнее про второй пункт. Как это на VBA можно сделать?

  13. 2
    Дмитрий Гайдамович ответил:

    1. В настройках безопасности Word выставляется высокий уровень.
    2. Если в настройках безопасности разрешён доступ к VB Project – то делается тоже несложно.
    3. Как в php – не знаю, честно говоря, но в самом COM-е наряду с функцией создания объекта имеется функция подключения к уже запущенному объекту. Обычно её выводят в скрипты. Например, в VB (VBA) имеются CreateObject и GetObject для этих двух видов получения ссылки на объект. Вариант N 2 – создавать не Word.Application, а другой, например, Word.Document, и, к примеру, уже в него вставлять из файла. В последнем случае Word также не будет запущен повторно.

  14. 1
    Алексей Вишняков ответил:

    Еще желательно что бы при открытии ворд не делал запрос на проверку на вирусы. Для ускорения открытия файла.

Клуб программистов работает уже ой-ой-ой сколько, а если поточнее, то с 2007 года.