PHP Conference Japan 2024

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 之前,dotnet 类不支持 .Net framework 4.0 及更高版本。如果程序集已使用 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 条注释

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);
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。
Bitterblue
6 年前
我过去几天一直在使用它,并弄明白了。
在 Stack Overflow 上:https://stackoverflow.com/a/51541801/1442225
jan dot zahradnik at data3s dot com
10 年前
PHP 仅在 GAC 中搜索 .NET 2.0 运行时,因此您的 DLL 必须面向 2.0 - 3.5 框架。

此外,它只识别类,不识别结构体,因此例如您无法实例化 DateTime。
jcastromail at yahoo dot es
8 年前
使用 Visual Studio 2015 中的 dotnet(以及 net framework 4.6.1,但与其他版本相同)。

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 可能已经创建)

命名空间 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。
m dot atifmajeed at gmail dot com
9 年前
如何使用 donet 类创建参数化构造函数的对象

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);
匿名
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') {

// 处理窗体功能和事件

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

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

为了成功加载程序集及其中的类,我必须更改 AssemblyInfo.cs 文件,使其更改其中类型的可见性。

// 上面的某些代码

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

// 下面的某些代码
kschroeder at mirageworks dot com
15 年前
要找出 PublicKeyToken 值是什么,请打开资源管理器并转到 c:\windows\assembly。在该目录中,您将看到所有已注册的程序集及其 PublicKeyToken 值。
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;
?>
m holmes at windowlogic dot com dot au
15 年前
对于在 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 扩展)。
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