Вызов метода из 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. Я перечислил подробные шаги, которые я предпринял ниже...
Добавьте папку с именем php в папку bin веб-роли
Начиная с 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
Создайте файл 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 веб-роли).Скопируйте и вставьте COM-компонент вне процесса (файл OleAutomationFeasibilityModel.exe) в папку bin.
Создайте файл RegisterOleAutomationFeasibilityModel.cmd в папке bin, чтобы зарегистрировать компонент COM и установить необходимые разрешения для его запуска...
chcp 1252>NUL OleAutomationFeasibilityModel.exe /regserver regedit.exe /s SetDCOMPermission.reg exit /b 0
В файле ServiceDefinition.csdef вставьте ссылку на файл.cmd непосредственно перед закрывающим тегом запуска...
<Task commandLine="RegisterOleAutomationFeasibilityModel.cmd" executionContext="elevated" />
Опубликовать веб-роль
Надеюсь, это поможет кому-то в подобной ситуации!