2024年PHP开发者大会日本站

com 类

(PHP 4 >= 4.1.0, PHP 5, PHP 7, PHP 8)

简介

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

类概要

class com extends variant {
/* 方法 */
public __construct(
    string $module_name,
    array|string|null $server_name = null,
    int $codepage = CP_ACP,
    string $typelib = ""
)
}

重载方法

返回的对象是一个重载对象,这意味着PHP不像处理常规类那样看到任何固定方法;相反,任何属性或方法访问都将传递给COM。

PHP将自动检测接受按引用传递的参数的方法,并将自动将常规PHP变量转换为可以按引用传递的形式。这意味着你可以非常自然地调用该方法;你的代码不需要做任何额外的努力。

com 示例

示例 #1 com 示例 (1)

<?php
// 启动Word
$word = new com("word.application") or die("无法实例化Word");
echo
"加载Word,版本 "{$word->Version}"\n";

// 放在最前面
$word->Visible = 1;

// 打开一个空文档
$word->Documents->Add();

// 做一些奇怪的事情
$word->Selection->TypeText("This is a test...");
$word->Documents[1]->SaveAs("Useless test.doc");

// 关闭Word
$word->Quit();

// 释放对象
$word = null;
?>

示例 #2 com 示例 (2)

<?php

$conn
= new com("ADODB.Connection") or die("无法启动ADO");
$conn->Open("Provider=SQLOLEDB; Data Source=localhost;
Initial Catalog=database; User ID=user; Password=password"
);

$rs = $conn->Execute("SELECT * FROM sometable"); // 记录集

$num_columns = $rs->Fields->Count();
echo
$num_columns . "\n";

for (
$i=0; $i < $num_columns; $i++) {
$fld[$i] = $rs->Fields($i);
}

$rowcount = 0;
while (!
$rs->EOF) {
for (
$i=0; $i < $num_columns; $i++) {
echo
$fld[$i]->value . "\t";
}
echo
"\n";
$rowcount++; // 增加行数
$rs->MoveNext();
}

$rs->Close();
$conn->Close();

$rs = null;
$conn = null;

?>

目录

添加备注

用户贡献备注 36条备注

tsintra at humansoft dot pt
15年前
尝试了一周理解我的PHP与MS Word通信的问题后,我终于让它工作了……
如果运行的是IIS,则COM对象似乎是以受限权限调用的。
如果你遇到权限问题,例如无法打开或保存文档,并且收到以下错误:

- 此命令不可用,因为没有打开文档

- 命令失败

请尝试以下操作(如果运行的是IIS):

- 执行“dcomcnfg”
- 打开组件服务 > 计算机 > 我的电脑 > DCOM 配置
- 搜索Microsoft Office Word 97-2003文档(它将类似于翻译成你的语言的名称,所以花点时间搜索它)
- 右键单击它并打开属性
- 选择“标识”选项卡
- 通常情况下,这设置为“启动用户”。你必须将其更改为“交互式用户”或你选择的管理员用户。
- 应用这些新设置并测试你的COM应用程序。现在应该可以正常工作了。

我希望我能为你们中的某些人节省大量的时间和头痛 :)
info at ensostudio dot ru
4年前
使用WScript.Shell的完整示例
<?php
/**
* 方法和属性
* @link https://msdn.microsoft.com/en-us/library/2f38xsxe(v=vs.84).aspx
*/
$shell = new com('WScript.Shell', null, CP_UTF8);
var_dump($shell->CurrentDirectory);
foreach (
$shell->Environment as $value) {
var_dump($value);
}
// 检查文件 'Test.php'
$process = $shell->Exec('.../php.exe --syntax-check --file=".../src/Test.php"');
// 等待完成: 1 - 完成
while (! $process->Status) {
usleep(5000);
}
// 结果: -1 - 语法错误, 0 - 无错误
var_dump($process->ExitCode);
// 显示响应
var_dump($process->StdOut->ReadAll());
// 显示错误
var_dump($process->StdErr->ReadAll());
?>
rogier
13年前
我花了一段时间才通过反复试验解决了这个问题

如果您在遇到类似“Error [0x80004002]...”的COM异常时感到沮丧(以及一条关于不支持接口的烦人消息),并且您正在通过COM调用一个期望字符作为参数的类方法,那么您不应该使用单字符字符串调用该方法。

正确调用此类方法的方法是使用类型为VT_UI1的VARIANT。

COM启用方法定义

public bool DoSomething(char arg);

<?php

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

// 这将失败
$var = 'a';
$com->DoSomething($var);

// 这将正确运行
$var = new VARIANT(ord('a'), VT_UI1);
$com->DoSomething($var);

?>

我希望这对一些人有所帮助
yinon at xacct dot com
22年前
为了使Word示例运行,请在服务器端执行以下操作。
对我有用……
1. 点击开始-->运行,然后输入“dcomcnfg”
2. 在“应用程序”选项卡中,向下找到“Microsoft Word 文档”
3. 点击“属性”按钮
4. 转到“安全”选项卡
5. 点击“使用自定义访问权限”,然后点击“编辑”
6. 点击“添加”,然后点击“显示用户”
7. 突出显示IIS匿名用户帐户(通常是IUSR_<machinename>),点击“添加”
8. 点击“确定”返回“安全”选项卡
9. 点击“使用自定义启动权限”,然后点击“编辑”
10. 点击“添加”,然后点击“显示用户”
11. 突出显示IIS匿名用户帐户(通常是IUSR_<machinename>),点击“添加”
12. 点击“确定”,然后点击“应用”。

此外,您应该查看Microsoft Word文档“属性”中的“标识”选项卡,并确保它设置为“交互式用户”。


