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("这是一个测试...");
$word->Documents[1]->SaveAs("无用测试.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;

?>

目录

添加备注

用户贡献的备注 37 个备注

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

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

- 命令失败

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

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

我希望我能为你们中的一些人节省很多很多小时的麻烦 :)
4
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());
?>
10
rogier
12 年前
我花了很长时间才通过试错法解决这个问题。

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

正确的方法是使用类型为 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);

?>

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

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


另外,以 IUSR_<机器名> 帐户登录机器,启动 Word,并确保单击 Word 在首次为特定用户运行时显示的对话框。换句话说,确保 Word 能够为 IUSR_ 用户正常打开。

更多有用信息可以在以下地址找到:
http://www.email-screen.com/support-doc2txt.html
4
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 应该得到下划线文本。但这两者对我来说都不起作用。
2
mastrboy.servebeer.com
16 年前
快速 WMI 查询示例

<?php
$obj
= new COM ( 'winmgmts://localhost/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";
?>
2
halfer
17 年前
感谢 paul at completewebservices 之前添加的备注;我使用他的代码解决了 Crystal 9 运行时组件的一个特别困难的问题。出于某种原因,VBA/VBS 可以将本机 Date 类型作为参数传递给需要日期的 Crystal 报表,但在 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");
?>
1
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");
?>
3
z3n at overflow dot biz
14 年前
在使用 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); ?>
1
csaba at alum dot mit dot edu
19 年前
将 IE 置于前台
如果您在 Win32 平台(例如 XP Pro,SP2)上使用命令行(CLI)版本的 PHP,您可能希望在 Popup 不够用时将输出重定向到 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 来自维也纳
1
rickardsjoquist at hotmail dot com
21 年前
如果您想对数据库使用无 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); 如果您想打印数组的结构。
2
sparrowstail at googlemail dot com
13 年前
此脚本报告所有 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 = "[Drive not ready]";
}
echo
"Drive " . $dO->DriveLetter . ": - " . $type[$dO->DriveType] . " - " . $n . " - " . $s . "<br>";

}

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

?>

驱动对象还有很多其他属性可以通过这种方式调用 - 请参见

http://msdn.microsoft.com/en-us/library/ts2t8ybh%28VS.85%29.aspx
3
juan156_elias at gmail dot com
8 年前
这是一个使用 NetPhp 库(基于 COM/DOTNET 类)的 .Net 使用示例。

您可以使用任何 .dll 文件,无论它是否装饰了 COM,以及任何开箱即用的 .Net 框架类型。您还可以针对任何版本的 .Net 框架。

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

?>
2
paul at completewebservices dot com dot au
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);
2
csaba at alum dot mit dot edu
19 年前
基本 Windows IO
如果您在 Win32 平台上使用 PHP 的命令行 (CLI) 版本,您可能希望使用简单的图形界面来获取输入和输出。以下列出了这两种方法的示例。

<?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 来自维也纳
2
casanoteva at yahoo dot com
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("servername", "DBname", "user", "password");

//- 字段提示,否则报表会挂起 - 以确保流程顺利进行
$creport->EnableParameterPrompting = 0;

//- 丢弃保存的数据 - 刷新数据,然后读取记录
$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 中,我必须在“选项”选项卡中检查“丢弃保存的数据”、“将数据与报表一起保存”和“自动保存(1 分钟)”,并且在报表选项中,我也必须检查“将数据与报表一起保存”。

希望这能帮到任何人

Casanoteva
1
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 表示可见

?>
1
volker at kybs dot de
18 年前
要使用 Windows 语音系统,请从 Microsoft 主页(免费下载)安装“用于 Windows 的语音 SDK 5.1”。
然后你可以像这样进行文本转语音

$voice = new COM("SAPI.SpVoice");
$voice->Speak("Hello, lets have a conversation");
1
deletethis@bjoern(at)syltonline(doot)de
18 年前
如果你能获得旧的“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 添加和删除任务。如果你有兴趣,给我发个消息。
1
phpguy _from_ toshpro _dot_ com
19 年前
如果你需要连接到 Access 数据库(在服务器上,使用 IIS 或 APACHE 用户帐户),以下代码可以帮助简化流程。这样编写是因为我们同时拥有 MySQL 和 Access 数据库,需要能够在两者之间切换。runQuery 函数将返回一个二维数组,可以使用列名称或数字作为内部数组的索引。外部数组总是使用整数索引。我们还发现 Access 会保持打开状态并在一两个小时内从 7MB 增长到 2.5GB,因此我们每次运行查询时都会打开和关闭它。如果它不是一个 select 查询,它将返回 TRUE。如果它因错误而失败,它将返回 false。

