PHP DOTNET() not able to load from "System" assembly - php

Trying to use the Microsoft's .NET classes from System.Security.Cryptography.X509Certificates located in System assembly raises the following error:
$certificate2 = new DOTNET('System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089', 'System.Security.Cryptography.X509Certificates.X509Certificate2');
com_exception: Failed to instantiate .Net object [Unwrapped, QI for IDispatch] [0x80004002] No such interface supported
in ...\test.php on line 2
Whereas the following calls do work and return DOTCOM instances.
$certificate = new DOTNET('mscorlib', 'System.Security.Cryptography.X509Certificates.X509Certificate');
$form = new DOTNET('System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089', 'System.Windows.Forms.Form');
Is there something special to System.dll or its classes contained in System.Security.Cryptography.X509Certificates?
Why could this file or classes not be usable?
digging deeper
The Exception origins to a failed method call in php_dotnet extension source code, line 250. But this is too low level for me. The call is:
hr = IUnknown_QueryInterface(V_UNKNOWN(&unwrapped), &IID_IDispatch, &V_DISPATCH(&obj->v));
side notes
PHP version is 5.5.5
this happens on a Windows 7 and Windows Server 2008 R2 box
the assembly seems to accessed correctly, but classes can not be found
selected .NET Framework Version is 2.0.0.0 (<=3.5), because PHP DOTNET does not work with Version >= 4
Cryptography classes from mscorlib do not suffice, because of limited functionality

Try this.It's working for me
<?php
$stack = new DOTNET("mscorlib", "System.Collections.Stack");
$stack->Push(".Net");
$stack->Push("Hello ");
echo $stack->Pop() . $stack->Pop();
?>
The link for the doc, Click here

Related

Working with the latest PHP / MongoDB version

After much of a struggle I managed to install MongoDB as a service and WAMP. Then on start I got a fatal error saying these would not work:
$m = new Mongo(...);
$m = new MongoClient(...);
In some previous questions on SO people mentioned using a new class called MongoDB/Driver/Manager. I also came across something called MongoDB/Client.
As a beginner to MongoDB I now stand rather confused about how to use/connect to a DB and collection.
I guess I will use:
$m = new MongoDB/Driver/Manager(...);
However,
$db = $m->$dbname; // Seems to cause -> Notice: Undefined Property
$collection = $db->shows; // dito
So all in all what are the difference between MongoDB/Driver/Manager and MongoDB/Client ? And with these new classes how would I correctly connect to a DB or Collection as shown in the previous snippet ? I can't seem to find many examples explaining how to use these new classes, or an up to date correct way of using the new classes for basic functionality.
Thanks,
I think I understand what I am confusing.
Using the MongoDB/Driver/Manager class and others, are part of the basic tools available with the PHP MongoDB Driver. I am guessing it is not recommended using them unless you know what you are doing, or you want something relatively customized.
A more recommendable alternative is to install "mongodb/mongodb-^1.x.x" with a PHP installer such as Composer, which will give you a MongoDB Library. This will give you classes such as the MongoDB/Client class.
Once the library has been installed you can connect like so:
<?php
require 'vendor/autoload.php';
$client = new MongoDB/Client('mongodb://localhost:27017');
// Add URI of MongoDB here
$mydb = $client->mydb; // Add the new DB name or existing DB name here
$collection = $mydb->createCollection('userCollection');
...
?>

Determining assembly name for use with PHP DOTNET

