php and com

39
PHP and COM Wez Furlong <[email protected] >

Upload: wez-furlong

Post on 05-Dec-2014

15.611 views

Category:

Technology


2 download

DESCRIPTION

A discussion of the OLE/COM bridge in PHP 5. These slides are from 2004. I\'m hoping that SlideShare preserves the speakers notes; there\'s a good deal of information in there to complement the slide content.

TRANSCRIPT

Page 1: PHP and COM

PHP and COMWez Furlong

<[email protected]>

Page 2: PHP and COM

Plan

• What is COM?

• What's it good for?

• How do I use it?

• Instantiation... and Monikers

• Exceptions

• Typelibraries

• Variants

• .Net Interop

• ActiveScript

• Persistence (experimental)

Page 3: PHP and COM

Common Object Model

• Frequently mislabeled asComponent Object Model

• Specifies programming interfaces for OO code

• Those interfaces are programming language independent

• Provides a mechanism for code re-use

Page 4: PHP and COM

OLE

• A subset of these interfaces are collectively known as OLE:Object Linking and Embedding

• They define a way to dynamically create and invoke methods on objects that implement those interfaces

• PHP COM is really PHP OLE

Page 5: PHP and COM

COM Servers

• A COM Server is some module that exposes a COM interface via creatable classes

• In-Proc (DLL) => fast

• Out-of-Proc (EXE) => not so fast

• DCOM => on another machine

• Your code sees these as the same thing

Page 6: PHP and COM

What's it good for?

• Talking to other applications and libraries

• Most win32 software vendors provide a COM interface

• Can be used to transition from ASP to PHP

• Can use “easy” languages to extend PHP

Page 7: PHP and COM

How do I use it?

$word = new COM(“Word.Application”);$word->visible = true;$word->Documents->Add();$word->Selection->TypeText(“hello”);$word->ActiveDocument->SaveAs(“test.doc”);$word->Quit();

Page 8: PHP and COM

Instantiation

$word = new COM(“Word.Application”, array( ‘Server’ => ‘otherbox’, ‘Username’ => ‘foo’, ‘Password’ => ‘bar’ ), CP_UTF8);

Page 9: PHP and COM

Exceptions

try { $o = new COM(“…”);} catch (com_exception $e) { print “failed to create: $e”;}

$e->getCode() corresponds to weird hex number (will show example later)

Page 10: PHP and COM

Typelibraries

• Import constants from a COM server as regular PHP constants.

• Manually

• com_load_typelib(‘Word.Application’);

• echo wdGoToBookmark;

• From php.ini:

• com.typelib_file=C:\mytypelibs.txt

Page 11: PHP and COM

Variants

• PHP COM is really PHP Variant

• Variant is win32 equivalent of PHP typeless variables

• JIT conversion in PHP 5

• OLE default properties

• $doc = $word->ActiveDocument;

• print $doc; // prints document title

Page 12: PHP and COM

Variant Arrays