有一个 showErr 标志,我们主要只在 MySQL 中使用它,因为你可以在没有 PHP 错误的情况下输出 MySQL 错误。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;
}
?>
1
admin at CdnDomainRegistry dot ca
20 年前
以下是一个 VBScript 与 PHP 的 COM 组件连接 IIS Web 服务器的示例/比较。
这些示例将备份 IIS 元数据库(您服务器上的网站配置)到 IIS 中。

VBScript
Dim obj, iFlags
Set obj = GetObject("IIS://LocalHost")
' 备份到下一个可用的版本号。
' 将标志设置为先保存元数据库,
' 即使保存失败,也要强制备份。
iFlags = (MD_BACKUP_SAVE_FIRST 或 MD_BACKUP_FORCE_BACKUP)
obj.Backup "MyBackups", MD_BACKUP_NEXT_VERSION, iFlags
' 注意:以上内容是从 Microbucks 复制而来。
' 这是您必须执行的操作。
' 即使用实际常量的值。
iFlags = (2 或 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
1
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);
1
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
1
johnno1985 at gmail dot com
15 年前
我在任何地方都找不到关于我要做的事情的示例。在从每个人那里获取了一些信息后,我最终得到了一个有效的解决方案。

我使用的是 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";

//------ 创建一个新的 Crystal 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 之前无法再次工作。如果你在脚本挂起后仍然遇到问题,这可能是一个值得尝试的解决方法。
1
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');
}
?>
2
IceNV
7 年前
在 PHP7(.x) 64 位下,存在一个文档错误(在 MSDN 侧,已经报告),如果你尝试通过 COM 操作注册表(StdRegProv),会导致问题。

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

这将抛出一个类型不匹配错误。
看起来,与 MSDN 目前(截至 2016 年 12 月 13 日)所说内容相反,根参数实际上必须作为 int32 传递。

所以你需要
1. 将你的根数字转换为负数,以避免在创建下面的变体时出现越界异常(基本上,整数大于或等于 2^31,你需要手动将其封装到 32 位有符号整数的最大值);
2. 创建一个新的 Variant($root,VT_I4);
3. 将该变体传递给你的 COM API 调用。

这在 PHP 7.0 之前没有发生,因为它之前(参见 https://bugs.php.net/bug.php?id=73605)始终在内部使用 VT_I4,但现在它遵守(并且这样做是对的)真实的整数长度,因此在没有显式转换的情况下,PHP7 现在会在 x64 上输出 VT_I8,而 PHP5 会输出 VT_I4。
0
Danil_lll
6 年前
您好。这里有一段使用 COM 库(用 C++ 编写)的 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 -> ..... ?????

接下来要写什么,我不知道...
请告诉我,谁知道...
0
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>';
}

?>
0
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);
0
sodeh at dana dot ir
19 年前
关于连接到 SQL Server 并了解 utf-8 编码
使用这种方法连接数据库

$db = new COM("ADODB.Connection",NULL, 65001 );
-2
drich at nea-online dot net
20 年前
更改 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 = "Testing";

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

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

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

?>
-1
sadi at unicornsoftbd dot com
18 年前
如果你的 PHP 被配置为 ISAPI 模块,那么你在 php 页面中创建的 COM 对象将使用与 web 服务器相同的内存空间。如果你的 COM 对象占用太多内存,这可能会强制出现一些 COM 错误,因为 PHP 本身不处理 COM 的内存使用情况。而且 web 服务器也不知道如何释放 COM 内存。但如果你将 PHP 作为 CGI 使用,那么 PHP 本身将处理 COM 的内存使用情况。曾经在一个我使用 COM 和 PHP 作为 ISAPI 模块的脚本中,我遇到了未知的 COM 错误。但当我将 PHP 作为 CGI 使用时,就没有错误了。所以那些想要在你的应用程序中使用 COM 对象的人,请注意这一点。
-1
jon at jonroig dot com
20 年前
这是一个使用 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();
?>
-1
info at sharedprojects dot nl
21 年前
<?php
// 另一种连接方式
// 这将连接到在
// 系统 DSN 下的 ODBC 数据源管理员中添加的 ODBC 数据源

$odbcname = "northwind";
$conn->Open("DSN=$odbcname");
?>
-2
eguan1ao_at_yahoo_dot_com
21 年前
连接到 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();

?>
-2
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-server/office2k/iis5/php 4.1.1 isapi

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

马克
-6
amenthes at NOSPAM dot gmail dot com
16 年前
如果您想将 Excel(.xls) 文件保存为 Office Excel 2003 XML 格式,只需使用

$excel->Workbooks[1]->SaveAs('new_file_name.xml', 46);

这就是您需要的数字,46。
To Top