I am trying to use Microsoft's Speech Platform 11 through PHP's DOTNET object
https://msdn.microsoft.com/en-us/library/jj127858.aspx
The platform should be instantiated as follows
$platform = new DOTNET("assembly-name", "Microsoft.Speech.Recognition");
But how to retrieve the assembly name for Speech Platform 11? (to replace "assembly-name" in the initialization call)
I have tried several assembly names by... guesswork, obviously with no luck.
The initialization error being thrown
Failed to instantiate .Net object [CreateInstance] [0x80070002] The system cannot find the file specified
UPDATE
With the following code, I was able to get PHP to find and use the assembly
$full_assembly_string = 'Microsoft.Speech, Version=11.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35';
$full_class_name = 'Microsoft.Speech.Recognition.SpeechRecognitionEngine';
$interface = new DOTNET($full_assembly_string, $full_class_name);
However, there's a new roadblock:
Failed to instantiate .Net object [Unwrapped, QI for IDispatch] [0x80004002] No such interface supported
At first glance it seems it has to do with COM visibility. But if for any reason the class isn't visible to COM (and it seems odd), how to change this? Is it even possible?
Not tested. Just another guess.
According to the Microsoft Speech Platform SDK 11 Docs:
https://msdn.microsoft.com/en-us/library/microsoft.speech.recognition.speechrecognitionengine.aspx
i would give this a try:
"assembly" Microsoft.Speech
"classname" Microsoft.Speech.Recognition.SpeechRecognitionEngine
Microsoft.Speech.Recognition is only the namespace
$sre = new DOTNET(
'Microsoft.Speech',
'Microsoft.Speech.Recognition.SpeechRecognitionEngine'
);
Methods are documented here: https://msdn.microsoft.com/en-us/library/microsoft.speech.recognition.speechrecognitionengine_members(v=office.14).aspx#Anchor_2

Where is the tutorial "processor" generated?

I just started working with the github hosted build of apache thrift, I am basically interested in a java client and PHP server implementation, but for now i am using the php server and client only
All nice and easy i made my thrift file
namespace php mobiledata
struct sms
{
1: string from,
2: string to,
3: string smstext,
4: string smsdatetime,
5: string smsdirection
}
struct smsdetails
{
1: list<sms> smsdata
}
service mobiledataservice
{
void insertsmsdata (1: smsdetails smslist)
}
And I generated the gen-php folder, which has got Types.php and mobiledataservice.php
the basic sample that comes with the github for php as server shows a line of code
$handler = new CalculatorHandler();
$processor = new \tutorial\CalculatorProcessor($handler);
I can't find this class "CalculatorProcessor" and certainly I don't have a comparative class generated in my gen_php like mobiledataprocessor, and it baffles me as to how I would run my server in absence of processor.
The server code is generated by calling
thrift -r -gen php:server tutorial.thrift
Note the :server part after -gen php, this triggers the processor generation.
These are all PHP options available:
php (PHP):
inlined: Generate PHP inlined files
server: Generate PHP server stubs
oop: Generate PHP with object oriented subclasses
rest: Generate PHP REST processors

Trouble using DOTNET from PHP.

