dotnet 类

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

介绍

dotnet 类允许您从 .Net 程序集实例化一个类,并调用其方法和访问其属性,前提是该类及其方法和属性对 COM 可见。

不支持实例化静态类或调用静态方法。也不支持实例化泛型类,例如 System.Collections.Generic.List

一些 .Net 类未实现 IDispatch,因此虽然可以实例化它们,但不能调用这些类的方法或访问其属性。

注意:

您需要在 Web 服务器上安装 .Net 运行时才能利用此功能。

注意:

在 PHP 8.0.0 之前,.Net framework 4.0 及更高版本不受 dotnet 类支持。如果程序集已使用 regasm.exe 注册,则可以将这些类实例化为 com 对象。从 PHP 8.0.0 开始,通过 php.ini 指令 com.dotnet_version 支持 .Net framework 4.0 及更高版本。

类概要

class dotnet extends variant {
/* 方法 */
public __construct(string $assembly_name, string $datatype_name, int $codepage = CP_ACP)
}

重载方法

返回的对象是一个重载对象,这意味着 PHP 不会像处理普通类一样看到任何固定方法;相反,任何属性或方法访问都会传递给 COM,然后传递给 DOTNET。换句话说,.Net 对象通过 .Net 运行时提供的 COM 互操作层进行映射。

创建 dotnet 对象后,PHP 会像对待任何其他 COM 对象一样对待它;所有相同的规则都适用。

dotnet 示例

示例 #1 dotnet 示例

<?php
$stack
= new dotnet("mscorlib", "System.Collections.Stack");
$stack->Push(".Net");
$stack->Push("Hello ");
echo
$stack->Pop() . $stack->Pop();
?>

目录

添加注释

用户贡献的注释 12 个注释

9
juan156_elias at gmail dot com
9 年前
直接使用 COM 和 DOTNET 非常痛苦。DOTNET 仅允许您定位 .Net 3.5 及更低版本,并且所有二进制文件都需要是 COM 可见。这基本上意味着您需要为所有内容编写自己的 .Net 二进制文件,至少是包装器。

有一个库 (NetPhp) 建立在 COM 类之上,可以解决所有这些问题,因此您可以获得以下代码

$manager = new \NetPhp\Core\NetManager();
$manager->RegisterAssembly('mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089', 'mscorlib');
$manager->RegisterClass('mscorlib', 'System.IO.File', 'File');
$manager->RegisterClass('mscorlib', 'System.IO.FileOptions', 'FileOptions');
$file = $manager->Create('mscorlib', 'File');
$fileoptions = $manager->Create('mscorlib', 'System.IO.FileOptions')->Enum('Encrypted');

$file->Create("C:\\www\\prueba.tres", 2048, $fileoptions);
8
ricardopsj at gmail dot com
10 年前
使用 DOTNET 创建一个 Excel 工作簿。

<?php

$full_assembly_string
= 'Microsoft.Office.Interop.Excel, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c';
$full_class_name = 'Microsoft.Office.Interop.Excel.ApplicationClass';

$e = new DOTNET($full_assembly_string, $full_class_name);
$wb = $e->workbooks->add();
$Precios = $wb->Worksheets(1);
$Precios->Name = 'Precios';
$Venta = $wb->Worksheets(2);
$Venta->Name = 'Venta';
$Tons = $wb->Worksheets(3);
$Tons->Name = 'Tons';

$Meses = Array('2014-01', '2014-02', '2014-03', '2014-04', '2014-05', '2014-06', '2014-07', '2014-08', '2014-09', '2014-10', '2014-11', '2014-12');
foreach (
$Meses as $Numero => $Mes) {
$Precios->Range("A" . ($Numero+1))->Value = $Mes;
}

$wb->SaveAs('c:\temp\Meta.2014.05.xlsx');
$wb->Close();

?>

转到 c:\windows\assembly 以了解在 $full_assembly_string 中输入什么值。

如果您不知道程序集,请使用 http://www.red-gate.com/products/dotnet-development/reflector/ 浏览它,使用您在其中学到的内容来填充 $full_class_name。

享受,

