PHP quirk: shell commands breaking on Windows

I’ve been wrestling with many compatibility quirks in my work on SLOODLE lately, and this one certainly takes the prize. It seems that some perfectly valid shell commands will simply not work when executed from within PHP on Windows.

Some of our code at SLOODLE needs to execute a shell command to make use of software called “ImageMagick” (although only as a fall-back if the MagickWand extension isn’t present). The basic structure of the command is simple:

convert src dst

In its simple form, it works fine. However, the path of the “convert” program and the files specified by “src” and “dst” sometimes need to be enclosed in quotation marks. That is often the case on Windows, which stupidly puts most software in “C:Program Files”.

For some reason, if the program being executed and one or more of the arguments are enclosed in quotation marks, then it won’t work from PHP (even though it works fine on the Windows command line). The “exec” command gives a return code of 1 and no output and the “shell_exec” command doesn’t seem to do anything at all. And what’s worse… no warnings, notices, or error messages are reported.

After much digging around, I found a few people using the Windows “start” command to solve some problems. It tried it, and it works! All you need to do is prepend some stuff to your shell command, so our command from above ends up looking something like this:

start /B "" convert src dst

The empty quotation marks after /B are required, but irrelevant. You can find out more about the “start” command by typing “start /?” on your Windows command line.

Obviously it’s worth noting that it won’t work on Linux, so you need to check the operating system in PHP before modifying your shell commands. You could actually put it in a handy function like this:

function makeWindowsCompatible( $cmd )
{
    if (substr(php_uname(), 0, 7) == "Windows") return 'start /B "" '.$cmd;
    return $cmd;
}

Pass your existing shell commands into that function, and the return result will be modified for Windows if necessary. You would use it something like this:

$cmd = 'convert src dest';
echo shell_exec( makeWindowsCompatible($cmd) );

Leave a Reply

Your email address will not be published. Required fields are marked *