So, In PHP on Windows: is it possible to both run an executable in the background AND retrieve its PID? I've deduced that it's possible to accomplish both tasks separately, but not together.
Backgrounding the Process
To background a process launched via the SHELL, the command 'start /B "bg" myprog.exe'
must be used and the the SHELL process must be closed immediately after.
To do this, many people use pclose( popen( ... ) )
like so pclose( popen( 'start /B "bg" myprog.exe', 'r') );
but to my knowledge it's impossible to retrieve the pid
when using popen.
Because it's impossible to get the pid
with popen, we must look to proc_open.
Getting the PID
Using proc_open
we can retrieve the pid of the exe if and only if bypass_shell
is set to true.
If bypass_shell
is set to false (the default), Windows returns the pid
of the SHELL. For more info see: https://bugs.php.net/bug.php?id=41052
The Problem Explained
The start /B
command fails when passed to proc_open when bypass_shell = true
because it skips the SHELL and sends the commandline arguments directly to myprog.exe which doesn't know what to do with them.
Conversely, If bypass_shell = false
(the default) and proc_close is used to close the SHELL immediately, myprog.exe runs in the background just like when using pclose( popen( ... ) )
BUT the incorrect pid
is returned (we get the pid
of the SHELL).
So, is backgrounding + correct pid retrieval possible?
If not, what's the next best thing? I need to do this for a PHP script that will be deployed on shared hosting so no third party extensions can be installed. The best I can come up with is taking a snapshot of tasklist
before and after launching myprog.exe in the background and then cross-analyzing the results. Note that myprog.exe can be running concurrently.
If it helps, although it shouldn't make a difference, myprog.exe is actually ffmpeg (which comes installed on most shared webhosts).
A Temporary Solution
// background the process
pclose( popen( 'start /B "bg" ffmpeg.exe', 'r') );
// get the pid using tasklist
exec( 'TASKLIST /NH /FO "CSV" /FI "imagename eq ffmpeg.exe" /FI "cputime eq 00:00:00"', $output );
$output = explode( '","', $output[0] );
$pid = $output[1];