PHP and COM <ul><li>Wez Furlong < [email_address] > </li></ul>
Plan <ul><li>What is COM? </li></ul><ul><li>What's it good for? </li></ul><ul><li>How do I use it? </li></ul><ul><ul><li>I...
Common Object Model <ul><li>Frequently mislabeled as Component Object Model </li></ul><ul><li>Specifies programming interf...
OLE <ul><li>A subset of these interfaces are collectively known as OLE: Object Linking and Embedding </li></ul><ul><li>The...
COM Servers <ul><li>A COM Server is some module that exposes a COM interface via creatable classes </li></ul><ul><li>In-Pr...
What's it good for? <ul><li>Talking to other applications and libraries </li></ul><ul><li>Most win32 software vendors prov...
How do I use it? <ul><li>$word = new COM(“Word.Application”); $word->visible = true; $word->Documents->Add(); $word->Selec...
Instantiation <ul><li>$word = new COM(“Word.Application”,   array(   ‘Server’  => ‘otherbox’,   ‘Username’ => ‘foo’,   ‘Pa...
Exceptions <ul><li>try {   $o = new COM(“…”); } catch (com_exception $e) {   print “failed to create: $e”; } </li></ul><ul...
Typelibraries <ul><li>Import constants from a COM server as regular PHP constants. </li></ul><ul><li>Manually </li></ul><u...
Variants <ul><li>PHP COM is really PHP Variant </li></ul><ul><li>Variant is win32 equivalent of PHP typeless variables </l...
Variant Arrays <ul><li>$user = new COM(   “LDAP://cn=user,ou=test,dc=php,dc=net”); </li></ul><ul><li>$arr = $user->GetEx(“...
Iterators <ul><li>Set domainObject = GetObject(&quot;WinNT://Domain&quot;) </li></ul><ul><li>For Each obj in domainObject ...
Variant Functions <ul><li>Arithmetic </li></ul><ul><ul><li>variant_add variant_sub </li></ul></ul><ul><ul><li>variant_mul ...
.Net Interop <ul><li>.Net is modern replacement for VB </li></ul><ul><li>Uses similar concepts to COM </li></ul><ul><li>MS...
Some Sample Scripts <ul><li>Look at some common tasks implemented in PHP </li></ul><ul><li>Gotchas? </li></ul>
WMI for system monitoring <ul><li>$wmi = new COM(   “WinMgmts:{impersonationLevel=impersonate}”   .“//{$hostname}/root/cim...
ADO DB <ul><li>Useful for transitioning ASP </li></ul><ul><li>Often faster to use odbc or native drivers </li></ul><ul><li...
MS Office (Word) <ul><li>$word = new COM(“Word.Application”); </li></ul><ul><li>$word->visible = true; </li></ul><ul><li>$...
Shmop mutex <ul><li>Use a single instance of Word </li></ul><ul><li>Use mutex to control access to it </li></ul><ul><li>ex...
Shmop mutex 2 <ul><li>function try_mutex($timeout) {   $t = time();   do {   $mtx = shmop_open(42, “cwn”, 0644, 1);   if (...
Shmop mutex 3 <ul><li>com_get_active_object() returns a handle to an instance from the Running Object Table </li></ul><ul>...
Shmop mutex 4 <ul><li>$mtx = try_mutex(3); if (!$mtx) { .. Try again later … } $word = get_one(); $word->Documents->Add();...
Create a server app <ul><li>The shmop idea is prone to failure if something bad happens to a request that holds the mutex ...
Client for Word Daemon <ul><li>$daemon = stream_socket_client(‘127.0.0.1:4000’); </li></ul><ul><li>if ($daemon) { </li></u...
Word Daemon <ul><li>$w = new COM(‘Word.Application’); $s = stream_socket_server(‘127.0.0.1:4000’); while (true) {   $clien...
With Events <ul><li>COM event handling framework is build from ‘Connection Points’ </li></ul><ul><li>A source object is im...
turning on events <ul><li>bool com_event_sink($object, </li></ul><ul><li>$sinkobject  [, $sinkname]); </li></ul><ul><li>Pl...
Sinking events from IE <ul><li>$ie = new COM(&quot;InternetExplorer.Application&quot;); </li></ul><ul><li>$ie->Visible = t...
IE Events 2 <ul><li>class IEEvents {   var $dom = null;   function DocumentComplete($dom, $url) {   echo “$url complete
”;...
IE Events 3 <ul><li>$sink = new IEEvents; $ie = new COM(&quot;InternetExplorer.Application&quot;); $ie->Visible = true; co...
IActiveScript <ul><li>A set of interfaces that abstract scripting engines </li></ul><ul><li>A compatible host can run any ...
Invoke JScript from PHP <ul><li>class foo {   function bar($msg) { echo $msg; } } </li></ul><ul><li>$js = new COM(‘ScriptC...
ActiveScript <ul><li>This SAPI lets you load PHP into other scripting engines </li></ul><ul><li>You need to regsvr32 php5a...
Using PHP in Windows Script Host <ul><li>Create a .wsf file like this:  </li></ul><ul><li><job id=&quot;test&quot;>   <scr...
Persistence Helper <ul><li>Not everything supports the relevant interfaces, so not totally useful </li></ul><ul><li>Intent...
Bogus Example <ul><li>$object = new COM(‘…’); $object->doSomething(); $dest = fopen(‘ftp://…/…’, ‘wb’); $p = new COMPersis...
Bogus Example 2 <ul><li>$object = new COM(‘…’); $src = fopen(‘ftp://…/…’, ‘rb’); $p = new COMPersistHelper($object); $p->L...
Resources <ul><li>These slides are on my blog and on slideshare.net http://netevil.org </li></ul><ul><li>PHP COM manual: h...
Upcoming SlideShare
Loading in...5
×

PHP and COM

15,119

Published on

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.

Published in: Technology
31 Comments
5 Likes
Statistics
Notes
  • Is there a way to use this OCX in PHP? or can i wrap it in a way? please if you can provide an example
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • I was reading the posts you have stated, I am facing a problem with COM and OCX, the issue is that the OCX i am using is provided with PSDispatch (Proxy for Dispinterface), whenever i call functions from this OCX using PHP/COM i get PHP Fatal error: Uncaught exception 'com_exception' with message 'Error [0x8000ffff] Catastrophic failure
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Hi,
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • The cool thing is that you can persist (and restore) the object state into any PHP compatible stream.
    So, we’ve dumped the object state onto an ftp site here, but could have stored it into a memory stream or some kind of db stream or …

    Bogus because I don’t have a practical use for it (only common COM object that supports IPersist is the MSXML stuff; you can save to file from there using native API (but not to PHP streams so…)
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Can load into any activescript host; Windows Scripting Host, ASP, the ScriptControl we used earlier, the WeaverSlave IDE, Kapsules desktop widget application
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total Views
15,119
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
319
Comments
31
Likes
5
Embeds 0
No embeds

No notes for slide
  • PHP and COM

    1. 1. PHP and COM <ul><li>Wez Furlong < [email_address] > </li></ul>
    2. 2. Plan <ul><li>What is COM? </li></ul><ul><li>What's it good for? </li></ul><ul><li>How do I use it? </li></ul><ul><ul><li>Instantiation... and Monikers </li></ul></ul><ul><ul><li>Exceptions </li></ul></ul><ul><ul><li>Typelibraries </li></ul></ul><ul><ul><li>Variants </li></ul></ul><ul><ul><li>.Net Interop </li></ul></ul><ul><ul><li>ActiveScript </li></ul></ul><ul><ul><li>Persistence (experimental) </li></ul></ul>
    3. 3. Common Object Model <ul><li>Frequently mislabeled as Component Object Model </li></ul><ul><li>Specifies programming interfaces for OO code </li></ul><ul><li>Those interfaces are programming language independent </li></ul><ul><li>Provides a mechanism for code re-use </li></ul>
    4. 4. OLE <ul><li>A subset of these interfaces are collectively known as OLE: Object Linking and Embedding </li></ul><ul><li>They define a way to dynamically create and invoke methods on objects that implement those interfaces </li></ul><ul><li>PHP COM is really PHP OLE </li></ul>
    5. 5. COM Servers <ul><li>A COM Server is some module that exposes a COM interface via creatable classes </li></ul><ul><li>In-Proc (DLL) => fast </li></ul><ul><li>Out-of-Proc (EXE) => not so fast </li></ul><ul><li>DCOM => on another machine </li></ul><ul><li>Your code sees these as the same thing </li></ul>
    6. 6. What's it good for? <ul><li>Talking to other applications and libraries </li></ul><ul><li>Most win32 software vendors provide a COM interface </li></ul><ul><li>Can be used to transition from ASP to PHP </li></ul><ul><li>Can use “easy” languages to extend PHP </li></ul>
    7. 7. How do I use it? <ul><li>$word = new COM(“Word.Application”); $word->visible = true; $word->Documents->Add(); $word->Selection->TypeText(“hello”); $word->ActiveDocument->SaveAs(“test.doc”); $word->Quit(); </li></ul>
    8. 8. Instantiation <ul><li>$word = new COM(“Word.Application”, array( ‘Server’ => ‘otherbox’, ‘Username’ => ‘foo’, ‘Password’ => ‘bar’ ), CP_UTF8); </li></ul>
    9. 9. Exceptions <ul><li>try { $o = new COM(“…”); } catch (com_exception $e) { print “failed to create: $e”; } </li></ul><ul><li>$e->getCode() corresponds to weird hex number (will show example later) </li></ul>
    10. 10. Typelibraries <ul><li>Import constants from a COM server as regular PHP constants. </li></ul><ul><li>Manually </li></ul><ul><ul><li>com_load_typelib(‘Word.Application’); </li></ul></ul><ul><ul><li>echo wdGoToBookmark; </li></ul></ul><ul><li>From php.ini: </li></ul><ul><ul><li>com.typelib_file=C:mytypelibs.txt </li></ul></ul>
    11. 11. Variants <ul><li>PHP COM is really PHP Variant </li></ul><ul><li>Variant is win32 equivalent of PHP typeless variables </li></ul><ul><li>JIT conversion in PHP 5 </li></ul><ul><li>OLE default properties </li></ul><ul><ul><li>$doc = $word->ActiveDocument; </li></ul></ul><ul><ul><li>print $doc; // prints document title </li></ul></ul>
    12. 12. Variant Arrays <ul><li>$user = new COM( “LDAP://cn=user,ou=test,dc=php,dc=net”); </li></ul><ul><li>$arr = $user->GetEx(“otherHomePhone”); </li></ul><ul><li>for ($i = 0; $i < count($arr); $i++) { print $arr[$i] . “ ”; } </li></ul>
    13. 13. Iterators <ul><li>Set domainObject = GetObject(&quot;WinNT://Domain&quot;) </li></ul><ul><li>For Each obj in domainObject Response.Write obj.Name & &quot;<br />“ Next </li></ul><ul><li>$domainObject = new COM(&quot;WinNT://Domain&quot;); </li></ul><ul><li>foreach ($domainObject as $obj) { echo $obj->Name . &quot;<br />&quot;; } </li></ul>
    14. 14. Variant Functions <ul><li>Arithmetic </li></ul><ul><ul><li>variant_add variant_sub </li></ul></ul><ul><ul><li>variant_mul variant_div </li></ul></ul><ul><li>Casting </li></ul><ul><ul><li>variant_set_type (VT_BSTR etc.) </li></ul></ul><ul><ul><li>variant_get_type </li></ul></ul><ul><ul><li>variant_date_from_timestamp </li></ul></ul><ul><ul><li>variant_date_to_timestamp </li></ul></ul><ul><li>VB-like behaviour </li></ul>
    15. 15. .Net Interop <ul><li>.Net is modern replacement for VB </li></ul><ul><li>Uses similar concepts to COM </li></ul><ul><li>MS provide an “Interop” layer to map .Net assemblies into COM </li></ul><ul><li>$stack = new DOTNET(‘mscorlib’, ‘System.Collections.Stack’); </li></ul><ul><li>$stack->push(‘.Net’); </li></ul><ul><li>$stack->Push(‘Hello ’); </li></ul><ul><li>echo $stack->pop() . $stack->pop(); </li></ul>
    16. 16. Some Sample Scripts <ul><li>Look at some common tasks implemented in PHP </li></ul><ul><li>Gotchas? </li></ul>
    17. 17. WMI for system monitoring <ul><li>$wmi = new COM( “WinMgmts:{impersonationLevel=impersonate}” .“//{$hostname}/root/cimv2” ); </li></ul><ul><li>$cpus = $wmi->ExecQuery( &quot;Select * from Win32_Processor&quot;); </li></ul><ul><li>foreach ($cpus as $cpu) { printf(“%s %dMHz %d%% ”, $cpu->Name, $cpu->MaxClockSpeed, $cpu->LoadPercentage); } </li></ul>
    18. 18. ADO DB <ul><li>Useful for transitioning ASP </li></ul><ul><li>Often faster to use odbc or native drivers </li></ul><ul><li>$conn = new COM(‘ADODB.Connection’); $conn->Open($dsn); $conn->Execute(‘update …’); </li></ul><ul><li>$rs = new COM(‘ADODB.Recordset’); $rs->Open(‘select foo from bar’, $conn); </li></ul><ul><li>while (!$rs->EOF()) { echo $rs->Fields(‘foo’); $rs->MoveNext(); } </li></ul>
    19. 19. MS Office (Word) <ul><li>$word = new COM(“Word.Application”); </li></ul><ul><li>$word->visible = true; </li></ul><ul><li>$word->Documents->Add(); </li></ul><ul><li>$word->Selection->TypeText(“hello ” . $_SESSION[‘username’]); </li></ul><ul><li>$word->ActiveDocument->SaveAs(“test.doc”); </li></ul><ul><li>$word->Quit(); </li></ul>
    20. 20. Shmop mutex <ul><li>Use a single instance of Word </li></ul><ul><li>Use mutex to control access to it </li></ul><ul><li>extension=php_shmop.dll </li></ul><ul><li>Need to be running ISAPI or Apache module on win2k and later </li></ul>
    21. 21. Shmop mutex 2 <ul><li>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; } </li></ul><ul><li>function drop_mutex($mtx) { shmop_delete($mtx); } </li></ul>
    22. 22. Shmop mutex 3 <ul><li>com_get_active_object() returns a handle to an instance from the Running Object Table </li></ul><ul><li>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; } } </li></ul>
    23. 23. Shmop mutex 4 <ul><li>$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); </li></ul>
    24. 24. Create a server app <ul><li>The shmop idea is prone to failure if something bad happens to a request that holds the mutex </li></ul><ul><li>An alternative is to run a separate process as a tcp server and queue requests to it </li></ul><ul><li>PHP 5 makes this easy </li></ul>
    25. 25. Client for Word Daemon <ul><li>$daemon = stream_socket_client(‘127.0.0.1:4000’); </li></ul><ul><li>if ($daemon) { </li></ul><ul><li>fwrite($daemon, serialize($data)); </li></ul><ul><li>$result = fgets($daemon); </li></ul><ul><li>} </li></ul>
    26. 26. Word Daemon <ul><li>$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 ”); fclose($client); } </li></ul>
    27. 27. With Events <ul><li>COM event handling framework is build from ‘Connection Points’ </li></ul><ul><li>A source object is implements IConnectionPointContainer </li></ul><ul><li>A sink object (callback handler) implements a dispinterface </li></ul><ul><li>dispinterfaces allow a loose handler implementation; perfect for scripting languages </li></ul>
    28. 28. turning on events <ul><li>bool com_event_sink($object, </li></ul><ul><li>$sinkobject [, $sinkname]); </li></ul><ul><li>Plumbs in event handling; </li></ul><ul><li>Events from $object are sunk into $sinkobject </li></ul>
    29. 29. Sinking events from IE <ul><li>$ie = new COM(&quot;InternetExplorer.Application&quot;); </li></ul><ul><li>$ie->Visible = true; </li></ul><ul><li>$ie->Navigate(&quot;http://www.php.net&quot;); </li></ul>
    30. 30. IE Events 2 <ul><li>class IEEvents { var $dom = null; function DocumentComplete($dom, $url) { echo “$url complete ”; $this->dom = $dom; } } </li></ul>
    31. 31. IE Events 3 <ul><li>$sink = new IEEvents; $ie = new COM(&quot;InternetExplorer.Application&quot;); $ie->Visible = true; com_event_sink($ie, $sink, ‘DWebBrowserEvents2’); $ie->Navigate(&quot;http://www.php.net&quot;); while (!$sink->dom) { com_message_pump(4000); } </li></ul><ul><li>// we can do stuff with $sink->dom here, or just continue with something else </li></ul>
    32. 32. IActiveScript <ul><li>A set of interfaces that abstract scripting engines </li></ul><ul><li>A compatible host can run any compliant script engine </li></ul><ul><li>Works in both directions; you can load engines in php, and you can load php into other hosts </li></ul>
    33. 33. Invoke JScript from PHP <ul><li>class foo { function bar($msg) { echo $msg; } } </li></ul><ul><li>$js = new COM(‘ScriptControl’); $js->Language = ‘JScript’; $js->AddObject(‘foo’, new foo, false); $js->AddCode(‘foo.bar(“js!”);’); </li></ul>
    34. 34. ActiveScript <ul><li>This SAPI lets you load PHP into other scripting engines </li></ul><ul><li>You need to regsvr32 php5activescript.dll to enable it </li></ul><ul><li>Language = PHPScript </li></ul><ul><li>Sadly, can't load PHP into PHP via COM due to architecture of PHP SAPI interface </li></ul>
    35. 35. Using PHP in Windows Script Host <ul><li>Create a .wsf file like this: </li></ul><ul><li><job id=&quot;test&quot;> <script language=&quot;PHPScript&quot;> $WScript->Echo(&quot;Hello&quot;); </script> </job> </li></ul><ul><li>cscript test.wsf </li></ul>
    36. 36. Persistence Helper <ul><li>Not everything supports the relevant interfaces, so not totally useful </li></ul><ul><li>Intention is to persist object state into streams or strings and store it into some kind of DB. </li></ul><ul><li>PHP streams are mapped as COM IStreams </li></ul>
    37. 37. Bogus Example <ul><li>$object = new COM(‘…’); $object->doSomething(); $dest = fopen(‘ftp://…/…’, ‘wb’); $p = new COMPersistHelper($object); $p->SaveToStream($dest); </li></ul>
    38. 38. Bogus Example 2 <ul><li>$object = new COM(‘…’); $src = fopen(‘ftp://…/…’, ‘rb’); $p = new COMPersistHelper($object); $p->LoadFromStream($src); </li></ul><ul><li>// $object is now in same state as it was on previous slide </li></ul>
    39. 39. Resources <ul><li>These slides are on my blog and on slideshare.net http://netevil.org </li></ul><ul><li>PHP COM manual: http://www.php.net/manual/en/ref.com.php </li></ul><ul><li>WMI: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/wmi_start_page.asp </li></ul><ul><li>Server-side MS Office: http://support.microsoft.com/default.aspx?scid=kb;EN-US;q257757 </li></ul><ul><li>PHP snapshots http://snaps.php.net </li></ul>
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×