8

I'm quite a newbie in PHP and today I discovered DOTNET class.
So I studied manual, surfed the web to find some example and finally wrote my test app:

  1. Created a new DLL using Framework 4.0 Client Profile
  2. Signed the assembly with a strong name key
  3. Marked assembly as COM-Visible

This is the test code I wrote

using System;

namespace CSharpCOM
{
    public class CSharpCOMClass
    {
        public string Base64(string s)
        {
            return Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(s));
        }
    }
}

I compiled the assembly and then registered in GAC (gacutil /if fullpath\CSharpCOM.dll).
If I use gacutil /l CSharpCOM I see

La cache di assembly globale contiene gli assembly seguenti:
csharpcom, Version=1.0.0.0, Culture=neutral, PublicKeyToken=beb607ae770f5750, processorArchitecture=MSIL

Numero di elementi = 1

So everything seems ok.
Then wrote this basic php:

<?php
try{
    $csclass = new DOTNET("CSharpCOM, Version=1.0.0.0, Culture=neutral, " .
                          "PublicKeyToken=beb607ae770f5750",
                          "CSharpCOM.CSharpCOMClass");
    echo $csclass->Base64("Test string"),"\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}
?>

Whatever I try, loading page hosted in Apache (http://localhost/test01/dotnet.php) I always get

Caught exception: Failed to instantiate .Net object [CreateInstance] [0x80070002] Impossibile trovare il file specificato.
Translation could be: unable to find specified file

Just another thing: using some example (a very basic one here) I read that my assembly (when registered) should be found on %windir%\assembly, but I'm only able to find it in %windi%\Microsoft.NET\assembly\GAC_MSIL\CSharpCOM\v4.0_1.0.0.0__beb607ae770f5750: is this correct? Why don't I have it on first directory?

More: if I create another framework project and try to add a .NET reference I can't find my assembly: is this related to the fact I'm not able to load this assembly from PHP?

Last note: I tried it on Windows XP Professional SP3 32bit and on Windows Seven Enterprise 64bit

UPDATE:
This works:

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

but this one does not:

$form = new DOTNET('System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089', 'System.Windows.Forms.Form');`  

Is it possible that PHP can load only framework 2.0 assemblies?

user692942
  • 16,398
  • 7
  • 76
  • 175
Marco
  • 56,740
  • 14
  • 129
  • 152
  • 1
    Negative control: can you load classes from an existing assembly, e.g. mscorlib? It sounds as though the problem here isn’t PHP but rather that your assembly isn’t properly registered. – Konrad Rudolph Apr 18 '12 at 14:13
  • yes, I can use `$stack = new DOTNET("mscorlib", "System.Collections.Stack");` – Marco Apr 18 '12 at 14:15
  • OK, follow-up question: can you load an existing, signed assembly, providing its full name in PHP (including public key)? – Konrad Rudolph Apr 18 '12 at 14:16
  • Removing spaces is useless: same result :( I give a try with some other assembly, but for a couple of hours I'm busy... so I post my answer this evening (here is 4.20PM). Thanks – Marco Apr 18 '12 at 14:20
  • Regarding the directory, this is normal as far as I remember. The “%Windir%\Assembly” directory doesn’t actually physically exist but it’s populated when you open it in Explorer with information found elsewhere (i.e. the GAC). – Konrad Rudolph Apr 18 '12 at 14:20
  • @KonradRudolph: one little update before leaving – Marco Apr 18 '12 at 14:27
  • Permissions problem maybe? Does it work when PHP is executed from CLI as a normal user? – Janus Troelsen Apr 18 '12 at 14:32
  • @JanusTroelsen: sorry for stupid question... what should I try? I'm a newbie :) – Marco Apr 18 '12 at 14:35
  • open a command prompt in the directory with your php script and execute the script using i.e. "c:\php\php.exe script.php" – Janus Troelsen Apr 18 '12 at 14:37
  • @JanusTroelsen: using CLI I have same results – Marco Apr 18 '12 at 14:42
  • 3
    Looks like this is a known issue: https://bugs.php.net/bug.php?id=55847 Can you target your DLL to .NET 3.5 or lower? – heavyd Apr 18 '12 at 14:43
  • I'm just trying to understand why you would ever want to do this. If the server has .NET installed, then it likely has ASP.NET support, so why even bother with php at all? – jrummell Apr 18 '12 at 14:59
  • @jrummell: I must run my website with some PHP portal, better if using Apache. Later I should try to move under Linux. I'm thinking about write some logic in .NET (I'm skilled with this) and use it in PHP. Do you think it's crazy? Do you have some advise? Thanks – Marco Apr 18 '12 at 15:05
  • @Marco a bit crazy? Yes :). My advice is to pick a single platform (php or .NET) and stick with it for the entire project. Or at least keep the UI in php and make calls to an ASP.NET web service layer. Mixing the two together sounds like trouble. – jrummell Apr 18 '12 at 16:49
  • @jrummell: yes, probably you're right. I'm still searching my way and I'm in a mess because PHP is standard and you can use everywhere, while ASP no; using Mono I can run .NET apps under Linux and ASP pages too. Using PHP for UI and continuosly call webservice layer developed in ASP is an option I've already thought, but it's nor "light" nor fast. Don't know, gotta think about it. Anyway thanks for your opinion that I agree with :) – Marco Apr 18 '12 at 16:53

2 Answers2

7

According to this bug report the DOTNET class is not loading .NET 4.0 DLLs. If you're not using any of the new libraries in .NET 4.0 you can target your to .NET 3.5 or lower by opening the project properties and on the "Application" tab change the "Target framework" to ".NET Framework 3.5 Client Profile"

Now when you install your DLL into the GAC it will get installed into the CLR 2.0 GAC and should be able to be loaded using the DOTNET class in PHP.

heavyd
  • 17,303
  • 5
  • 56
  • 74
6

There is a library out there called NetPhp (https://github.com/david-garcia-garcia/netphp) that will let you:

  • Use any .Net binaries (even without COM Visibility) and ANY version of the .Net framework including CLR4
  • Dump a PHP class model
  • Iterate over .Net collections directly from PHP PHP class model generation, to use PHP classes as if it where .Net Automatic propagation of .Net errors into native PHP exceptions that can be properly handled
  • Acces native enums and static methods
  • Use class constructors with parameters
  • Debug .Net and PHP code at the same time as if it was a single application.

There is a project with code samples here:

https://github.com/david-garcia-garcia/netphp-sample

This is what a piece of code with NetPhp looks like:

$datetime = $runtime->TypeFromName("System.DateTime");
$datetime->Instantiate();

echo $datetime->ToShortDateString()->Val(); // Outputs 01/01/0001

// We can only use Int32 from native PHP, so parse
// an Int64 that is equivalent to (long) in the DateTime constructor.
$ticks = $runtime->TypeFromName("System.Int64")->Parse('98566569856565656');
$ticks = \ms\System\netInt64::_Parse('98566569856565656');

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

$now = $runtime->TypeFromName("System.DateTime")->Now;
echo $now->ToShortDateString()->Val(); // Outputs "23/10/2015"

$now = $runtime->TypeFromName("System.DateTime")->Now();
echo $now->ToShortDateString()->Val(); // Outputs "23/10/2015"

$timer = $runtime->TypeFromName("System.Timers.Timer")->Instantiate();
$timer->AutoReset(TRUE);
$timer->AutoReset = TRUE;
Juan Elias
  • 81
  • 1
  • 1