Domanda

Devo risolvere questo piccolo bug.Innanzitutto parliamo di un piccolo fatto:Nella CLI su Windows, non puoi eseguire un programma con uno spazio nel suo percorso, a meno che non sia eseguito l'escape:

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:\>

Sto usando proc_open...proc_close in PHP per eseguire un processo (programma), esempio:

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');

Esempio 1

  • RISULTATO:1
  • STDER:'C: A' non è riconosciuto come comando interno o esterno, programma operabile o file batch.
  • STUDIO:

Esempio 2

  • RISULTATO:1
  • STDER:'C: A' non è riconosciuto come comando interno o esterno, programma operabile o file batch.
  • STUDIO:

Esempio 3

  • RISULTATO:1
  • STDER:La sintassi del nome file, del nome della directory o dell'etichetta del volume non è corretta.
  • STUDIO:

Quindi vedi, in entrambi i casi (virgolette doppie o meno) il codice fallisce.Sono io o mi sono perso qualcosa?

È stato utile?

Soluzione

Sfortunatamente, la soluzione non funziona come previsto, tuttavia il primo suggerimento di Pekka mi ha dato un'idea:

$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);

Questo è specifico della piattaforma e spero di non doverlo risolvere anche su Linux.Finora funziona bene!

Altri suggerimenti

Un altro modo per risolvere questo problema è inserire virgolette doppie aggiuntive all'inizio e alla fine del comando.

$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);

Ho trovato questa soluzione su https://bugs.php.net/bug.php?id=49139
Sembra strano, ma ehi, è Windows...:D

Questo è strano.

Idee alternative non testate:

  • Utilizza una variabile d'ambiente temporanea:

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

    (non ho idea se funzionerà per proc_open)

  • Usa il nome file 8.3 se in qualche modo può essere recuperato in PHP: sarebbe sicuramente fattibile usandone un altro exec()

  • proc_open() ha un'opzione per bypassare cmd.exe - potrebbe valere la pena provare nel caso in cui il filesystem gestisca in qualche modo le virgolette in modo diverso

  • Prova a sfuggire alle virgolette \"

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top