PHP Scripting in Win32 Apps
March 22, 2008
This is a repost of something I put together a couple years ago, and as such it may be out of date. There are much better ways to add scripting support to your apps these days, but if you are dead-set on using PHP, this may help you do it.
In order to use the cli version of php for scripting in your win32 app, you’ll need to connect your app to PHP, send it PHP code, and read the processed output.
To do this, of course, requires a means of interprocess communication between the two applications. Experienced programmers instantly think
“pipes!”and search MSDN for the relevant information. Well, I did that and turned up a lot of information on a function called _popen() — a function that seems wonderful, since it does so much for you. It opens the pipe(s), launches the program, and returns a FILE *that you can read or write to (and, if some of what I’ve read is to believed, you can even open a bidirectional pipe to read AND write from!)
Sounds great, doesn’t it? Well, there’s just one problem. Microsoft, in my opinion, worded this terribly when they said:
Note: If used in a Windows program, the _popen function returns an invalid file pointer that will cause the program to hang indefinitely. _popen works properly in a Console application.
If that is clear to you, congratulations, you speak Microsoft. But for the rest of us, let me translate: do not use _popen() unless both of the applications (parent and child) are console applications. Otherwise, it won’t work.
So what you really need to do is create your own pipes.
Here are the steps involved in creating two pipes and redirecting stdin and stdout for the child process to these pipes:
- Create the two pipes using CreatePipe()
- Let the system know that we want our child to inherit these two pipes
- Spawn the child process
- Immediately close the end of each pipe that we aren’t using (in other words, close the ends that the child will be using)
- Read and write to and from the pipes as needed
- Close the pipes when done
Clear? Ok then, let’s look at an abreviated version of this process, and we’re even spawning php.exe as our child process:
-
// We will run php.exe as a child process after creating
-
// two pipes and attaching them to stdin and stdout
-
// of the child process
-
// Define sa struct such that child inherits our handles
-
-
SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES) };
-
sa.bInheritHandle = TRUE;
-
sa.lpSecurityDescriptor = NULL;
-
-
// Create the handles for our two pipes (two handles per pipe, one for each end)
-
// We will have one pipe for stdin, and one for stdout, each with a READ and WRITE end
-
HANDLE hStdoutRd, hStdoutWr, hStdinRd, hStdinWr;
-
-
// Now create the pipes, and make them inheritable
-
CreatePipe (&hStdoutRd, &hStdoutWr, &sa, 0))
-
SetHandleInformation(hStdoutRd, HANDLE_FLAG_INHERIT, 0);
-
CreatePipe (&hStdinRd, &hStdinWr, &sa, 0)
-
SetHandleInformation(hStdinWr, HANDLE_FLAG_INHERIT, 0);
-
-
// Now we have two pipes, we can create the process
-
// First, fill out the usage structs
-
STARTUPINFO si = { sizeof(STARTUPINFO) };
-
PROCESS_INFORMATION pi;
-
si.dwFlags = STARTF_USESTDHANDLES;
-
si.hStdOutput = hStdoutWr;
-
si.hStdInput = hStdinRd;
-
-
// And finally, create the process
-
CreateProcess (NULL, "c:\\php\\php-win.exe", NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, π);
-
-
// Close the handles we aren’t using
-
CloseHandle(hStdoutWr);
-
CloseHandle(hStdinRd);
-
-
// Now that we have the process running, we can start pushing PHP at it
-
WriteFile(hStdinWr, "", 9, &dwWritten, NULL);
-
-
// When we’re done writing to stdin, we close that pipe
-
CloseHandle(hStdinWr);
-
-
// Reading from stdout is only slightly more complicated
-
int i;
-
-
std::string processed("");
-
char buf[128];
-
-
while ( (ReadFile(hStdoutRd, buf, 128, &dwRead, NULL) && (dwRead != 0)) ) {
-
for (i = 0; i < dwRead; i++)
-
processed += buf[i];
-
}
-
-
// Done reading, so close this handle too
-
CloseHandle(hStdoutRd);






PHP is like chinese to me, i’m glad i have a good scripter
hey,you have posted such a effectful article that it will certainly help me