Ricardo.
1
Bitterblue
6 年前
我过去几天一直在使用它,终于搞明白了。
在 stack overflow 上:https://stackoverflow.com/a/51541801/1442225
3
jan dot zahradnik at data3s dot com
10 年前
PHP 仅在 GAC 中搜索 .NET 2.0 运行时,因此您的 DLL 必须定位 2.0 - 3.5 框架。

它也只识别类,不识别结构体,因此您不能实例化 DateTime,例如。
1
jcastromail at yahoo dot es
7 年前
使用 Visual Studio 2015(以及 .NET Framework 4.6.1,其他版本类似)进行 .NET 开发。

1) 在 Visual Studio 2015 中,创建一个库项目(本例中使用 C#)。
2) 双击项目-> 构建事件-> 构建后事件。

"C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6 Tools\gacutil.exe" /i "$(TargetPath)"

项目编译后,会自动添加到全局程序集缓存 (GAC) 中。请根据您的安装路径修改 bin 文件夹路径。

3) 在工具-> 外部工具中,添加以下外部工具。
标题: 获取限定程序集名称
命令: Powershell.exe
参数: -command "[System.Reflection.AssemblyName]::GetAssemblyName(\"$(TargetPath)\").FullName"
用户输出窗口: 勾选

4) 运行工具-> 获取限定程序集名称,并查看输出窗口。

5) 创建以下类(Class1 可能已经存在)。

namespace ClassLibrary2 // <-- 修改此部分。
{
public class Class1
{
public string Ping(string t1, string t2)
{
return "pong " + t1 + t2;
}
}
}

6) 在 PHP 代码中

$full="ClassLibrary2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=746927f9726d7222"; // 从输出窗口获取
$class = 'ClassLibrary2.Class1'; // 命名空间和类名。

$stack = new DOTNET($full,$class);
$r1="hello";
$r2="world";
echo $stack->Ping($r1,$r2);

重要提示: PHP 会“缓存”DLL 库,因此每次编译 DLL 库后,都需要重启 PHP 服务(重启 Apache 服务)。
重要提示 2: 您可能需要以管理员身份运行 Visual Studio。
1
m dot atifmajeed at gmail dot com
9 年前
如何使用 .NET 类创建参数化构造函数的对象

https://php.net/manual/en/class.dotnet.php

private SGF ingerPrintManager m_FPM; // 成员变量
SGFPMDeviceName device_name = SGFPMDeviceName.DEV_ FDU02 ;
m_FPM = new SGF ingerPrintManager (device_name);
1
Anonymous
14 年前
如前所述,您可能需要使用完整的程序集字符串,包括程序集名称、程序集版本(不是 DLL 文件版本)、区域性和公钥标记。否则,您将收到一个可捕获的“文件未找到”错误。要快速找到您自己系统上的程序集,以开始使用,请在资源管理器中打开 C:\Windows\assembly(不要在 cmd 中打开,因为这会显示不同的视图),向下滚动列表,直到找到要使用的程序集,将鼠标悬停在它上面,工具提示将显示要使用的确切字符串(虽然显示的 processcorArchitecture 是可选的)。您将不得不使用 .NET 工具或其他方法在其他机器上自动收集这些信息。

您还需要使用完全限定的类名。换句话说,如果您想使用“System.Windows.Forms”中的“Form”类,您必须使用完整的类层次结构“System.Windows.Forms.Form”。否则,您将收到一个无用的“无法实例化 .NET 对象”可捕获错误。

以下示例展示了使用“Form”类从 php-cli 弹出空白窗体的正确语法,这可以用来代替许多 Windows GUI PHP 扩展。将 Version 替换为您的本地版本,将 PublicKeyToken 替换为您的本地公钥标记。

<?php

$full_assembly_string
= 'System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=a8425bc35256e463';
$full_class_name = 'System.Windows.Forms.Form';
$form = new DOTNET($full_assembly_string, $full_class_name);

// 代码来添加按钮、菜单、文本等

$form->Show();

$form_event = '';
while(
$form_event !== 'close') {

// 处理窗体函数和事件

}
?>
0
murat at muratyaman dot co dot uk
14 年前
首先,我遇到了同样的问题

