php的COM组件调用相关(包括com_event_sink的用法)

参见:http://www.phpnotes.top/2017/12/06/php/111/

前提

需要手动在php.ini中开启

[COM_DOT_NET]
extension=php_com_dotnet.dll


COM配置项

COM 配置选项
名字 默认 可修改范围 更新日志
com.allow_dcom "0" PHP_INI_SYSTEM 自 PHP 4.0.5 起可用
com.autoregister_typelib "0" PHP_INI_ALL 在 PHP 4 中是 PHP_INI_SYSTEM。自 PHP 4.1.0 起可用
com.autoregister_verbose "0" PHP_INI_ALL 在 PHP 4 中是 PHP_INI_SYSTEM。自 PHP 4.1.0 起可用
com.autoregister_casesensitive "1" PHP_INI_ALL 在 PHP 4 中是 PHP_INI_SYSTEM。自 PHP 4.1.0 起可用
com.code_page "" PHP_INI_ALL 自 PHP 5.0.0 起可用
com.typelib_file "" PHP_INI_SYSTEM 自 PHP 4.0.5 起可用

com.allow_dcom

如果打开此选项,PHP 将被允许以一个 D-COM(Distributed COM)客户方式操作并允许 PHP 脚本在远程服务器上实例化 COM 对象

com.autoregister_typelib

当打开这个时,PHP将尝试从它实例化的对象类型库中注册常量,如果这些对象实现了获取该信息所需的接口。它所注册的常量的情况敏感性由配置指令控制

com.autoregister_verbose

当打开这个程序时,在对象实例化过程中加载类型库的任何问题都将使用PHP错误机制来报告。缺省值是off,如果出现错误查找或加载类型库,则不会发出任何指示

com.autoregister_casesensitive

当打开这个(默认值)时,在自动加载的类型库中发现的常量将会大小写敏感地注册,点击com_load_typelib()查看更多的细节

com.code_page

 

它控制在从COM对象传递字符串时使用的默认字符集代码页。如果设置为空字符串,PHP将假定您想要CP_ACP,它是默认系统ANSI代码页。

如果脚本中的文本使用默认设置的不同编码/字符集进行编码,那么设置该指令将使您不必将代码页作为参数传递给COM类构造函数。请注意,通过使用这个指令(和任何PHP配置指令一样),您的PHP脚本变得更不便于携带;您应该尽可能使用COM构造函数参数

com.typelib_file

设置时,该文件应该包含一个文件,该文件包含应该在启动时加载的类型库列表。文件的每一行将被视为类型库名称,并像您调用com_load_typelib()那样加载。常量将持续地注册,以便库只需要加载一次。如果类型库的名称以字符串# cis或#case_insensitive结束,那么该库中的常量将以不区分大小写的方式注册


 

预定义常量

可以通过get_defined_constants(true)查看具体值,

 

 


The COM class

COM类允许实例化一个OLE兼容的COM对象并调用其方法并访问其属性。

$obj = new COM("Application.ID");

COM::__construct ( string $module_name [, mixed $server_name [, int $codepage [, string $typelib ]]] )

COM类构造函数。参数有以下含义

module_name

可以用一个ProgID、类ID或Moniker,当作module_name进行加载组件。ProgID通常是应用程序或DLL名称,然后是一个句点,然后是对象名称。类似:Word.Application。类ID是唯一标识给定类的UUID。Moniker是一种特殊的命名形式,类似于URL scheme的概念,它标识一个资源并指定如何加载它。作为一个示例,您可以加载Word并通过指定Word文档的完整路径作为模块名称来表示Word文档,或者您可以使用LDAP:作为使用ADSI接口到LDAP的名字

server_name

应该加载和运行组件的DCOM服务器的名称。如果该对象为NULL,则使用该应用程序的缺省值运行该对象。默认情况下,通常是在本地机器上运行它,尽管管理员可能已经将应用程序配置为在另一台机器上启动。如果您为服务器指定了一个非空值,PHP将拒绝加载该对象,除非配置选项设置为TRUE。

如果server_name是一个数组,它应该包含以下元素(区分大小写!)请注意它们都是可选的(尽管您需要同时指定用户名和密码);如果忽略了服务器设置,将使用默认服务器(如上所述),并且该对象的实例化不会受到指令的影响

DCOM server name
server_namekey type description
Server string The name of the server.
Username string The username to connect as.
Password string The password for Username.
Flags integer One or more of the following constants, logically OR'd together: CLSCTX_INPROC_SERVER,CLSCTX_INPROC_HANDLERCLSCTX_LOCAL_SERVERCLSCTX_REMOTE_SERVERCLSCTX_SERVER and CLSCTX_ALL. The default value if not specified here is CLSCTX_SERVER if you also omit Server, orCLSCTX_REMOTE_SERVER if you do specify a server. You should consult the Microsoft documentation for CoCreateInstance for more information on the meaning of these constants; you will typically never have to use them.

