Wez Furlong I am Wez Furlong, Chief Software Architect at Message Systems. We're responsible for building an awesome Messaging Platform.

I'm also a PHP Core developer and OpenSource contributor, residing in Maryland, USA with Juliette, Xander and Lily. (read more)

Subscribe. (circulation 957)
Comments. (circulation 8)

Search powered by Google

Running PHP as a Service on Win32

18th September 2005 @ 02:28 EDT

[Update: I wrote some docs for the php manual]

So, you've written some kind of super-duper daemon process in PHP, perhaps using the event extension and stream_socket_server(). On Unix, it's quite a simple matter to have it run from init (or maybe inetd) when your machine starts... but doing the same on windows isn't possible without some hacks. Until now.

Last night I put together 2 new extensions for windows; the first of these is called win32service and it allows you run your PHP scripts from the "Service Control Manager" (SCM). The SCM is roughly analagous to the init process on unix, in that it runs tasks on startup and monitors their status, optionally restarting them if something goes awry.

I've included a sample service script that demonstrates minimal usage. Before you can run a script as a service, you need to register it with the SCM; in the sample, you do this by running it with the "install" argument on the command line. Once installed, you can use either the services MMC snap-in (run services.msc, or look for it under "Administrative Tools") or the good old fashined "net" command to launch or stop the service. I prefer the latter:

   net start dummyphp

The output from the command should indicate the service started correctly; use the task manager to verify this--you should see a php.exe process running as SYSTEM. This dummy service does nothing much; just sleeps and waits for the SCM to tell it to stop; lets do that now:

   net stop dummyphp

Again, the output from that command should indicate that the service stopped, and your task manager should no longer show php.exe running as SYSTEM. Now that we've proved that it works, we should remove the same from the SCM; running the script with the "uninstall" argument will do this.

It's all pretty straight-forward; the most complicated part is the win32_create_service() function; the first argument is an array that describes the service; the following keys are supported:

  • service - the short name of the service. You can't have two services with the same name.
  • display - the display name of the service.
  • user - the account name under which to run the service. If omitted, runs as the local system account
  • password - the password to match the "user" setting.
  • path - full path to the binary to run. If omitted, the full path to the currently running process will be used (typically php.exe)
  • params - command line parameters to pass to the binary. You'll probably want to specify the full path to a PHP script, plus some parameter to indicate that the script should run as a service.

(there are some more keys but they're not fully supported yet)

When it comes to actually running your service, you should call win32_start_service_ctrl_dispatcher() and pass in the name of the service. This function checks-in with the SCM; it is especially important that you do this as soon as possible in your script, as the SCM blocks while it waits for you to check-in--you can cause system-wide issues if you take too long.

While your service is running, you should periodically check to see if the SCM has requested that you stop. One way to do this is to wrap the main body of your service code in a while loop like this:

<?php
   while (WIN32_SERVICE_CONTROL_STOP != win32_get_last_control_message()) {
      // do stuff here, but try not to take more than a few seconds
   }
?>

If you already have an event loop, you can fold the above into your application. If you're using the event extension, you can schedule a recurrent timed event to check for the stop condition.

And that's pretty much all there is to say for now. I strongly recommend that you look through the MSDN documentation on services; it's very valuable background information.

The binaries for PHP 5 should show up under http://snaps.php.net/win32/PECL_5_0/ in the next couple of hours.

Enjoy :)

Post a comment

Php 4.4.4 + PECL impossible? Need to create an exe win service

6th January @ 00:17 EDT

Good morning everybody,

