Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

As part of my troubleshooting of being unable to launch SRCDS (the dedicated server for the Source game engine), I decided to try out launching some other executables (specifically Chrome and Firefox). Neither of those were launched, however. The page loaded (didn't hang as it does with SRCDS), but when checking Windows Task Manager, the processes were never actually launched. $output is a 0-length array, $return_var is 1 (giving me no information on the actual error happening.

The code I use is (no change occurs when using system or passthru instead of exec):

<?php
// Save the current working directory, then set it to SRCDS' directory
$old_path = getcwd();
chdir("C:/Users/Johan/Desktop/SteamCMD/tf2/");

// Launch SRCDS. Only the 3rd exec allows the page to load.
//$tmp = exec("srcds -console -game tf +map ctf_2fort 2>&1",$output,$output2);
//$tmp = exec("srcds -console -game tf +map ctf_2fort >> tmp.txt",$output,$output2);
$tmp = exec("srcds -console -game tf +map ctf_2fort 1>/dev/null/ 2/&1",$output,$output2);
echo "<p>SRCDS Output: ".sizeof($output)."</p>";
echo "<p>SRCDS Output2: ".$output2."</p>";

// Test execution of other files
// test.bat echoes %time%
$tmp2 = exec("test.bat");
echo $tmp2;
// Trying to launch another executable
chdir("C:\Program Files (x86)\Mozilla Firefox");
$tmp2 = exec("firefox", $output, $output2);
echo $tmp2;
echo "<p>FF Output:".sizeof($output)."</p>";
echo "<p>FF Output2:".$output2."</p>";

// End
chdir($old_path);
echo "Done.";
?>

This outputs:

SRCDS Output: 0

SRCDS Output2: 1

0:47:59,79
FF Output:0

FF Output2:1

Done.

My question is, is there any reason for this? Am I doing this incorrectly?

share|improve this question
Does the user you are running PHP under have permissions to run the programs in question? Also it looks like you are trying to redirect output to /dev/null on a Windows system, which won't work (use > nul instead) and the correct syntax for redirecting STDERR to STDOUT on *nix and Windows is 2>&1. Also note that simply redirecting output is not enough to launch programs asynchronously, which I imagine is what you are trying to do. To do this on Windows you will need COM available. – DaveRandom Jul 9 at 22:54
@DaveRandom Yeah, I'm not quite sure how that 2/&1 got in there, thanks for pointing it out. When using ` > nul` the page hangs, and never loads - just as what happens with all the other examples. The user PHP is run under is SYSTEM, so I'd assume it does. I'll have a look at COM - thanks a lot! – Birjolaxew Jul 9 at 23:04

1 Answer

up vote 0 down vote accepted

It looks like you are:

  • on Windows
  • trying to launch an external program asynchronously

Here is the secret sauce that will allow you to do so:

function async_exec_win($cmd)
{
    $wshShell = new COM('WScript.Shell');
    $wshShell->Run($cmd, 0, false); // NB: the second argument is meaningless
                                    // It just has to be an int <= 10
}

This requires the COM class to be available to your PHP instance, you may need to enable extension=php_com_dotnet.dll in php.ini (since PHP 5.3.15/5.4.5) in order to make it available.

Also note that this will require a full file name of the file you wish to execute, as the extension search list will not be used outside cmd.exe. So instead of srcds -console ... you'll want srcds.exe -console ... - personally I don't like the chdir() approach, I'd rather pass the full path of the exe into the function instead - but if you do this, you'll need to make sure the directory separators are of the correct type for the operating system. PHP will let you use whatever you like wherever you like, the OS won't be so forgiving.

For completeness, here's how to do a similar thing on *nix. This is actually better than the Windows version as it also returns the PID of the process that was created:

function async_exec_unix($cmd)
{
    return (int) exec($cmd . ' > /dev/null 2>&1 & echo $!');
}

Something to pay attention to: your command must be properly escaped. Neither of these implementations perform any validation on the command being executed, they just run it blindly. Never pass user input to an external program without escaping it as appropriate to the host operating system!

share|improve this answer
Very helpful, thank you. Currently at version 5.3.13, so COM works by default - however, upon using the following code, Firefox is still not launched: $wshShell = new COM("WScript.Shell");$wshShell->Run("firefox.exe",7,false);. I've also tried with 1 and 3 as the WindowStyle parameter, but that didn't change much. The process never appears in the task manager. – Birjolaxew Jul 9 at 23:22
@Birjolaxew Are you running this via a web server or from the command prompt? – DaveRandom Jul 9 at 23:23
Through WAMP 2.2, so a web server. – Birjolaxew Jul 9 at 23:25
@Birjolaxew OK first of all check which user account the Apache service is running as and verify that it has file system permissions to execute the file in question. – DaveRandom Jul 9 at 23:29
Well, I just realized how remarkably stupid I had been - I had only checked for process' running under my user account, but since Apache/PHP were running under SYSTEM, the programs would run there. Thanks for your help - I've marked it as the accepted answer since it helped me immensily, and I'd have had to come back with more stupid questions if it wasn't for you. – Birjolaxew Jul 9 at 23:33
show 1 more comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.