codepage

指定用于将字符串转换为unicode字符串的代码页,反之亦然。当一个PHP字符串作为一个参数传递或者从这个COM对象的方法返回时,就应用转换。PHP 5中的代码页是粘性的,这意味着它将传播到从对象返回的对象和变量。可能的值是CP_ACP(如果省略此参数,则使用系统默认的ANSI代码页)、CP_MACCP、CP_OEMCP、CP_SYMBOL、CP_THREAD_ACP(使用当前执行线程的codepage /地区设置)、CP_UTF7和CP_UTF8。你也可以使用一个给定代码页的数字;查阅Microsoft文档,了解更多关于代码页和它们的数值的细节

注意:

函数参数问题

很多实例化的COM对象的方法参数,不能直接是字符串,

如果您在遇到类似Error [0x80004002] ..." (with a message nagging you about an unsupported interface),您正在通过COM调用类方法,它期望char作为一个参数,您不应该使用单字符串来调用该方法。

调用这种方法的正确方法是使用带有VT_UI1类型的变体

例如:

$com = new COM('Some.Class.Name');

// This will fail
$var 'a';
$com->DoSomething($var);

// This works correctly
$var = new VARIANT(ord('a'), VT_UI1);
$com->DoSomething($var);

可以参考VARIANT类。

权限问题

如果你有权限问题比如不能打开或保存文档,可能出现这样的错误:

由于没有打开文档,所以无法使用此命令

——命令失败

试试这个(如果你正在运行IIS):

——执行“dcomcnfg”

-打开组件服务>计算机>我的计算机> DCOM配置

-搜索Microsoft Office Word 97- 2003文档(它会像这样翻译成你的语言,所以花点时间搜索一下)

-右键单击并打开属性

——选择“身份”选项卡

-通常情况下设置为“启动用户”。您必须将其更改为“交互式用户”或您选择的管理用户。

-应用这些新设置并测试你的COM应用程序

实例化时的异常捕捉

= new COM('Whatever.Something') or die(); ?>
然而,”或die()“是多余的”,将会抛出一个致命的“com_exception”异常,杀死您的脚本。如果你想处理“or”条件,你需要捕获异常

类似于:

try {
$var = new COM('Whatever.Something');
} catch (
com_exception $e) {
//couldn't load, do something else like register
exec('regsvr32 /s whatever.dll');
}
?>


The DOTNET class

DOTNET类允许您从a实例化一个类。Net组装并调用其方法并访问其属性。

$obj = new DOTNET("assembly", "classname");

构造函数:

DOTNET::__construct ( string $assembly_name , string $class_name [, int $codepage ] )

DOTNET类构造函数。assembly y_name指定应该装载哪个程序集,以及在该程序集中实例化的类的class_name指定。您可以选择指定一个代码页用于unicode字符串转换;有关代码页的更多细节,请参阅COM类。

返回的对象是一个重载对象,这意味着PHP不像常规类那样看到任何固定方法;相反,访问的任何属性或方法都可以通过COM传递到网络。换句话说,就是。Net对象通过COM互操作层映射通过使用 .Net runtime

一旦创建了DOTNET对象,PHP就将其与其他COM对象进行完全相同的处理;所有的规则都适用


VARIANT class

The VARIANT是COM的等价于PHP zval的一种结构,可以包含有一系列不同类型的值。COM扩展提供的VARIANT Class允许您对PHP传递值的方式和来自COM的方式有更多的控制。

$vVar = new VARIANT($var);

构造函数:

VARIANT::__construct ([ mixed $value [, int $type [, int $codepage ]]] )

参数:

value

初始值。如果省略了,或者设置为NULL,则创建一个VT_EMPTY对象。

type

指定变量对象的内容类型。可能的值是VT_XXX预定义常量。在PHP 5之前的PHP版本中,您可以强制PHP通过使用类型的VT_BYREF引用一个变体对象。在PHP 5中,此hack不受支持;相反,PHP 5可以自动检测通过引用传递的参数;它们甚至不需要作为变量对象传递。请咨询MSDN库,以获得关于VARIANT 类型的附加信息。

codepage

指定用于将字符串转换为unicode的代码页。有关更多信息,请参见COM类中的相同名称的参数。

 

在PHP 5之前,PHP版本定义了许多(未归档的)虚拟属性,以实现VARIANT  Class的实例;这些属性都在PHP 5中被删除,以支持其更自然的语法;

改变的原因是,在内部,COM扩展将VARIANT 、COM和DOTNET类视为相同的东西,这些类的设计理念是,所有的属性和成员访问都是通过COM传递的,没有任何干扰。新语法更加自然,工作量也更少,而且大多数删除的虚拟属性在任何情况下都没有任何意义.