另外,以IUSR_<machinename>帐户登录到计算机,启动Word,并确保点击Word首次为特定用户运行时显示的对话框。换句话说,确保Word可以为IUSR_用户干净地打开。

更多有用的信息可以在这里找到
http://www.email-screen.com/support-doc2txt.html
mbirth at webwriters dot de
16年前
使用来自http://freenet-homepage.de/gborn/WSHBazaar/WSHDynaCall.htm的DynamicWrapper,并在通过“regsvr32 dynwrap.dll”注册后,您可以轻松设置输出颜色,即使在Windows上也能创建彩色的CLI脚本。

<?php

$dw
= new COM('DynamicWrapper'); // 需要dynwrap.dll (regsvr32 dynwrap.dll)

// 注册所需功能
$dw->Register('kernel32.dll', 'GetStdHandle', 'i=h', 'f=s', 'r=l');
$dw->Register('kernel32.dll', 'SetConsoleTextAttribute', 'i=hl', 'f=s', 'r=t');
$dw->Register('kernel32.dll', 'SetConsoleTitle', 'i=s', 'f=s', 'r=l');

// 获取控制台句柄
$ch = self::$dw->GetStdHandle(-11); // -11 = STD_OUTPUT_HANDLE

?>

完成这些初始化步骤后,您可以使用以下方法设置控制台输出颜色

<?php
$dw
->SetConsoleTextAttribute($ch, 14);
echo
'这是黄色文本!';
$dw->SetConsoleTextAttribute($ch, 7);
echo
'恢复为正常的灰色!';
?>

使用SetConsoleTitle,您甚至可以设置在控制台窗口中显示的标题。

颜色值为0..7表示暗色,8..15表示亮色。顺序为(黑色/银色,蓝色,绿色,青色,红色,品红色,黄色/棕色,白色/灰色)。我还发现,如果将16384添加到值中,它应该是反向的。添加32768应该得到下划线文本。但后两者对我来说不起作用。
mastrboy.servebeer.com
16年前
快速的WMI查询示例

<?php
$obj
= new COM ( 'winmgmts://127.0.0.1/root/CIMV2' );
$wmi_computersystem = $obj->ExecQuery("Select * from Win32_ComputerSystem");
$wmi_bios = $obj->ExecQuery("Select * from Win32_BIOS");
foreach (
$wmi_computersystem as $wmi_call )
{
$model = $wmi_call->Model;
}

foreach (
$wmi_bios as $wmi_call )
{
$serial = $wmi_call->SerialNumber;
$bios_version = $wmi_call->SMBIOSBIOSVersion;
}
echo
"BIOS版本: $bios_version\n".
"序列号: $serial\n".
"硬件型号: $model\n";
?>
halfer
17年前
感谢paul at completewebservices之前添加的注释;我已经使用他的代码解决了Crystal 9运行时组件的一个特别棘手的问题。出于某种原因,VBA/VBS可以将本机Date类型作为参数传递给需要日期的Crystal Report,但在PHP中,我已经尝试了各种各样的字符串、unix时间戳、COM变体日期等,所有这些都导致了com_exception。

我的解决方案是使用VBScript来借用CDate函数,该函数可以正常工作。这不是最优雅的解决方案,但这种参数化方法比搜索和替换RecordSelectionFormula字符串更好。当然,如果这里有人有更好的方法,请在这里发布——我相信它会很有用。

<?php
// $rptParam是一个报表参数对象,其类型为日期
$oScript = new COM("MSScriptControl.ScriptControl");
$oScript->Language = "VBScript";
$oScript->AllowUI = false;
$oScript->AddObject('rptParam', $rptParam, true);
$oScript->AddCode('Function SetDateParameter(strDate)
rptParam.AddCurrentValue(CDate(strDate))
End Function'
);
$oScript->Run("SetDateParameter", "25 April 2006");
?>
z3n at overflow dot biz
15年前
在使用ADODB.Connection对象的查询回复中,我所有的`$rs->Fields['field_name']->Value`在插入数组时都返回`variable Object`,如下所示

<?php
for ($rl[$v]=array(),_qm($_query);!$res->EOF;$res->MoveNext()) {
$rl[$v][]=$res->Fields['x']->Value;
}
?>

我发现将值转换为 INT 解决了这个问题。

<?php $rl[$v][]=intval($res->Fields['x']->Value); ?>
james dot m dot love at gmail dot com
15年前
如果您使用 COM 创建与 MS Access 2007 数据库的无 DSN 连接,您会通过 Google 搜索发现您需要使用更新版本的 Jet,因此我找到的连接字符串如下所示

<?php
$databaselocation
= "C:\Path\to\db.accdb";
$conn = new COM('ADODB.Connection') or exit('无法启动 ADO.');
$conn->Open("Provider=Microsoft.ACE.OLEDB.12.0; Data Source=$databaselocation") or die('无法使用 Jet 启动');
?>

但是,在我的设置(WinVista、Access 2007、PHP526)中,我发现它总是以“无法使用 Jet 启动”而“终止”,即使连接成功($conn->State 显示“1”)。

我想直接去掉 $conn->Open() 中的 die() 命令。如果 ADO 连接出现灾难性问题,它自己的错误处理引擎会将堆栈跟踪等信息传递回控制台/标准输出。

因此,我的 Open() 命令如下所示

<?php
$conn
->Open("Provider=Microsoft.ACE.OLEDB.12.0; Data Source=$databaselocation");
?>
csaba at alum dot mit dot edu
19 年前
将 IE 置于前台
如果您在 Win32 平台(例如 XP Pro,SP2)上使用命令行 (CLI) 版本的 PHP,当弹出窗口不足时(参见我之前的帖子,如下所示),您可能希望将输出定向到 IE(也许您想在那里处理输出)。