$user = new COM( “LDAP://cn=user,ou=test,dc=php,dc=net”);

$arr = $user->GetEx(“otherHomePhone”);

for ($i = 0; $i < count($arr); $i++) { print $arr[$i] . “\n”;}

Page 13: PHP and COM

Iterators

Set domainObject = GetObject("WinNT://Domain")

For Each obj in domainObject Response.Write obj.Name & "<br />“Next

$domainObject = new COM("WinNT://Domain");

foreach ($domainObject as $obj) { echo $obj->Name . "<br />";}

Page 14: PHP and COM

Variant Functions

• Arithmetic

• variant_add variant_sub

• variant_mul variant_div

• Casting

• variant_set_type (VT_BSTR etc.)

• variant_get_type

• variant_date_from_timestamp

• variant_date_to_timestamp

• VB-like behaviour

Page 15: PHP and COM

.Net Interop

.Net is modern replacement for VB

Uses similar concepts to COM

MS provide an “Interop” layer to map .Net assemblies into COM

$stack = new DOTNET(‘mscorlib’, ‘System.Collections.Stack’);

$stack->push(‘.Net’);

$stack->Push(‘Hello ’);

echo $stack->pop() . $stack->pop();

Page 16: PHP and COM

Some Sample Scripts

• Look at some common tasks implemented in PHP

• Gotchas?

Page 17: PHP and COM

WMI for system monitoring

$wmi = new COM( “WinMgmts:{impersonationLevel=impersonate}” .“//{$hostname}/root/cimv2”);

$cpus = $wmi->ExecQuery( "Select * from Win32_Processor");

foreach ($cpus as $cpu) { printf(“%s %dMHz %d%%\n”, $cpu->Name, $cpu->MaxClockSpeed, $cpu->LoadPercentage);}

Page 18: PHP and COM

ADO DB

Useful for transitioning ASP

Often faster to use odbc or native drivers

$conn = new COM(‘ADODB.Connection’);$conn->Open($dsn);$conn->Execute(‘update …’);

$rs = new COM(‘ADODB.Recordset’);$rs->Open(‘select foo from bar’, $conn);

while (!$rs->EOF()) { echo $rs->Fields(‘foo’); $rs->MoveNext();}

Page 19: PHP and COM

MS Office (Word)

$word = new COM(“Word.Application”);

$word->visible = true;

$word->Documents->Add();

$word->Selection->TypeText(“hello ” . $_SESSION[‘username’]);

$word->ActiveDocument->SaveAs(“test.doc”);

$word->Quit();

Page 20: PHP and COM

Shmop mutex

• Use a single instance of Word

• Use mutex to control access to it

• extension=php_shmop.dll

• Need to be running ISAPI or Apache module on win2k and later

Page 21: PHP and COM

Shmop mutex 2

function try_mutex($timeout) { $t = time(); do { $mtx = shmop_open(42, “cwn”, 0644, 1); if ($mtx) return $mtx; usleep(200000); // 0.2 seconds } while (time() < $t + $timeout); return false;}

function drop_mutex($mtx) { shmop_delete($mtx);}

Page 22: PHP and COM

Shmop mutex 3

com_get_active_object() returns a handle to an instance from the Running Object Table

function get_one() { try { $w = com_get_active_object(‘Word.Application’); return $w; } catch (com_exception $e) { if ($e->getCode() == MK_E_UNAVAILABLE) return new COM(‘Word.Application’); throw $e; }}

Page 23: PHP and COM

Shmop mutex 4

$mtx = try_mutex(3);if (!$mtx) { .. Try again later … }$word = get_one();$word->Documents->Add();$word->Selection->TypeText(“foo”);$word->ActiveDocument->SaveAs($filename);$word->ActiveDocument->Close();drop_mutex($mtx);readfile($filename);

Page 24: PHP and COM

Create a server app

• The shmop idea is prone to failure if something bad happens to a request that holds the mutex

• An alternative is to run a separate process as a tcp server and queue requests to it

• PHP 5 makes this easy

Page 25: PHP and COM

Client for Word Daemon

$daemon = stream_socket_client(‘127.0.0.1:4000’);

if ($daemon) {

fwrite($daemon, serialize($data));

$result = fgets($daemon);

}

Page 26: PHP and COM

Word Daemon

$w = new COM(‘Word.Application’);$s = stream_socket_server(‘127.0.0.1:4000’);while (true) { $client = stream_socket_accept($s); $data = unserialize(stream_get_contents($client)); generate_word_doc($data); fwrite($client, “DONE\r\n”); fclose($client);}

Page 27: PHP and COM

With Events

• COM event handling framework is build from ‘Connection Points’

• A source object is implements IConnectionPointContainer

• A sink object (callback handler) implements a dispinterface

• dispinterfaces allow a loose handler implementation; perfect for scripting languages

Page 28: PHP and COM

turning on events

bool com_event_sink($object,

$sinkobject [, $sinkname]);

Plumbs in event handling;

Events from $object are sunk into $sinkobject

Page 29: PHP and COM

Sinking events from IE

$ie = new COM("InternetExplorer.Application");

$ie->Visible = true;

$ie->Navigate("http://www.php.net");

Page 30: PHP and COM

IE Events 2

class IEEvents { var $dom = null; function DocumentComplete($dom, $url) { echo “$url complete\n”; $this->dom = $dom; }}

Page 31: PHP and COM

IE Events 3

$sink = new IEEvents;$ie = new COM("InternetExplorer.Application");$ie->Visible = true;com_event_sink($ie, $sink, ‘DWebBrowserEvents2’);$ie->Navigate("http://www.php.net");while (!$sink->dom) { com_message_pump(4000);}

// we can do stuff with $sink->dom here, or just continue with something else

Page 32: PHP and COM

IActiveScript

• A set of interfaces that abstract scripting engines

• A compatible host can run any compliant script engine

• Works in both directions; you can load engines in php, and you can load php into other hosts

Page 33: PHP and COM

Invoke JScript from PHP

class foo { function bar($msg) { echo $msg; }}

$js = new COM(‘ScriptControl’);$js->Language = ‘JScript’;$js->AddObject(‘foo’, new foo, false);$js->AddCode(‘foo.bar(“js!”);’);

Page 34: PHP and COM

ActiveScript

• This SAPI lets you load PHP into other scripting engines

• You need to regsvr32 php5activescript.dll to enable it

• Language = PHPScript

• Sadly, can't load PHP into PHP via COM due to architecture of PHP SAPI interface

Page 35: PHP and COM

Using PHP in Windows Script Host

Create a .wsf file like this:

<job id="test"> <script language="PHPScript"> $WScript->Echo("Hello"); </script></job>

cscript test.wsf

Page 36: PHP and COM

Persistence Helper

• Not everything supports the relevant interfaces, so not totally useful

• Intention is to persist object state into streams or strings and store it into some kind of DB.

• PHP streams are mapped as COM IStreams

Page 37: PHP and COM

Bogus Example

$object = new COM(‘…’);$object->doSomething();$dest = fopen(‘ftp://…/…’, ‘wb’);$p = new COMPersistHelper($object);$p->SaveToStream($dest);

Page 38: PHP and COM

Bogus Example 2

$object = new COM(‘…’);$src = fopen(‘ftp://…/…’, ‘rb’);$p = new COMPersistHelper($object);$p->LoadFromStream($src);

// $object is now in same state as it was on previous slide

Page 39: PHP and COM

Resources

• These slides are on my blog and on slideshare.nethttp://netevil.org

• PHP COM manual:http://www.php.net/manual/en/ref.com.php

• WMI:http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/wmi_start_page.asp

• Server-side MS Office:http://support.microsoft.com/default.aspx?scid=kb;EN-US;q257757

• PHP snapshotshttp://snaps.php.net