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'は、内部または外部コマンド、操作可能なプログラム、またはバッチファイルとして認識されません。
  • STDOUT:

例2

  • 結果:1
  • STDERR:'C:\ a'は、内部または外部コマンド、操作可能なプログラム、またはバッチファイルとして認識されません。
  • STDOUT:

例3

  • 結果:1
  • STDERR:ファイル名、ディレクトリ名、またはボリュームラベルの構文が正しくありません。
  • STDOUT:

ご覧のとおり、どちらの場合(二重引用符であるかどうかに関係なく)、コードは失敗します。それは私ですか、それとも何かが足りないのですか?

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 に答える