使用Azure上的PHP从进程外COM组件调用方法

时间:2013-08-27 19:29:23

标签: php azure com out-of-process

我编写了一个简单的PHP脚本,它为进程外(即exe文件)COM组件实例化一个COM对象,并使用它来调用组件公开的COM方法。这个COM方法非常简单地将作为第一个参数传递的数字增加四倍,将结果返回到第二个参数(通过引用传递)。下面显示的脚本在WampServer 2.0(Apache 2.2.11 / PHP 5.3.1)上的本地开发计算机上成功运行。 COM组件是使用Delphi构建的Win32可执行文件。

<?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>';   
?>

注意:根据我的理解,人们只能通过引用使用VARIANT类型的COM方法传递参数,因为像整数和字符串这样的常见数据类型将不起作用(参见http://www.php.net/manual/en/ref.com.php#45038

然后,我创建并部署了一个Azure Web角色(Cloud Service),其中包含一个成功注册COM组件的启动脚本,即注册表中出现了相应的注册表项。为了进一步确认COM组件可以与之交互,我使用RDP连接到云服务实例并安装了Microsoft Access Runtime 2010,因为我有一个Access应用程序,它提供了一个GUI来测试COM组件的方法。我能够运行此应用程序并成功地与COM组件交互,使用它将整数传递给CalculateWithVariants方法,并返回预期的四倍结果。因此,我已经确定已安装COM组件,并且可以在Azure云服务实例上进行交互。

接下来,我在Web角色中包含了上述PHP脚本,并将其部署在Azure上。不幸的是,从浏览器调用脚本会导致HTTP错误500(内部服务器错误),我正在努力找出原因。如果我注释掉引用$oleapp的所有行,我仍会得到相同的错误。如果我另外注释掉实例化变体对象的行,则不会发生错误。如果我恢复实例化COM对象及其下面的行的行,则不会收到任何错误消息,但回显的唯一文本来自COM对象创建行之前的行,即对Version方法的调用失败。所以它似乎正在努力与变体对象创建和COM对象创建。

我对如何解决这个问题感到有些困惑。因此,如果有人对前进的方向有任何指示,我将非常感激。

更新1

我决定通过...尝试在Azure平台上采取不同的行动方案。

  • 使用Windows Server 2008 R2操作系统创建Azure Virtual Machine
  • 安装WampServer 2.2E(Apache 2.2.22 / PHP 5.3.13 / MySQL 5.5.24)在VM中作为一种快速简便的方法来测试这种方法是否有效
  • 将上述PHP脚本复制到WampServer“www目录”
  • 启动WampServer
  • 从WampServer菜单中选择“Put Online”选项(通过左键单击Windows任务栏通知区域中的WampServer图标进行访问)
  • 为VM防火墙创建“入站规则”以允许连接到端口80

...谢天谢地,脚本成功运行了!

理想情况下,我仍然希望将其作为Azure云服务运行,因为我不需要在完整的VM中维护PHP安装。

更新2

我尝试重新启动云服务,然后远程连接到云服务实例并查看应用程序事件查看器。我看到WMI在启动期间记录了1个错误:

Event filter with query "SELECT * FROM __InstanceModificationEvent WITHIN 60 
WHERE TargetInstance ISA "Win32_Processor" AND TargetInstance.LoadPercentage > 99" 
could not be reactivated in namespace "//./root/CIMV2" because of error 0x80041003 
Events cannot be delivered through this filter until the problem is corrected.

然后我运行了上述脚本几次并重新检查了应用程序事件查看器,但没有记录任何内容。

我还检查了IIS日志和Azure logstartup-tasks-logstartup-tasks-error-log文件无效。

1 个答案:

答案 0 :(得分:0)

去年放弃解决这个问题。我本周再次齐心协力解决问题,并取得了成功!

我基本上需要(a)启用 php_com_dotnet.dll 以允许使用COMVARIANT类,以及(b)授予IIS_IUSRS的默认本地激活权限,以允许访问COM组件。我已经列出了我在下面采取的详细步骤......

  1. 在网络角色的 bin 文件夹中添加名为 php 的文件夹

    < / LI>
  2. 自PHP 5.3.15 / 5.4.5起,为了使用COMVARIANT 类, 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. bin 文件夹中创建 SetDCOMPermission.reg 文件,其中包含以下内容:授予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
    

    我不知道上述注册表更改是否适用于所有人,因此我使用的流程记录为 here (它主要涉及使用名为 RegFromApp 的程序,用于记录在COM安全性中为IIS_IUSRS授予默认本地激活权限并保存注册表更改时对注册表所做的更改作为.reg文件进入Web角色的 bin 文件夹。)

  4. 将进程外COM组件( OleAutomationFeasibilityModel.exe 文件)复制并粘贴到 bin 文件夹

  5. bin 文件夹中创建 RegisterOleAutomationFeasibilityModel.cmd 文件以注册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. 发布网络角色

  8. 希望帮助处于类似情况的人!