I've been trying to call a .net assembly from PHP through com (using DOTNET()). It seems like php is finding the DLL and initializing properly, but I can't see/use the methods for some reason. Anyone know how I might be able to fix this?
Here is the php code I'm using to call the .net class. When I call it the output is "hello1 hello2". When I try to directly call the function by doing $csclass->ModelBuilder("","") I get a 500 server error specifying that it couldn't find the function.
<?php
echo "hello1";
try{
$csclass = new DOTNET("ModelBuilder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1208136d23b48dc5",
"ModelBuilder.ModelBuilder2");
$class_methods = get_class_methods($csclass);
foreach ($class_methods as $method_name) {
echo "$method_name\n";
}
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}
echo "hello2";
?>
Here is the the class in the assembly I'm trying to call (built using .net 3.5, signed with a strong name, and registered with gacutil):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using OfficeOpenXml;
using System.Runtime.InteropServices;
namespace ModelBuilder
{
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
public class ModelBuilder2
{
[ComVisible(true)]
public Boolean BuildModel(String outputFileLoc,String excelTemplateFile)
{
try
{
//do stuff
return true;
}
catch (Exception e)
{
return false;
}
}
}
The get_class_methods() will not work with a Dotnet class object. That thing is a proxy, and it does not behave the way a normal php object does.
If you really are focused on listing the methods of the object, then you need to look into implementing IDispatch on your .NET object. If, however, your main goal is to simply use the .NET object, and your attempt to list the methods was just a side effort to diagnose why that was not working, then I have some suggestions for you.
rather than using gacutil, consider whether you can insert the required DLL into the php directory, the place where php.exe resides. If php.exe resides at c:\php5\php.exe, then
copy your assembly into c:\php5.
If you follow the above suggestion, the .NET assembly need not be strongly named. It needs to be strongly named if you plan to GAC it. As I said, you don't need to GAC it, in order to load it with php. If you copy the assembly into the PHP dir, then you can use an un-signed assembly.
For early development and exploration with this, use the php.exe program from the command-line, rather than using IIS to launch php via a web request. This lets you see the error messages directly, rather than worrying about 500 errors from IIS.
Example
Suppose this is the C# code:
using System;
namespace Ionic
{
public class MathEx
{
System.Random rnd;
public MathEx ()
{
rnd = new System.Random();
}
public int RandomEven()
{
return rnd.Next()*2;
}
}
}
Compile it from the command-line like this:
c:\net3.5\csc.exe /t:library /out:Ionic.MathEx.dll MathEx.cs
copy the assembly to the dir that holds php.exe:
copy Ionic.MathEx.dll \php
1 file(s) copied.
Then, suppose I have a php script named mathex.php with these contents:
<?php
$my_assembly = 'Ionic.MathEx'; // name of the dll without the .dll suffix
$clz = new DOTNET($my_assembly, 'Ionic.MathEx');
for ($i=0; $i<5; $i++) {
echo $i . " " . $clz->RandomEven() . "\n";
}
?>
... and if I run it from the command line this way:
\php\php.exe mathex.php
...then I get these results:
0 -1083602762
1 1535669896
2 -86761710
3 -1204365564
4 459406052
Nota Bene
I tried doing this with an assembly compiled with .NET 4.0, but it did not work, giving me an error message about a .NET runtime mismatch. Like this:
Fatal error: Uncaught exception 'com_exception' with message 'Failed to instantiate .Net object
[CreateInstance] [0x8013101b] ' in C:\dev\php\mathEx.php:6
Stack trace:
#0 C:\dev\php\mathEx.php(6): dotnet->dotnet('Ionic.MathEx', 'Ionic.MathEx')
#1 {main}
thrown in C:\dev\php\mathEx.php on line 6
The 0x8013101b indicates a runtime mismatch - the runtime version of the assembly does not match the runtime version of the app that is trying to load the assembly.
From this I conclude that php5 is compiled to support .NET 2.0 (which includes 3.0 and 3.5). The runtime version changed for .NET 4.0, so assemblies that you compile with a .NET 4.0 compiler (including VS2010) will not be usable with php5.exe. The workaround is to just compile with the .NET 2.0 or 3.5 compiler (VS2005, vs2008).

PHP Lucene - Indexation - Fails in Linux after 2.000.000 system blocks

I have been working on creating an index using Zend Framework latest version. The interface is working fine and everything else.
The problem I have now is the "re-indexation" or creation of the index. I have checked everything else, sanitizing the data and double checking the quality of the data.
The Process always stops at most likely record 15.000 and the limit on the index dir of 2.000.000. That I decided to build an application compiled in java with version lucene3.0.3 to run the indexation.
Fatal error: Uncaught exception 'Zend_Search_Lucene_Exception' with message 'Unsupported segments file format' in
It seems the latest format used by Zend Lucene is 2.3
Any ideas how to solve this problem, I really appreciate your input
I have no experience with this. But on the zend lucene website they state that the currently supported lucene index version is 2.3. It might be the case that version 3.0.3 is not fully supported.
[1] The currently supported Lucene index file format version is 2.3 (starting from Zend Framework 1.6).
See: http://framework.zend.com/manual/en/zend.search.lucene.java-lucene.html
I customized the example of this site http://www.techcrony.info/?p=33, this example reads text files from a data dir. So, the new customized functions need to read the info from the MySQL database:
public static void main(String[] args) throws Exception
{....System.out.print("Index dir arg_0 : " + indexDir + "\r");
String id ="%";
long start = new Date().getTime();
int numIndexed = index_main(indexDir, id);
long end = new Date().getTime();
System.out.print("End Program... \r");
}
private static int index_main(File indexDir, String id )throws IOException {
int numIndexed = 0;
try{
IndexWriter writer =
new IndexWriter(indexDir, new StandardAnalyzer(), true);
writer.setUseCompoundFile(false);
java.sql.Connection conn = linktodata();
int rowCount = 0;
...
As you can see I used the lucene-core-2.3.0.jar
javac -cp .:lucene-core-2.3.0.jar:mysql-connector-java-5.1.16-bin.jar Indexer.java
Run:
java -cp .:lucene-core-2.3.0.jar:mysql-connector-java-5.1.16-bin.jar Indexer /home/public_html/index_main
Now the most important question, is anyone aware if PHP lucene is able to manage more than 1.000.000 documents?

Categories