Вызов метода из COM-компонента вне процесса с использованием PHP на Azure

Я написал простой PHP-скрипт, который создает экземпляр COM-объекта для COM-компонента вне процесса (т.е. exe-файла) и использует его для вызова COM-метода, предоставляемого компонентом. Этот метод COM очень просто в четыре раза превышает число, переданное в качестве первого аргумента, возвращая результат во втором аргументе (переданном по ссылке). Сценарий, показанный ниже, успешно работает на моей локальной машине для разработки на WampServer 2.0 (Apache 2.2.11 / PHP 5.3.1). COM-компонент - это исполняемый файл Win32, созданный с использованием Delphi.

<?php
  // ensure no time limit is imposed
  set_time_limit(0);
  // show all errors, warnings and notices whilst developing
  error_reporting(E_ALL);

  $numIn = 3;
  $numOut = new VARIANT(1, VT_I4);
  echo '----- BEFORE ---------' . '<br>';
  echo 'NumIn: ' . $numIn . '<br>';
  echo 'NumOut: ' . $numOut . '<br>';   
  echo '----------------------' . '<br>';

  $oleapp = new COM("OleAutomationFeasibilityModel.Automation") or die ("Could not initialise feasibility model object.");
  echo '<br />COM object created version = ' . $oleapp->Version . '<br /><br />';
  $oleapp->CalculateWithVariants($numIn, $numOut);
  unset($oleapp);

  echo '----- AFTER ---------' . '<br>';
  echo 'NumIn: ' . $numIn . '<br>';
  echo 'NumOut: ' . $numOut . '<br>';   
  echo '----------------------' . '<br>';   
?>