I'm afraid this blog is dead as I didn't find any other comment after 2005 .. 5 years ago! :(

Anyway I'm using bamcompile a great single EXE compiler for php.. with some limitations..: cannot use php higher than V.4.4.4 and cannot use foreach (array_expression as $key => $value).

Now, the problem is that I'd like to write a single exe Window Service as my little webcheck php program runs quite well, but is not able to run before user logon.

I thought it was MUCH simpler to create a Win32 Service application but instead I discovered I need a lot more code with no dll support in php 4.4.4.

I tried adding to my PHP4 php.ini installation the

extension=php5ts.dll

extension=php_win32service.dll

as win32service requires php5ts.dll but I get an error as PHP API is different from what expected (of course it is php 4.4.4 instead of 5.2!!)

Now there seems to be a problem that I'm not able to overcome: create a single EXE file which is a windows service with a free php compiler :(

Any ideas??

BTW is there some php 5.x.x chunk of code to create a simple socks service to play with?

I think I'm only missing the PECL::Event to get and answer messages from SCM.

Thanks a lot in advance!

L.R.

Luxnews AT gmail DOT com

by Luca Regoli in .

I've been waiting yeras for this

9th February 2005 @ 10:40 EDT

Now, if only you could port it to PHP 4 too...

by giunta.gaetano@sea-aeroportimilano.it in .

#

11th March 2005 @ 17:01 EDT

Anybody knows how to make it working?? Apache 2 doesn't want to load MODPHP with that extension.

by in .

Any real time example

19th May 2005 @ 00:20 EDT

Is there any real time sample example to try out here. I wrote a socket server in PHP but that is blocking in nature. How do we run such daemon as a windows service. I am not really windows pro so please ignore my knowledge about windows services.

by in .

It did work...but...

22nd June 2005 @ 19:50 EDT

Hi,

I've just could have a successful script running as a service... So, first of all, great work !

The one thing that I was not able to do was call a function from within the while() loop.

I mean;

while (WIN32_SERVICE_CONTROL_STOP != win32_get_last_control_message()) { ...code... }

worked fine, but

while (WIN32_SERVICE_CONTROL_STOP != win32_get_last_control_message()) { my_code($parm); }

function my_code($parm) { ...code... }

did not....

Any ideas ???

Being able to call my own functions from within the while() loop allows much clearer code (at leas for me :>)

Look forward to your answer.

Regards. Gonzalo

by gmartinez@accendo-it.com in .

It did work...no buts at all...

22nd June 2005 @ 20:07 EDT

Previous message was an error of mine, sorry !

It works just fine !

Thanks again.

by gmartinez@accendo-it.com in .

small mistake

5th August 2005 @ 13:33 EDT

the sample code still has a small error:

$x = win32_start_service_ctrl_dispatcher('dummyphp');

needs to be replaced by: $x = win32_start_service_ctrl_dispatcher('sample dummy PHP service');

apart from this: great!

Robbie

by robbie in .

small mistake 2

5th August 2005 @ 14:13 EDT

add also quotes to: 'params' => '"'. FILE_ . '"' . ' run',

this is for when you run your sript from a directory which contains spaces like fe "Program Files"

this error and previous one is applicable for win xp, on win 2003 the example is working fine without these modifications and also with these modifications ;-)

Robbie

by robbie in .

Problem running under Windows XP

23rd August 2005 @ 02:28 EDT

Hi,

I had my php script running as a service perfectly under Win2k.

Now, I've installed WinXP, and the service do not start.

In the event viewer I get;

"... Timeout (30000 milliseconds) waiting for the MY SERVICE service to connect.

For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp. ..."

Any Ideas ???

by gmartinez@accendo-it.com in .

Problem running under Windows XP

25th August 2005 @ 12:07 EDT

I got it working now.

It works fine

by gmartinez@accendo-it.com in .

Using PECL::Event to check service stopage

19th October 2005 @ 14:57 EDT

Has anyone used the PECL::Event to check for the control_stop? I've almost got it but I can't seem to get it to run my stopage code when I stop the service.

Here is what I have right now:

$x = win32_start_service_ctrl_dispatcher('WWH');

function check_service(){ if(WIN32_SERVICE_CONTROL_STOP == win32_get_last_control_message()){ stop(); exit; } }

event_init(); $e = event_new(NULL, EV_PERSIST, 'check_service'); event_schedule($e, 2, 0); event_dispatch();

.. More code like the stop function.

Thanks

by smitchell@northrock.bm in .

Quick note PECL::Event

20th October 2005 @ 00:09 EDT

After looking at the CVS for PECL::Event I found the even_timout method that works better for me as I'm not using streams. What I'm finding now is that anything after me event_dispatch() is not be run.

I'm trying to use this with a socket server but I'm trying to use the current version on the socket server and not replacing it with the Event methods. I just want Event to run the check for closure method every X time.

Lastly, I've noticed that since my socket server waits in a loop that I wasn't able to put the service control in the same code that created the server as it never ran anything after the server was opened because it didn't return but waited for connections.

by smitchell@northrock.bm in .
Post a comment

Would you like to work with me?
I have positions open for server/infrastructure software development (C) and QA.

Ohloh profile for wez