7

我必须修复这个小错误。首先,让我们谈谈一个小事实:在 Windows 上的 CLI 中,您不能运行路径中有空格的程序,除非转义:

C:\>a b/c.bat
'a' is not recognized as an internal or external command,
operable program or batch file.

C:\>"a b/c.bat"

C:\>

我在 PHP 中使用 proc_open...proc_close 来运行进程(程序),例如:

function _pipeExec($cmd,$input=''){
    $proc=proc_open($cmd,array(0=>array('pipe','r'),
        1=>array('pipe','w'),2=>array('pipe','w')),$pipes);
    fwrite($pipes[0],$input);
    fclose($pipes[0]);
    $stdout=stream_get_contents($pipes[1]); // max execusion time exceeded ssue
    fclose($pipes[1]);
    $stderr=stream_get_contents($pipes[2]);
    fclose($pipes[2]);
    $rtn=proc_close($proc);
    return array(
        'stdout'=>$stdout,
        'stderr'=>$stderr,
        'return'=>(int)$rtn
    );
}

// example 1
_pipeExec('C:\\a b\\c.bat -switch');
// example 2
_pipeExec('"C:\\a b\\c.bat" -switch');
// example 3 (sounds stupid but I had to try)
_pipeExec('""C:\\a b\\c.bat"" -switch');

示例 1

  • 结果:1
  • STDERR: 'C:\a' 不是内部或外部命令、可运行程序或批处理文件。
  • 标准输出:

示例 2

  • 结果:1
  • STDERR: 'C:\a' 不是内部或外部命令、可运行程序或批处理文件。
  • 标准输出:

示例 3

  • 结果:1
  • STDERR:文件名、目录名或卷标语法不正确。
  • 标准输出:

所以你看,无论是哪种情况(双引号或不是双引号),代码都会失败。是我还是我错过了什么?

4

3 回答 3

5

最不幸的是,修复没有按预期工作,但是 Pekka 的第一个建议给了我一个想法:

$file='C:\a b\c';
$cmdl='/d /b /g';

if(strtolower(substr(PHP_OS,0,3))=='win') // if windows...
    $file='cd '.escapeshellarg(dirname($file)).' && '.basename($file);

_pipeExec($file.' '.$cmdl);

这是特定于平台的,我希望我也不必在 linux 上解决这个问题。到目前为止,它运作良好!

于 2010-12-10T15:30:14.380 回答
1

解决此问题的另一种方法是在命令的开头和结尾添加额外的双引号。

$process = 'C:\\Program Files\\nodejs\\node.exe';
$arg1 = 'C:\\Path to File\\foo.js';

$cmd = sprintf('"%s" %s', $process, escapeshellarg($arg1));
if (strtolower(substr(PHP_OS, 0, 3)) === 'win') {
    $cmd = '"'.$cmd.'"';
}

_pipeExec($cmd);

我在https://bugs.php.net/bug.php?id=49139
上找到了这个解决方案 它看起来很奇怪,但是嘿 - 它是 Windows ......:D

于 2016-04-08T08:16:04.380 回答
0

这是一个悲剧。

未经测试的解决方法想法:

  • 使用临时环境变量:

    exec('SET ENVPATH="C:\a b"');
    proc_open('%ENVPATH%\c.bat' ....
    

    (不知道这是否适用于 proc_open)

  • 如果可以在 PHP 中以某种方式获取,请使用 8.3 文件名——当然可以使用另一个文件名exec()

  • proc_open()可以选择绕过cmd.exe- 如果文件系统以不同方式处理引号,可能值得一试

  • 尝试转义引号\"

于 2010-11-19T15:08:10.527 回答