PHP 5采用了一种更简单的方法来处理变量;当返回一个值或获取一个变量属性时,只在不导致信息丢失的类型之间进行直接映射时,才将变量转换为PHP值。在所有其他情况下,结果返回为变量类的实例。您可以强制PHP通过显式地使用浇注操作符来转换或评估其变体,或者通过打印将其隐式转换为字符串。您可以使用各种不同的函数来执行变量的算术运算,而不需要强制转换或冒丢失数据的风险。

注意

如果您对print_r($ obj)($ obj是从一个COM对象的函数调用返回的东西)不返回任何有用的东西,并且该变量的variant_get_type($ obj)返回一个数字,那么您实际上在后面的函数是:

com_print_typeinfo($ obj);

它列出了可读格式的所有函数、变量和类型。

 

一些VBA函数具有可选参数(例如word)。有时你想要传递的参数不是连续的。

例如:

GoTo What:=wdGoToBookmark, Name="BookMarkName"
GoTo(wdGoToBookmark,,,"BookMarkName)

在php中,这些空白地方应该设为空,


COM 函数

参见

有关COM的进一步信息,请阅读COM规范。你可能会发现一些额外的有用的信息在我们的常见问题为PHP和COM。如果您想在服务器端使用MS Office应用程序,那么您应该阅读这里的信息:»对Office服务器自动化的考虑。

  • com_create_guid — 生成一个全局唯一标识符(GUID)
  • com_event_sink — 将事件从COM对象连接到PHP对象
  • com_get_active_object — 返回一个已经运行的COM对象的实例句柄
  • com_load_typelib — 装载一个 Typelib
  • com_message_pump — 处理COM消息,睡眠时间超过毫秒
  • com_print_typeinfo — 为dispatchable接口打印一个PHP类定义
  • variant_abs — 返回变量的绝对值
  • variant_add — 将两个变量值加在一起并返回结果
  • variant_and — 在两个变量之间执行一个位and操作
  • variant_cast — 将一个变量转换为另一个类型的新变量对象
  • variant_cat — 将两个变量值连接在一起并返回结果
  • variant_cmp — 比较两个变量
  • variant_date_from_timestamp — 返回一个Unix时间戳的变量日期表示
  • variant_date_to_timestamp — 将一个变量日期/时间值转换为Unix时间戳
  • variant_div — 返回划分两个变量的结果
  • variant_eqv — 在两个变量上执行一个位等价
  • variant_fix — 返回变量的整数部分
  • variant_get_type — 返回变量对象的类型
  • variant_idiv — 将变量转换成整数,然后通过将其分隔返回结果
  • variant_imp — 对两个变量执行一个位暗示
  • variant_int — 返回变量的整数部分
  • variant_mod — 划分两个变量并只返回剩余部分
  • variant_mul — 将这两个变量的值相乘
  • variant_neg — 对变量执行逻辑上的否定
  • variant_not — 对变量执行不否定
  • variant_or — 在两个变量上执行逻辑or
  • variant_pow — 返回使用两个变量执行功能函数的结果
  • variant_round — 将一个变量转到指定的小数位数
  • variant_set_type — 将一种变量转换为另一种类型的“in-place”
  • variant_set — 为变量对象分配一个新值
  • variant_sub — 从左变值减去右变量的值
  • variant_xor — 对两个变量执行逻辑亦或

com_event_sink

bool com_event_sink ( variant $comobject , object $sinkobject [, mixed $sinkinterface ] )

指示COM将comobject生成的事件放入PHP对象sinkobject中。

comobjectsinkobject

实例化的COM对象

sinkobject

应该是一个类的实例,其方法是以期望的不接口的方式命名的;您可以使用com_print_typeinfo()来帮助为这个目的生成一个模板类。

sinkinterface

PHP将尝试使用与comobject相关联的typelibrary指定的默认的消息接口类型,但是您可以通过将sinkinterface设置为您想要使用的接口的名称来覆盖这个选择

成功时返回 TRUE, 或者在失败时返回 FALSE

例如:

ComTestSinkClass类中的方法名和事件中的方法名应一致,在事件被调用的时候出发方法时,php中可以获取,并进行相应的操作。

//将打印的文字进行排版
function pr() {
$args = func_get_args();
if (!empty($args)) {
echo '

';
foreach ($args as $arr) {
print_r($arr);
echo '
';
}
echo '
';
}
}

class ComTestSinkClass {

var $flag = false;

public function eventMsg($a) {
pr($a);
}

public function quit(){
$this->flag = true;
}

}

try {
$MyCom = new COM('MyCom.MyClass');
$sink = new ComTestSinkClass();
com_event_sink($MyCom, $sink, 'MyCom.MyClassEvent');
while (!$sink->flag) {
com_message_pump(2000);
}
} catch (Exception $e) {
pr($e);
}

?>

 

 

 

 

 

 

你可能感兴趣的:(php,php,com组件)