使用 `$ie = new COM("InternetExplorer.Application");` 获取 IE 实例很容易。问题是,您不一定能看到它在前台(特别是如果您已经打开了一个实例),谁想浪费按键来找到它呢?下面的代码对我有用(如果您想进行其他调整(例如 `$ie->Document->ParentWindow->resizeTo(800,500);` 或 `$ie->Document->Body->bgColor = "yellow";`),在 `$ie->Visible = true;` 行之前进行调整将避免屏幕干扰)

<?php
function newIEtoForeground($title, $evtPrefix="") {
// 将 IE 的新实例置于前台,标题为 $title
if (!$extPrefix) $ie = new COM("InternetExplorer.Application");
else
$ie = new COM("InternetExplorer.Application", $evtPrefix);
$ie->Navigate2("about:blank");
$oWSH = new COM("WScript.Shell");
while (
$ie->ReadyState!=4) usleep(10000);

$ie->Document->Title = ($tmpTitle = mt_rand()); // 唯一标题
$ie->Visible = true;
while (!
$oWSH->AppActivate("$tmpTitle - M")) usleep(10000);

$ie->Document->Title = $title;
$ie->Document->ParentWindow->opener="me"; // 允许 self.close()
return $ie;
}
?>

来自维也纳的 Csaba Gabor
rickardsjoquist at hotmail dot com
21 年前
如果您想对数据库(例如 Access)使用无 DSN 连接,并将查询结果作为具有字段名作为标识符的多维数组返回,请尝试此方法。希望它能帮助到某些人 :-)
--------------------------------------------------------

<?php
function db($sql) {
$c = new COM("ADODB.Connection");
$c->open('DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=' . realpath("relative_path/db.mdb"));
$r = $c->execute($sql);
$i = 0;
$num_fields = $r->fields->count();
while (!
$r->EOF)
{
for(
$j = 0;$j<$num_fields;$j++) {
$key = $r->Fields($j);
$r_items[$i][$key->name] = $key->value;
}
$i++;
$r->MoveNext();
}
$r->close();
$c->close();
$r = null;
$c = null;
return
$r_items;
}
?>

--------------------------------------------------------
使用方法如下
--------------------------------------------------------
<?php
$results
= db("SELECT field_a, field_b FROM table");
foreach(
$result as $i => $item) {
echo
$item['field_a'];
echo
$item['field_b'];
}
?>
--------------------------------------------------------
如果您想打印数组的结构,也可以使用:`print_r($result);`。
sparrowstail at googlemail dot com
14 年前
此脚本报告所有 Windows 磁盘、磁盘类型、状态(如果不可用)、可用空间和总磁盘大小。

<?php

$fso
= new COM('Scripting.FileSystemObject');
$D = $fso->Drives;
$type = array("Unknown","Removable","Fixed","Network","CD-ROM","RAM Disk");
foreach(
$D as $d ){
$dO = $fso->GetDrive($d);
$s = "";
if(
$dO->DriveType == 3){
$n = $dO->Sharename;
}else if(
$dO->IsReady){
$n = $dO->VolumeName;
$s = file_size($dO->FreeSpace) . " free of: " . file_size($dO->TotalSize);
}else{
$n = "[驱动器未准备好]";
}
echo
"驱动器 " . $dO->DriveLetter . ": - " . $type[$dO->DriveType] . " - " . $n . " - " . $s . "<br>";

}

function
file_size($size)
{
$filesizename = array(" 字节", " KB", " MB", " GB", " TB", " PB", " EB", " ZB", " YB");
return
$size ? round($size/pow(1024, ($i = floor(log($size, 1024)))), 2) . $filesizename[$i] : '0 字节';
}

?>

可以通过这种方式调用驱动器对象的许多其他属性,请参见

http://msdn.microsoft.com/en-us/library/ts2t8ybh%28VS.85%29.aspx
[email protected]
9年前
这是一个使用基于 COM/DOTNET 类的 NetPhp 库的 .Net 用法的示例。

您可以使用任何 .dll 文件,无论它是否为 COM 装饰,以及任何开箱即用的 .Net framework 类型。您还可以定位任何版本的 .Net framework。

<?php

$runtime
= new \NetPhp\Core\NetPhpRuntime('COM', 'netutilities.NetPhpRuntime');

// 添加SpreadsheetLight和它依赖的OpenXML。
$runtime->RegisterAssemblyFromFile('/binaries/SpreadsheetLight.dll', 'SpreadsheetLight');
$runtime->RegisterAssemblyFromFile('/binaries/DocumentFormat.OpenXml.dll', 'DocumentFormat.OpenXml');
$runtime->RegisterAssemblyFromFile('/binaries/AjaxMin.dll', 'AjaxMin');

// 使用属于已注册程序集的类型的完整名称。
$datetime = $runtime->TypeFromName("System.DateTime");

// 使用尚未注册的类型的完整名称(来自文件)
$minifier = $runtime->TypeFromFile("Microsoft.Ajax.Utilities.Minifier", APPLICATION_ROOT . '/binaries/AjaxMin.dll');

// 使用尚未注册的类型的完整名称(可自动发现)
$datetime2 = $runtime->TypeFromAssembly("System.DateTime", "mscorlib, ....");

$datetime->Instantiate();
echo
$datetime->ToShortDateString()->Val(); // 输出 01/01/0001

