PHP中的奇怪错误,路径和Windows中的空格

时间:2010-11-19 14:55:15

标签: php windows path command-line-interface space

我必须修复这个小虫子。首先,我们来谈谈一个小事实: 在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'未被识别为内部或外部命令, 可操作程序或批处理文件。
  • STDOUT:

示例2

  • 结果:1​​
  • STDERR:'C:\ a'未被识别为内部或外部命令, 可操作程序或批处理文件。
  • STDOUT:

示例3

  • 结果:1​​
  • STDERR:文件名,目录名或卷标语法不正确。
  • STDOUT:

所以你看,无论是(双引号还是双引号)代码都失败了。 是我还是我错过了什么?

3 个答案:

答案 0 :(得分:4)

最不幸的是,修复程序没有按预期工作,但是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上解决这个问题。到目前为止它运作良好!

答案 1 :(得分: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

答案 2 :(得分:0)

这是一种策略。

未经测试的解决方法提示:

  • 使用临时环境变量:

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

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

  • 使用8.3文件名,如果可以以某种方式在PHP中获取 - 肯定可以使用其他exec()

  • proc_open()有一个绕过cmd.exe的选项 - 如果文件系统以某种方式处理报价,可能值得一试

  • 尝试转义引号\"