0

我编写了一个简单的 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/ zh/ref.com.php#45038)。

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

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

我对如何解决这个问题有点困惑。因此,如果有人对前进的道路有任何指示,我将不胜感激。

更新 1

我决定在 Azure 平台上尝试不同的行动方案...

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

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

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

更新 2

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

带有查询“SELECT * FROM __InstanceModificationEvent WITHIN 60”的事件过滤器
在哪里 TargetInstance ISA“Win32_Processor”和 TargetInstance.LoadPercentage > 99“
由于错误 0x80041003,无法在命名空间“//./root/CIMV2”中重新激活
在问题得到纠正之前,无法通过此过滤器传递事件。

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

我还检查了 IIS 日志和Azurelog和文件,但无济于事。startup-tasks-logstartup-tasks-error-log

4

1 回答 1

0

在去年放弃解决这个问题之后。本周我再次齐心协力解决它并成功了!

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

  1. 在 web 角色的bin文件夹中添加一个名为php的文件夹

  2. 从 PHP 5.3.15 / 5.4.5 开始,为了使用COMVARIANT 类,需要在 php.ini中启用php_com_dotnet.dll。以前的 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
    

    我不知道上面的注册表更改是否适用于所有人,所以我使用的过程记录在这里(它本质上涉及使用一个名为RegFromAppIIS_IUSRS的程序来记录在 COM 安全中授予默认本地激活权限时对注册表所做的更改并将注册表更改作为 .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文件中,在关闭 Startup 标记之前插入对 .cmd 文件的引用...

    <Task commandLine="RegisterOleAutomationFeasibilityModel.cmd" executionContext="elevated" />
    
  7. 发布 Web 角色

希望对遇到类似情况的人有所帮助!

于 2014-02-02T21:56:46.877 回答