Wez Furlong
commented on
Getting It Doneslideshare seems busted and won’t let me check the box to allow download. If you can sit tight for a couple of days, I’ll be uploading a revised set of slides, and I’ll make sure that you can download a PDF, whether it be via slideshare or my blog.7 months ago
Wez Furlong
commented on
PHP Streams: Lucky Dipin response to guest3a83ae, the stream_eof() method is something you must implement for user wrappers otherwise the feof() function won’t operate correctly on streams created from that wrapper. My personal feeling is that the world doesn’t need feof(), but I have to live with the fact that the world uses feof() anyway, so this method is therefore necessary to make things work for them.2 years ago
Wez Furlong
commented on
PHP and COMThe 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…)2 years ago
Wez Furlong
commented on
PHP and COMCan load into any activescript host; Windows Scripting Host, ASP, the ScriptControl we used earlier, the WeaverSlave IDE, Kapsules desktop widget application2 years ago
Wez Furlong
commented on
PHP and COMPHP also has an ActiveScript compatible interface; it is still a little bit experimental, but works for most of the stuff I’ve tried.
The DLL is called php5activecript.dll and the best available version can be found in the PECL repository on our snapshots site.2 years ago
Wez Furlong
commented on
PHP and COMThe Language property can be set to the name of any language that you have installed; by default, windows ships with javascript and vbscript.
You can download ActivePerl, ActiveRuby and ActivePython
The COM extension provides an IDispatchEx wrapper for PHP objects, so that you can invoke them from other COM compatible scripting languages using this technique.2 years ago
Wez Furlong
commented on
PHP and COMThe main new thing here is com_message_pump(); you can thing of this as being something like sleep() except that the time is measured in milliseconds. The other big difference is that it will handle COM messages while it sleeps, returning after it processes the queue.
We need to do this so that the COM can maintain various state and be able to actually call into our callback.
If you’re writing any COM scripts, you should probably use com_message_pump() in any place where you are sleeping for more than a couple of seconds.2 years ago
Wez Furlong
commented on
PHP and COMIE has a number of different event interfaces that could bind to; the one we’re interested in is called DWebBrowserEvents2. It has a number of methods that will be called for a number of useful events. In particular, we want the “DocumentComplete” method.
This is called once the page has downloaded and rendered; you are passed a reference to the document object for the page and the url.
You can use these as you see fit—you might want to walk the DOM to extract (or insert) information, or you might just want to indicate to the user that you’re ready.
The handler above simply prints out the URL that loaded and sets the dom as a member variable.
Now we need to hook it up…2 years ago
Wez Furlong
commented on
PHP and COMThis script launches IE, makes it visible and then navigates to the PHP home page.
Let’s assume that we want to make sure that it has fully loaded and rendered before doing something else in our script.2 years ago
Wez Furlong
commented on
PHP and COMThis script is a separate entity from the rest of your site; you should run it using php.exe (the CLI version), and that process will be the only part that talks to MS Word.
It’s quite a simple script; it creates a server socket and then loops waiting for a client connection; stream_socket_accept() returns a stream that we can use to talk to the client.
We un-serialize the data into a php variable and pass that into the code that actually generates the doc.
Once its done, we send back a line of text to the client and close the connection.
This approach is much simpler to code, and less prone to failure.
Since the daemon only accepts once connection at a time, one after the other, we’re effectively getting a mutex for free (although sockets cost a bit more resources).
Shmop might be faster, but this is approach is more reliable.
You could also place the server on a separate machine and have it generate the docs there.
Taking this further, you could move your web code over to unix and call out to a windows box (or virtual machine) to generate the office documents.2 years ago
Wez Furlong
commented on
PHP and COMWe’ll run the daemon on the loopback interface (so no external access to it is possible) on TCP port 4000… you can choose any port that doesn’t conflict with other services that you might be running on the machine.
We’re using stream_socket_client() to connect to the daemon; this is part of the new stream transport subsystem in PHP 5 and gives you more options than the traditional fsockopen() function. You could use fsockopen(); I’m only using stream_socket_client() because the server name is symmetric with the stream_socket_server() call on the next slide; fsockopen() would need two parameters to do the same thing.
Here we’re assuming that $data is some kind of object or array that contains the information needed to generate the document.
We serialize it and send the whole thing over the socket to the server process; then we wait for it to complete; we simply wait for it to send a line of output back.2 years ago
Wez Furlong
commented on
PHP and COMImportant points
You need to ensure that you call drop_mutex() before the request ends, otherwise you lock out other requests (can be solved by restarting the web server)
We’re not setting the application visible, to save resources.
We’re not calling $word->Quit(), as we want to keep the application around for the next request
Readfile represents doing something with the document… $filename is some unique filename2 years ago
Wez Furlong
commented on
PHP and COMSo we now have a way to mutex requests; we just need a way to ensure that we are only ever running a single instance of Word.
OLE provides a number of services, and one of these is known as the Running Object Table (ROT). An out-of-proc com server will typically register itself in the ROT when it is launched; this allows other applications to bind to that instance and saves them from having to launch their own, private, new instance. This is just what we need.
PHP 5 added com_get_active_object_object for this purpose; if it fails to get a handle on the object it will throw a moniker exception; that you can check for using the MK_E_UNAVAILBLE code (which translates roughly to Moniker Error: Name Unavailable).
In that case, you will want to create a new word instance yourself and return it.
Otherwise, you had some other weird error; let’s just re-throw the exception and let some other code handle it.2 years ago
Wez Furlong
commented on
PHP and COMTo avoid an indefinite wait for the mutex, we’re going to set a time limit, in seconds, that we’re willing to wait for the mutex to become available.
PHP doesn’t expose the native win32 mutex functions, so we fake it by attempting to create a 1-byte shared memory segment; “cwn” means “Create a Writable segment, but only succeed if we made a New one”
While our request has the handle, no other request will succeed in getting it.
When we’re done, we’ll delete the shared memory segment, allowing other requests a chance at grabbing it
The key is simply an integer number; on win32, it can be any number, so long as that number is not used by some other PHP script that calls shmop_open. (on unix, the id has to be unique across all applications).
I like using 42 because I’m a bit of a Douglas Adams fan.2 years ago
Wez Furlong
commented on
PHP and COMMutex is an abbreviation for “Mutual Exclusion Device”. It’s some kind of object that allows you code to (co-operatively) avoid having multiple threads or processes doing the same thing at the same time.
We’re going to use shmop to implement a mutex to avoid multiple requests calling into our single word instance2 years ago
Wez Furlong
commented on
PHP and COMGenerating MS Office documents on the fly is something of a holy grail for many web applications.
If you’re running on windows (and are appropriately licensed—each client must have an Office license!), what better way to produce them than by using COM to tell Office exactly what you want to do?
At first glance, you’re likely to think of running this script for each person that wants their document.
That’s fine if you have low traffic, but as soon as you start to have more than a couple of people (literally) making concurrent demands for their custom docs, you’re going to run into trouble.
On a technical level, there are a number of reasons why you should avoid server side office:
MS Office applications are designed to have a single COM client per process (they’re out-of-proc servers)
That means you get one instance of the app for each COM object you create.
If you have to make a lot of COM calls into word to format your document, you’re wasting a lot of CPU just handling the marshalling
It won’t take many concurrent users to bring the machine to its knees.
Secondary issues are:
User identity; Office needs to load a user profile when it initializes, so you need to launch using a specific user/password (those extra params in the constructor) for someone that does have a valid office setup
Stability and Resiliency; Microsoft suggest that using Office on the server side via COM could lead to deadlocks and other problems that cannot be solved without interaction with the user. In addition, the install-on-demand features could also block your scripts while waiting for appropriate media and user confirmation.
So, Microsoft are making this sound like a bad idea. Maybe it is for you and your application. It is worth exploring how to solve these issues, since many other out-of-proc COM servers are likely to have similar limitations. The user identity problem can be easily solved by passing in the credentials when you create the object. Install-on-demand problems can be avoided simply by making a full install to the hard disk.
Here are two strategies for handling the concurrency issues, that can be applied to other objects.2 years ago
Wez Furlong
commented on
PHP and COMADO is (or was, last time I looked at ASP—haven’t done that in a few years) the defacto standard for working with databases from windows scripting languages.
To me, ADO feels a bit verbose, and slightly back-to-front in the way you open a recordset, so I would probably want rewrite the code to use the PDO ODBC driver instead (), but since that isn’t stable yet, the COM extension should be more than good enough, and code changes will be minimal, saving on man hours.
Don’t confuse it with a PHP project with the same name…. John Lim has a DB abstraction library that smells like ADODB and runs on unixy as well as win32 platforms2 years ago
Wez Furlong
commented on
PHP and COM“Windows® Management Instrumentation (WMI) is a component of the Microsoft® Windows® operating system and is the Microsoft implementation of Web-Based Enterprise Management (WBEM), which is an industry initiative to develop a standard technology for accessing management information in an enterprise environment. WMI uses the Common Information Model (CIM) industry standard to represent systems, applications, networks, devices, and other managed components. You can use WMI to automate administrative tasks in an enterprise environment.”
WMI ships with WinME and later, and can be downloaded for older windows versions.
WMI provides a moniker “winmgmts:” as a shortcut to get a handle on an object in the WMI namespace. The default namespace in win2k and later is \root\cimv2
There are a whole bunch of things you can monitor and configure via WMI, and I confess to not being an expert on the topic; consult the MSDN docs for more details.2 years ago
Wez Furlong
commented on
PHP and COM.Net is one of the latest buzzwords in the windows world.
It features a managed code environment, with JIT compilation to native code, providing a fast, crash free platform for application building.
Microsoft provide an extensive class library (thousands of classes are available), and the whole environment has many similarities with COM.
PHP offers the poor-man’s .Net support through the COM Interop layer, which acts as a bridge between .Net and COM.
As a result, it was reasonably simple to build this into the PHP COM extension; .Net objects, once instantiated, look and smell just like any other COM object.
To instantiate a .Net object, you need to know which assembly contains the class and the class name, so there are two distinct parameters rather than the single parameter you use for COM.2 years ago
Wez Furlong
commented on
PHP and COMPHP 4 COM was very eager to make conversions to/from variants, and this could lead to loss in precision, particularly if PHP didn’t have a direct mapping for a particular type.
PHP 5 avoids most of these problems by defering the type conversion until a point where you really need to work with the value.
For those cases where the value can’t be represented in PHP without loss of precision, but where you really need to operate on them, PHP 5 offers a whole range of variant arithmetic functions. These functions allow you to perform addition, subtraction, multiplication, division, string concatentation, modulus, bitwise operations, rounding, type juggling and comparison.
This is particularly useful if you need more precision when manipulating currency values; the variant currency type is faster than bcmath, and the COM extension offers you the convenience of referring to a variant value implicitly (ala print).
Also available are two functions for converting between unix timestamps and variant date types, so you can very easily use PHP’s date and time functions with COM.
All of these functions follow the OLE/Variant rules for type comparison and evaluation (which you might be familiar with from VB); they are in some cases different from PHP.2 years ago
Comments