// 我们只能从原生 PHP 使用 Int32,因此解析
// 等效于 DateTime 构造函数中的 (long) 的 Int64。
$ticks = $runtime->TypeFromName("System.Int64")->Parse('98566569856565656');

$datetime->Instantiate($ticks);
echo
$datetime->ToShortDateString()->Val(); // 输出 07/05/0313

// 我们只能从原生 PHP 使用 Int32,因此解析
// 等效于 DateTime 构造函数中的 (long) 的 Int64。
$ticks = $runtime->TypeFromName("System.Int64")->Parse('98566569856565656');

// 转储 .Net System.Timers.Timer 对象!
$data = $timer->GetPhpFromJson();

var_dump($data);

// 输出:
// object(stdClass)[38]
// public 'AutoReset' => boolean true
// public 'Enabled' => boolean false
// public 'Interval' => int 100
// public 'Site' => null
// public 'SynchronizingObject' => null
// public 'Container' => null

// 检查今天是否是星期一
$IsMonday = $runtime->TypeFromName("System.DateTime")->Now->DayOfWeek->
Equals($runtime->TypeFromName("System.DayOfWeek")->Enum('Monday'));

?>
[email protected]
18年前
似乎PHP不支持使用参数设置属性。这就是我解决这个问题的方法

// 带有我想设置的方法的对象
$auth = new COM("AUTHXOCX.AuthXOCXCtrl.1");

// ScriptControl
$oScript = new COM("MSScriptControl.ScriptControl");
$oScript->Language = "VBScript";
$oScript->AllowUI = TRUE;

// 将我们的对象添加到控件
$oScript->AddObject('auth', $auth, true);