"... 无法实例化 .NET 对象 [未包装,QI 用于 IDispatch] [0x80004002] 不支持此类接口 ..."

为了成功加载程序集和其中的类,我不得不更改我的 AssemblyInfo.cs 文件,更改其中类型可见性。

// 一些代码在上面

// 此设置将程序集中的类型的默认 COM 可见性设置为不可见。
// 如果您需要将类型公开给 COM,请在该类型上使用 [ComVisible(true)]。
[assembly: ComVisible(true)]

// 一些代码在下面
0
kschroeder at mirageworks dot com
15 年前
要找出 PublicKeyToken 的值,请打开资源管理器并转到 c:\windows\assembly。在该目录中,您将看到所有已注册的程序集以及它们的 PublicKeyToken 值。
-1
sandips (yardi)
13 年前
练习尝试不同类型的函数签名并在 PHP 中调用它们。

VB.NET 代码
Public Class Class1
Public Function SayHello(ByVal input As String) As String
Return "Php input: " & input & "</BR>Dot net library said- 'Hello'"
End Function
Public Function ConcatArray(ByVal Values As Object()) As String
Dim ret As String = String.Empty
For Each sval As Object In Values
ret = ret & sval.ToString & " "
Next
Return ret.Substring(1, ret.Length - 1)
End Function
Public Function ReturnObject(ByVal FirstName As String, ByVal LastName As String) As Name
Dim obj As New Name
obj.FirstName = FirstName
obj.LastName = LastName
Return obj
End Function
'解释 ByRef 不适用于 PHP
Public Function CallByRef(ByRef value As String) As String
value = "Value to ByRef parameter set in dot net."
Return "ByRef CallByRef() method called."
End Function
End Class

Public Class Name
Public FirstName As String = String.Empty
Public LastName As String = String.Empty
End Class

PHP 代码用于测试 .NET 库
<?php
$class1
= new DOTNET("DotNetTest,"
."Version=1.0.0.0,"
."Culture=neutral,"
."PublicKeyToken=6675daefc27eafc4"
,"DotNetTest.Class1");
echo
$class1->SayHello("Hi PHP!!!!");
echo
"</P>";

$parameter[0] = 12345;
$parameter[1] = "MyString";
$parameter[2] = false;
$ret = $class1 -> ConcatArray($parameter);
echo
$ret;
echo
"</P>";

$Obj = $class1 -> ReturnObject("Sandip","Shimpi");
echo
$Obj->FirstName." ".$Obj->LastName;

echo
"</P>";
$myByRef = "";
echo
"Value of ByRef Variable before calling .net CallByRef() method: ".$myByRef;
echo
"</BR>";
echo
$class1 -> CallByRef($myByRef);
echo
"</BR>";
echo
"Now value of ByRef Variable: ".$myByRef;
echo
$myByRef;
?>
-1
m holmes at windowlogic dot com dot au
14 年前
对于已注册到 GAC 中的强命名 .NET 程序集,您只需使用程序集名称即可。
例如: $x = new DOTNET ("myAssembly", "myClass");

对于未注册到 GAC 中的强命名 .NET 程序集,您需要使用完整的程序集字符串。
例如: $x = new DOTNET('myAssembly, Version=X.X.X.X, Culture=neutral, PublicKeyToken=ZZZZZZZZZZZZ', 'myClass');

您无法实例化未进行强命名的程序集。

“强命名”意味着程序集具有公钥。要在 Visual Studio 中对您自己的类进行强命名,请转到项目属性中的“签名”选项卡,然后单击“签名程序集”框并选择一个密钥文件名称。

要将程序集注册到 GAC 中,可以使用各种工具,但最简单的方法是使用 Windows 资源管理器将编译后的程序集拖放到 c:\windows\assembly(默认情况下会安装一个处理拖放文件的 shell 扩展)。
-4
sam at bitopia dot co dot uk
16 年前
如果您想加载除 mscorlib 之外的任何其他程序集,您需要像下面这样包含它

$x = new DOTNET('The.Assembly.Name, Version=X.X.X.X, Culture=neutral, PublicKeyToken=ZZZZZZZZZZZZ', 'The.Class.Name');

替换所有相关的细节。
To Top