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 二進位檔,至少是包裝器。

有一個建構在 COM 類別之上的程式庫(NetPhp)可以解決所有這些問題,因此您可以獲得類似以下的程式碼

$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 應填入的值。

如果您不清楚組件 (assembly),請使用 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 框架為目標。

此外,它只會辨識類別 (class),不會辨識結構 (struct),所以您無法例如實例化 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 可能已經建立)

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。
m dot atifmajeed at gmail dot com
9 年前
如何使用 .NET 類別來建立具有參數化建構子的物件

https://php.dev.org.tw/manual/en/class.dotnet.php

private SGF ingerPrintManager m_FPM; //成員變數
SGFPMDeviceName device_name = SGFPMDeviceName.DEV_ FDU02 ;
m_FPM = new SGF ingerPrintManager (device_name);
Anonymous
14 年前
如先前建議,您可能需要使用完整的組件字串,包括組件名稱、組件版本 (不是 dll 檔案版本)、文化特性和公開金鑰權杖。否則,您會收到「找不到檔案」的可捕捉錯誤。若要快速在您自己的系統上找到此資訊以開始處理,請在檔案總管中開啟 C:\Windows\assembly (不要在 cmd 中開啟,因為它會顯示不同的檢視),向下捲動清單直到找到您要使用的組件,將滑鼠游標停留在其上方,工具提示會顯示要使用的確切字串 (雖然顯示的 processcorArchitecture 是選用的)。您必須使用 .NET 公用程式或其他方法來自動收集其他機器上的這項資訊。

您也必須使用完整的類別名稱。換句話說,如果您想要使用 'System.Windows.Forms' 內的 'Form' 類別,您必須使用完整的類別階層 'System.Windows.Forms.Form'。否則,您會收到無用的「無法實例化 .Net 物件」的可捕捉錯誤。

以下範例顯示從 php-cli 彈出空白表單的 'Form' 類別的正確語法,它可以用來代替許多 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 物件 [Unwrapped, QI for IDispatch] [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

用於測試 .net 程式庫的 Php 程式碼
<?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