// 创建一个VBScript函数,允许我设置它们
$oScript->AddCode(
'Function fixAccess(accessname)
auth.AuthDataReferrerEnabled(accessname) = 1
auth.AuthDataAuthentiXDBEnabled(accessname) = 0
End Function');

// 执行函数
$oScript->Run("fixAccess", $dir);
[email protected]
19 年前
基本的Windows IO
如果您在 Win32 平台上使用命令行 (CLI) 版本的 PHP,您可能希望拥有一个简单的图形界面来获取输入和输出。以下是两者的一个示例。

<?php
// 首先获取一些输入
$oScript = new COM("MSScriptControl.ScriptControl");
$oScript->Language = "VBScript";
$title = "I/O 演示:输入部分";
$initial = "更改此值";
$prompt = "请输入一个值";

$code = <<<EOF
Function getInput()
inVal = InputBox("
$prompt", "$title", "$initial")
getInput = inVal 'VB 中返回值的赋值方式
End Function
EOF;

$oScript->AddCode($code);
$input = $oScript->Eval("getInput()");
if (
gettype($input)=="NULL") $input = "输入框已取消";

// 现在显示一些输出
$oWSH = new COM("WScript.Shell");
$title = "I/O 演示:输出部分";
$timeout = 2; // 0 表示无超时
$style = 0 + 48; // 显示按钮 + 警报符号
$oWSH->Popup($input, $timeout, $title, $style);
?>

此示例为了说明目的而过于复杂。如果使用的代码只有一条语句,则整个输入部分会崩溃。因此,以下代码就足够了
$code = "InputBox(\"$prompt\", \"$title\", \"$initial\")";
$input = $oScript->Eval($code);

此技术展现了与 Windows 操作系统和 VBScript 绑定的相当强大的脚本功能。但是,您应该有充分的理由使用它,因为在我的测试中,与 PHP 相比,VBScript 的速度非常慢。但是,像这样的简单 I/O 很好,弹出窗口的大小可以非常大。此外,这可能是访问 WinAPI 的可行途径。

http://www.ss64.com/wsh/popup.html 显示了一些关于 $oWSH->Popup 的文档

来自维也纳的 Csaba Gabor
[email protected]
15年前
大家好,在尝试了无数次创建 Crystal Report 的 PDF 格式报表后,我想与大家分享我的经验。
最终我成功地完成了,没有任何错误。
我的系统配置如下:PHP 5.1.6、MSSQL2005 和 Crystal Report Server XI RL2

<?php

//- 变量 - 用于您的 RPT 和 PDF
echo "打印报表测试";
$my_report = "D:\\Folder1\\SubFolder1\\Report.rpt"; //
rpt 源文件
$my_pdf
= "D:\\Folder1\\SubFolder1\\Report.pdf"; // RPT 导出到 pdf 文件
//-创建新的 COM 对象-取决于您的 Crystal Report 版本
$ObjectFactory= new COM("CrystalReports115.ObjectFactory.1") or die ("加载错误"); // 调用 COM 端口
$crapp = $ObjectFactory-> CreateObject("CrystalDesignRunTime.Application"); // 为 Crystal 创建一个实例
$creport = $crapp->OpenReport($my_report, 1); // 调用 rpt 报表

// 刷新数据之前

//- 设置数据库登录信息 - 必须有
$creport->Database->Tables(1)->SetLogOnInfo("服务器名", "数据库名", "用户名", "密码");

//- 参数提示,否则报表将挂起 - 通过
$creport->EnableParameterPrompting = 0;

//- DiscardSavedData - 刷新然后读取记录
$creport->DiscardSavedData;
$creport->ReadRecords();


// 导出到 PDF 过程
$creport->ExportOptions->DiskFileName=$my_pdf; // 导出到 pdf
$creport->ExportOptions->PDFExportAllPages=true;
$creport->ExportOptions->DestinationType=1; // 导出到文件
$creport->ExportOptions->FormatType=31; // PDF 类型
$creport->Export(false);

//------ 释放变量 ------
$creport = null;
$crapp = null;
$ObjectFactory = null;

//------ 将报表嵌入网页 ------
print "<embed src=\"D:\\Folder1\\SubFolder1\\Report.pdf\" width=\"100%\" height=\"100%\">"



?>

这就是我的全部内容,无论如何,在 Crystal Report 中,我必须在“选项”选项卡中检查“DiscardSavedData”、“保存带有报表的數據”和“自动保存 (1 分钟)”,并且还必须在“报表选项”中检查“保存带有报表的數據”。

希望这对大家有所帮助

Casanoteva
pavanphp Gudipati
15年前
在这里,我描述了一个程序,您可以使用 COM 组件连接任何 exe(软件)。
pdf2swf 是一款将 PDF 转换为 SWF 文件的软件。

这是 WScript.Shell 的最佳示例

<?php
# 使用 pdf2swf 软件将 pdf 转换为 swf 的代码
# 此代码在 Windows 环境中有效。


## 重要参数
$software_path ="C:\\SWFTools\\pdf2swf" ;
$pdf_path ="C:\\SWFTools\\abcd.pdf" ;
$argument = "-o";
$swf_output ="C:\\SWFTools\\abcd.swf" ;



# 实际代码
$cmd =" $software_path $pdf_path $argument $swf_output";

$WshShell = new COM("WScript.Shell");
$oExec = $WshShell->Run("cmd /C $cmd ", 0, true);

# 0 表示命令提示符隐藏模式
# 3 表示可见

?>
[email protected]
19 年前
要使用 Windows 语音系统,请从 Microsoft 主页安装“适用于 Windows 的语音 SDK 5.1”应用程序(免费下载)。
然后您可以像这样进行文本转语音:

$voice = new COM("SAPI.SpVoice");
$voice->Speak("Hello, lets have a conversation");
deletethis@bjoern(at)syltonline(dot)de
19 年前
如果您能获得旧的“TaskScheduler.dll”并注册它,那么从 PHP 处理和启动 Windows 任务就非常简单。
当您需要在不同的用户上下文中运行任务时,这非常有用。准备一个具有用户权限的任务,并使用 PHP 和 COM 为其构建 Web 界面。

以下是如何启动 Windows 任务的示例

function start_task ($taskname) {
$SchedObj = new COM("Scheduler.SchedulingAgent.1");
foreach ($SchedObj->Tasks as $task) {
if (strtolower( (string) $task) == strtolower( $taskname.".job" )) {
$task->Run();
}
}
}

我也正在开发一个PHP类来处理任务信息,以及添加和删除任务的功能。如有兴趣,请与我联系。
phpguy _from_ toshpro _dot_ com
20年前
如果您需要连接到Access数据库(服务器上,使用IIS或APACHE用户帐户),以下代码可以帮助简化此过程。之所以这样编写,是因为我们同时拥有MySQL和Access数据库,需要能够在两者之间切换。runQuery函数将返回一个二维数组,可以使用列名或数字作为内部数组的索引。外部数组始终使用整数索引。我们还发现Access数据库会保持打开状态并从7MB增长到2.5GB,时长仅为两小时,因此我们每次运行查询时都会打开和关闭它。如果这不是一个SELECT查询,它将返回TRUE。如果它因错误而失败,它将返回false。

我们主要只对MySQL使用showErr标志,因为您可以输出MySQL错误而无需PHP错误。Access似乎不那么友好。

<?php

function runQuery(&$conn,
$strSQL,
$associative=true,
$debug=false,
$showSQL=false,
$showErr=false) {
return
runMSQuery($conn,$strSQL,$associative,$debug,$showSQL,$showErr);
//return runMyQuery($conn,$strSQL,$associative,$debug,$showSQL,$showErr);
}

function
openMSDB($dbfile="c:/path/and/filename.mdb") {
if (!@
$conn = new COM("ADODB.Connection"))
exit(
"无法创建ADODB连接<br>");
$strConn = "DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=".$dbfile;
@
$conn->open($strConn);
if(
$conn->State == 0) return false;
return
$conn;
}

function
closeMSDB(&$conn) {
@
$conn->Close();
$conn = null;
return
true;
}

function
runMSQuery(&$conn,
$strSQL,
$associative=true,
$debug=false,
$showSQL=false,
$showErr=false) {
if(!
is_object($conn)) if(!$conn=openMSDB()) return false;
if(
$showSQL || $debug ) echo $strSQL."\n<br>\n";
$rtn = false;
if(
$debug) $rs = $conn->execute($strSQL);
else
$rs = @$conn->execute($strSQL);

if(!
$rs) {
if(
$showErr) echo "SQL执行错误。<br>\n";
closeMSDB($conn);
return
false;
}
if (
$rs->State == 0) {
closeMSDB($conn);
return
true;
} else {
$rows=0;
while(!
$rs->EOF) {
for(
$i=0;$i<$rs->Fields->count;$i++) {
$rsf = $rs->Fields($i);
if(
$associative) $rtn[$rows][$rsf->Name] = $rsf->value;
else
$rtn[$rows][$i] = $rsf->value;
}
$rows++;
$rs->MoveNext();
}
if(
$rs->State != 0) $rs->Close();
$rs = null;
}
if(
$debug) var_dump($rtn);
closeMSDB($conn);
return
$rtn;
}
?>
admin at CdnDomainRegistry dot ca
21 年前
这是一个VBScript和PHP的COM组件连接到IIS Web服务器的示例/比较。
这些示例在IIS中备份IIS Metabase(服务器网站的配置)。

VBScript
Dim obj, iFlags
Set obj = GetObject("IIS://LocalHost")
' 备份到下一个可用版本号。
' 设置标志以首先保存metabase,并且
' 即使保存失败也要强制备份。
iFlags = (MD_BACKUP_SAVE_FIRST or MD_BACKUP_FORCE_BACKUP)
obj.Backup "MyBackups", MD_BACKUP_NEXT_VERSION, iFlags
' 注意:以上内容是从Microbucks复制的。
' 这是您必须执行的操作方式。
' 即使用实际常量的值。
iFlags = (2 or 4)
obj.Backup "MyBackups", &HFFFFFFFF, iFlags

PHP
<?php
$obj
= new COM("IIS://LocalHost")or die("无法实例化IIS");
$err = com_invoke ($obj, "Backup", "MyBackups", "&HFFFFFFFF", 2|4 );
$obj = null;
print
"err=".$err; // 成功时返回0
?>

Glen
djogopatrao at gmail dot com
18年前
我之前关于Crystal Reports的笔记消失了,但无论如何我都准备修正它们。

上面的代码连接到COM(注意版本号!在注册表编辑器中搜索正确的名称以放入$COM_Object中),从文件($my_report)打开报表,从数据库重新加载记录,然后将其导出到PDF文件($my_pdf)。

* 重要 * 当从浏览器(我使用的是Apache)调用此代码并且使用连接到ODBC数据库的报表时,它不起作用(问题特别在于ReadRecords()行,但是当数据未保存到报表文件中时,它也可能出现)。

但是当您通过PHP-CLI(即通过命令行)运行此代码时,它可以正常工作!我已经报告了这个错误,但至今没有答案(如果您认为这很重要,请投票:http://bugs.php.net/bug.php?id=36959)。

此外,可能会出现异常,因此请将其放在try_catch块中。

--------------------------

// dfcp '06 ([email protected])

$COM_Object = "CrystalReports11.ObjectFactory.1";
$my_report = "C:\\report.rpt";
$my_pdf = "C:\\report.pdf";

$ObjectFactory= New COM($COM_Object);
$crapp = $ObjectFactory->CreateObject("CrystalDesignRunTime.Application");
$creport = $crapp->OpenReport($my_report, 1);
$creport->ReadRecords(); // 注意!

$creport->ExportOptions->DiskFileName=$my_pdf;
$creport->ExportOptions->PDFExportAllPages=true;
$creport->ExportOptions->DestinationType=1; // 导出到文件
$creport->ExportOptions->FormatType=31; // 类型:PDF
$creport->Export(false);
djogopatrao at gmail dot com
18年前
我在某个地方(http://www.recrystallize.com/merchant/supportfaq/supportfaq0003.htm)找到一个列表,将每个版本的Crystal Reports与其相应的progID关联起来——这可能会帮助那里的一些人。

7 Crystal.CRPE.Application

8.0 CrystalRuntime.Application 或 CrystalRuntime.Application.8

8.5 CrystalRuntime.Application 或 CrystalRuntime.Application.8.5

9 (RDC) CrystalRuntime.Application.9
9 (RAS) CrystalReports.ObjectFactory.2
10 (RDC) CrystalRuntime.Application.11
10 (CEE) CrystalReports10.ObjectFactory.1


XI (RDC) CrystalRuntime.Application.11
XI (RAS) CrystalReports11.ObjectFactory.1
johnno1985 at gmail dot com
16年前
我在任何地方都找不到关于我正在尝试执行的操作的示例。在从每个人那里获取了一些信息后,我最终得到了一些可用的东西。

我使用的是Crystal Reports 10、MS SQL Server 2005、Apache2和PHP5。

我的报表使用SQL存储过程,并传递一些参数来获取报表数据,因此我们的PHP必须设置数据库登录信息并传递参数。

下面是我想出的解决方案

<?php

//------ 变量 ------
$my_report = "C:\\Apache2\\htdocs\\test\\MyReport.rpt"; // 这必须是文件的完整路径
$my_pdf = "C:\\Apache2\\htdocs\\test\\MyReport.pdf";

//------ 创建一个新的Crytal Reports 10 COM对象 ------
$ObjectFactory= new COM("CrystalReports10.ObjectFactory.1");

//------ 创建库应用程序的实例 -------
$crapp = $ObjectFactory->CreateObject("CrystalDesignRunTime.Application.10");

//------ 打开您的rpt文件 ------
$creport = $crapp->OpenReport($my_report, 1);

//------ 设置数据库登录信息 ------
$creport->Database->Tables(1)->SetLogOnInfo("MYSERVER", "Database", "user", "password");

//------ 抑制参数字段提示,否则报表将挂起 ------
$creport->EnableParameterPrompting = 0;

//------ DiscardSavedData 在您的数据中进行刷新 -------
$creport->DiscardSavedData;
$creport->ReadRecords();

//------ 传递公式字段 --------
$creport->FormulaFields->Item(1)->Text = ("'My Report Title'");
$creport->ParameterFields(1)->AddCurrentValue ("FirstParameter");
$creport->ParameterFields(2)->AddCurrentValue (2000);

//------ 导出为PDF -------
$creport->ExportOptions->DiskFileName=$my_pdf;
$creport->ExportOptions->FormatType=31;
$creport->ExportOptions->DestinationType=1;
$creport->Export(false);

//------ 释放变量 ------
$creport = null;
$crapp = null;
$ObjectFactory = null;

//------ 将报表嵌入网页 ------
print "<embed src=\"MyReport.pdf\" width=\"100%\" height=\"100%\">"

?>

显然,这里有很多改进的空间,但它有效,应该能让你走上正轨。我还发现,在测试期间,脚本在抑制参数提示之前挂起了。一旦发生这种情况,一些之前有效的导出就完全停止了,除非我重启Apache,否则无法再次工作。如果脚本挂起后仍然遇到问题,这可能是值得尝试的。
Eion Robb
10年前
这里的所有示例都显示
<?php $var = new COM('Whatever.Something') or die(); ?>
但是'or die()'部分是多余的,因为将抛出一个致命的'com_exception'异常,从而终止您的脚本。如果您想处理'or'条件,则需要捕获异常,例如
<?php
try {
$var = new COM('Whatever.Something');
} catch (
com_exception $e) {
//无法加载,执行其他操作,例如注册
exec('regsvr32 /s whatever.dll');
}
?>
IceNV
7年前
在PHP7(.x) 64位下,存在一个文档错误(在MSDN端,已报告),如果您尝试通过COM操作注册表(StdRegProv),则会导致问题。

事实上,MSDN报告说注册表hive/root必须报告为uint32,这意味着在PHP 64位中,将创建一个新的Variant($root,VT_UI4)。

这将抛出一个类型不匹配错误。
似乎在内部,与MSDN所说的相反(截至目前,2016-12-13),root参数实际上必须作为int32传递。

所以你必须
1. 将您的root数字转换为负整数,以避免在下面创建变体时出现越界异常(基本上整数>= 2^31,您必须自己将它包装在32位有符号整数最大值内);
2. 创建一个新的Variant($root,VT_I4);
3. 将该变体传递给您的COM API调用。

在PHP 7.0之前不会发生这种情况,因为它之前总是内部使用VT_I4(参见https://bugs.php.net/bug.php?id=73605),但现在它尊重(并且这样做是正确的)真实的整数长度,所以如果没有显式转换,PHP7现在将在x64上输出VT_I8,而PHP5为VT_I4。
Danil_lll
6年前
你好。这里有一段C#代码,它使用COM库(用C++编写)- hybrid.dll。
我需要将这段代码从C#重写到PHP(即连接COM库到PHP代码)

这是在C#中调用的函数
Gr = HybridLib.Hybrid_Color.GREEN;

这是库中“Hybrid_Color”的列表
enum Hybrid_Color
{
GREEN = 0x00000001,
BLACK = 0x00000002,
BLUE = 0x00000004,
};

该库本身在PHP中启动
$PHP_Lib = new COM("HybridLib.Hybrid");

无法赋值
$gr = $PHP_Lib -> ..... ?????

接下来我写什么,我不知道……
请告诉我,谁知道……
dpchiesa at hotmail dot com
15年前
这是一个使用DotNetZip通过COM类在PHP中创建AES加密ZIP文件的方法。

<?php
try
{
$fname = "zip-generated-from-php-" . date('Y-m-d-His') . ".zip";
$zipOutput = "c:\\temp\\" . $fname;
$zip = new COM("Ionic.Zip.ZipFile");
$zip->Name = $zipOutput;
$dirToZip= "c:\\temp\\psh";
#$dirToZip= "c:\\dinoch\\webs\\php";
$zip->Encryption = 3;
$zip->Password = "AES-Encryption-Is-Secure";
$zip->AddDirectory($dirToZip);
$zip->Save();
$zip->Dispose();

if (
file_exists($zipOutput))
{
header('Cache-Control: no-cache, must-revalidate');
header('Content-Type: application/x-zip');
header('Content-Disposition: attachment; filename=' . $fname);
header('Content-Length: ' . filesize($zipOutput));
readfile($zipOutput);
unlink($zipOutput);
}
else
{
echo
'<html>';
echo
' <head>';
echo
' <title>Calling DotNetZip from PHP through COM</title>';
echo
' <link rel="stylesheet" href="basic.css"/>';
echo
' </head>';
echo
'<body>';
echo
'<h2>Whoops!</h2>' . "<br/>\n";
echo
'<p>The file was not successfully generated.</p>';
echo
'</body>';
echo
'</html>';
}
}
catch (
Exception $e)
{
echo
'<html>';
echo
' <head>';
echo
' <title>Calling DotNetZip from PHP through COM</title>';
echo
' <link rel="stylesheet" href="basic.css"/>';
echo
' </head>';
echo
'<body>';
echo
'<h2>Whoops!</h2>' . "<br/>\n";
echo
'<p>The file was not successfully generated.</p>';
echo
'<p>Caught exception: ', $e->getMessage(), '</p>', "\n";
echo
'<pre>';
echo
$e->getTraceAsString(), "\n";
echo
'</pre>';
echo
'</body>';
echo
'</html>';
}

?>
hwcshirley at gmail dot com
18年前
回复:djogopatrao at gmail dot com
我稍微改了你的代码。它能运行了。

$COM_Object = "CrystalDesignRunTime.Application";
$my_report = "C:\\appserv\\www\\mc\\test.rpt";
$my_pdf = "C:\\appserv\\www\\mc\\test.pdf";

$crapp= New COM($COM_Object) or die("无法创建对象");
$creport = $crapp->OpenReport($my_report, 1);
$creport->ReadRecords(); // 注意!

$creport->ExportOptions->DiskFileName=$my_pdf;
$creport->ExportOptions->PDFExportAllPages=true;
$creport->ExportOptions->DestinationType=1; // 导出到文件
$creport->ExportOptions->FormatType=31; // 类型:PDF
$creport->Export(false);
sodeh at dana dot ir
20年前
连接SQL Server并了解utf-8编码
使用此方法连接数据库

$db = new COM("ADODB.Connection",NULL, 65001 );
drich at nea-online dot net
21 年前
修改MS Word中的字段(非FORMFIELDS)……

我为此搜索了整个下午,因为这是我们项目中需要的东西。也许这对其他人也有帮助。

<?php
$input
= "x:\\path\\to\\test.doc";
$word = @new COM("word.application") or die("无法实例化Word");
print
"加载Word,版本 {$word->Version}\n<br>";
$word->Visible = 1;
print
"设置Word为可见<br>";
$word->Documents->Open($input);
print
"已打开 $input<br>";
$word->Activate;
print
"已激活Word<br>";

print
"编辑字段<br>";
$Field = $word->ActiveDocument->Fields(1);
$fieldData = $Field->Result;
$fieldData->Text = "测试";

// 打印文档
$word->Printout();

// 关闭Word
$word->Quit();

// 释放对象
$word->Release();
$word = null;

?>
sadi at unicornsoftbd dot com
19 年前
如果你的PHP配置为ISAPI模块,那么你在PHP页面中创建的COM对象将与Web服务器使用相同的内存空间。如果你的COM对象占用太多内存,这可能会强制一些COM错误,因为PHP本身不处理COM的内存使用情况。而且Web服务器也不知道如何释放COM内存。但是,如果将PHP用作CGI,则PHP本身会处理COM的内存使用情况。在一个我使用COM和PHP作为ISAPI模块的脚本中,我得到了未知的COM错误。但是当我使用PHP作为CGI时,没有错误。因此,那些希望在应用程序中使用COM对象的人请注意这一点。
jon at jonroig dot com
21 年前
这是一个使用MS Word打印格式化模板的简单示例。

首先,我已经在Word中创建了我的发票并将其保存为RTF文件。
在本例中,我使用的是“sampleInvoice.php”

将要替换的字段已标记为||CUSTOMER ID||等等。

<?php
$dataText
= "";

// 打开文件
if(!($fp= fopen ("C:\wordTest\sampleInvoice.rtf", "r"))) die ("无法打开");
$dataText = fread($fp, 2000000);
fclose ($fp);

// 替换模板字段
$dataText = str_replace ("||CUSTOMER ID||",$customerIDValue, $dataText);

// 将文件保存为rtf
$timeStamp = time();
$saveFile = "C:/wordTemp/".$timeStamp."-invoice-".$customerIDValue.".rtf";
if(!(
$fq= fopen ($saveFile, "w+"))) die ("无法打开");
fwrite ($fq, $dataText);
fclose ($fq);

// 初始化Word组件
$word = new COM("word.application") or die("无法实例化Word");

print
"加载Word版本 ($word->Version)\n";
$word->visible = true;
$word->Documents->Add();

// 打开文件
$word->Documents->Open("$saveFile");

// 将文件输出到默认打印机
$word->ActiveDocument->PrintOut(1);

// 关闭Word
$word->Quit();
?>
info at sharedprojects dot nl
21 年前
<?php
// 另一种连接方式
// 此连接到在
// ODBC 数据源管理器(在系统 DSN 下)中添加的 ODBC 数据源

$odbcname = "northwind";
$conn->Open("DSN=$odbcname");
?>
eguan1ao_at_yahoo_dot_com
22年前
连接Microsoft Access数据库、执行SQL查询以及在HTML中显示结果的示例。

<?php

$db
= 'C:\\Program Files\\Microsoft Office\\Office\\Samples\\Northwind.mdb';

$conn = new COM('ADODB.Connection');

// 连接的两种方式。选择一种。
$conn->Open("Provider=Microsoft.Jet.OLEDB.4.0; Data Source=$db");
//$conn->Open("DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=$db");

$sql = 'SELECT ProductName, QuantityPerUnit, UnitPrice
FROM Products
ORDER BY ProductName'
;
$rs = $conn->Execute($sql);

?>

<table>
<tr>
<th>产品名称</th>
<th>每单位数量</th>
<th>单价</th>
</tr>
<?php while (!$rs->EOF): ?>
<tr>
<td><?= $rs->Fields['ProductName']->Value ?></td>
<td><?= $rs->Fields['QuantityPerUnit']->Value ?></td>
<td><?= $rs->Fields['UnitPrice']->Value ?></td>
</tr>
<?php $rs->MoveNext() ?>
<?php
endwhile ?>
</table>

<?php

$rs
->Close();
$conn->Close();

?>
mstaiger at informatik dot uni-siegen dot de
22年前
我发现上面的示例(MS Word)相当令人不满。尤其是我找不到任何人真正让它运行起来,包括我自己。

因此,你或许可以尝试一下这个Powerpoint示例
----------------------------------
# 实例化 PowerPoint 对象。
$ppoint = new COM("PowerPoint.application") or die("无法实例化 PowerPoint");

<?php
# 创建一个新的演示文稿
$ppoint->Presentations->Add() or die ("无法创建演示文稿");

// 添加一个幻灯片
$slide=$ppoint->Presentations[1]->Slides->Add(1,1);

// 获取该幻灯片的名称
$slidename = $slide->Name();
echo
"<br>slidename : $slidename";

// 更改该新幻灯片的名称
$slide->Name = "New Slidename";
$slidename = $slide->Name();
echo
"<br>NEW slidename : $slidename";

// 保存演示文稿
$ppoint->Presentations[1]->SaveAs("c:/InetPub/www/test.ppt");
$ppoint->Presentations[1]->Close();

// 关闭 PowerPoint
$ppoint->Quit();

// 释放对象
$ppoint->Release();
$ppoint = null;
-----------------------
?>

配置为
w2k-服务器/office2k/iis5/php 4.1.1 isapi

如果您碰巧运行了一个可用的 word2k 示例,请告诉我。

Marc
To Top