Примечание: насколько я понимаю, параметр можно передать только по ссылке на метод COM с использованием типа VARIANT, так как общие типы данных, такие как целые числа и строки, не будут работать (см. http://www.php.net/manual/en/ref.com.php).

Затем я создал и развернул веб-роль Azure ( облачная служба) со сценарием запуска, который успешно регистрирует компонент COM, т.е. в реестре появились соответствующие ключи реестра. Чтобы дополнительно подтвердить возможность взаимодействия с компонентом COM, я использовал RDP для подключения к экземпляру облачной службы и установил Microsoft Access Runtime 2010, поскольку у меня есть приложение Access, которое предоставляет графический интерфейс для тестирования методов компонента COM. Я смог запустить это приложение и успешно взаимодействовал с компонентом COM, используя его для передачи целого числа в CalculateWithVariants метод и ожидаемый четырехкратный результат был возвращен. Итак, я установил, что компонент COM установлен и может взаимодействовать с экземпляром облачной службы Azure.

Затем я включил указанный выше PHP-скрипт в веб-роль и развернул его в Azure. К сожалению, вызов скрипта из браузера приводит к ошибке HTTP 500 (Internal Server Error), и я пытаюсь выяснить, почему. Если я закомментирую все строки ссылки $oleappЯ все еще получаю ту же ошибку. Если я дополнительно закомментирую строку, которая создает экземпляр варианта объекта, ошибки не возникает. Если я восстанавливаю строку, которая создает экземпляр COM-объекта, и строку под ним, я не получаю сообщения об ошибке, но выводится только текст из строк, предшествующих строке создания COM-объекта, т.е. при вызове Version метод не удался. Похоже, что он борется с созданием варианта объекта и созданием объекта COM.

Я немного застрял в том, как решить эту проблему. Поэтому я был бы очень признателен, если бы у кого-нибудь были какие-либо указания относительно дальнейших действий.

ОБНОВЛЕНИЕ 1

Я решил попробовать другой курс действий на платформе Azure, выполнив...

  • создание виртуальной машины Azure с ОС Windows Server 2008 R2
  • установка WampServer 2.2E (Apache 2.2.22 / PHP 5.3.13 / MySQL 5.5.24) на виртуальную машину как быстрый и простой способ проверить, будет ли работать этот подход
  • копирование вышеуказанного PHP-скрипта в WampServer "www каталог"
  • запуск WampServer
  • выбрав опцию "Подключить к сети" из меню WampServer (доступ к которому можно получить, щелкнув левой кнопкой мыши значок WampServer в области уведомлений панели задач Windows)
  • создание "правила входящего трафика" для брандмауэра виртуальных машин, чтобы разрешить подключения к порту 80

... и, к счастью, сценарий успешно запущен!

В идеале я бы хотел, чтобы это работало как облачная служба Azure, поскольку мне не нужно поддерживать установку PHP в полной виртуальной машине.

ОБНОВЛЕНИЕ 2

Я попытался перезапустить облачную службу, затем удаленно подключиться к экземпляру облачной службы и посмотреть в Application Event Viewer. Я увидел, что во время запуска WMI вошла 1 ошибка:

Фильтр событий с запросом "SELECT * FROM __InstanceModificationEvent WITHIN 60 
ГДЕ TargetInstance ISA "Win32_Processor" И TargetInstance.LoadPercentage > 99" 
не удалось повторно активировать в пространстве имен "//./root/CIMV2" из-за ошибки 0x80041003 
События не могут быть доставлены через этот фильтр, пока проблема не будет устранена.

Затем я несколько раз запустил вышеуказанный скрипт и перепроверил Application Event Viewer, но ничего не было зарегистрировано.

Я также проверил журналы IIS и Azure log, startup-tasks-log а также startup-tasks-error-log файлы безрезультатно.

1 ответ

Решение

После отказа от решения этого в прошлом году. Я предпринял еще одно согласованное усилие, чтобы решить эту проблему на этой неделе, и мне это удалось!

Мне в основном нужно (а) включить php_com_dotnet.dll, чтобы разрешить использование COM а также VARIANT классы, и (б) предоставить разрешение локальной активации по умолчанию для IIS_IUSRS разрешить доступ к компоненту COM. Я перечислил подробные шаги, которые я предпринял ниже...

  1. Добавьте папку с именем php в папку bin веб-роли

  2. Начиная с PHP 5.3.15 / 5.4.5, чтобы использовать COM а также VARIANT классы, php_com_dotnet.dll должен быть включен внутри php.ini. Предыдущие версии PHP включали эти расширения по умолчанию (источник: http://www.php.net/manual/en/com.installation.php). В папке php создайте файл php.ini, содержащий только следующие строки...

    [COM_DOT_NET] 
    extension=php_com_dotnet.dll
    
  3. Создайте файл SetDCOMPermission.reg в папке bin, содержащей следующее содержимое, чтобы предоставить по умолчанию разрешение локальной активации для IIS_IUSRS...

    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\OLE]
    "DefaultLaunchPermission"=hex(3):01,00,04,80,74,00,00,00,84,00,00,00,00,00,\
    00,00,14,00,00,00,02,00,60,00,04,00,00,00,00,00,14,00,1F,00,00,00,01,01,00,\
    00,00,00,00,05,12,00,00,00,00,00,18,00,1F,00,00,00,01,02,00,00,00,00,00,05,\
    20,00,00,00,20,02,00,00,00,00,18,00,0B,00,00,00,01,02,00,00,00,00,00,05,20,\
    00,00,00,38,02,00,00,00,00,14,00,1F,00,00,00,01,01,00,00,00,00,00,05,04,00,\
    00,00,01,02,00,00,00,00,00,05,20,00,00,00,20,02,00,00,01,02,00,00,00,00,00,\
    05,20,00,00,00,20,02,00,00
    

    Я не знаю, будет ли указанное выше изменение реестра работать для всех, поэтому процесс, который я использовал, задокументирован здесь (он, по сути, включал использование программы под названием RegFromApp для записи изменений, внесенных в реестр при предоставлении разрешений локальной активации по умолчанию для IIS_IUSRS в COM Security и сохранить изменения реестра в виде файла.reg в папку bin веб-роли).

  4. Скопируйте и вставьте COM-компонент вне процесса (файл OleAutomationFeasibilityModel.exe) в папку bin.

  5. Создайте файл RegisterOleAutomationFeasibilityModel.cmd в папке bin, чтобы зарегистрировать компонент COM и установить необходимые разрешения для его запуска...

    chcp 1252>NUL
    OleAutomationFeasibilityModel.exe /regserver
    regedit.exe /s SetDCOMPermission.reg
    exit /b 0
    
  6. В файле ServiceDefinition.csdef вставьте ссылку на файл.cmd непосредственно перед закрывающим тегом запуска...

    <Task commandLine="RegisterOleAutomationFeasibilityModel.cmd" executionContext="elevated" />
    
  7. Опубликовать веб-роль

Надеюсь, это поможет кому-то в подобной ситуации!

Другие вопросы по тегам