2010-11-19 9 views
6

Muszę naprawić ten mały błąd. Najpierw porozmawiajmy o małej rzeczywistości: W CLI w systemie Windows, nie można uruchomić program z miejscem na swojej drodze, chyba że uciekł:Dziwny błąd w PHP, Spaces in Paths i Windows

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

Używam proc_open ... proc_close w PHP do prowadzenia procesu (programu), na przykład:

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

Przykład 1

  • Wynik: 1
  • STDERR: "C: \ a" nie jest rozpoznawane jako polecenie wewnętrzne lub zewnętrzne, program roboczy lub plik wsadowy.
  • STDOUT:

Przykład 2

  • Wynik: 1
  • STDERR: 'C: \ a' nie jest rozpoznawana jako polecenie wewnętrzne lub zewnętrzne, dostosowany program lub partia plik.
  • STDOUT:

Przykład 3

  • Wynik: 1
  • STDERR: Składnia etykieta pliku, nazwa katalogu lub objętość jest nieprawidłowe.
  • STDOUT:

Więc widzisz, albo przypadek (cudzysłowy lub nie) kod nie powiedzie się. Czy to ja czy ja czegoś brakuje?

+0

strzał w ciemno, ale można spróbować przełączania rodzajów ofertę? ('' '' ') –

+0

Nie mam w tym żadnego doświadczenia, ale w wierszu polecenia uruchamiasz" ab/c.bat ", aw PHP nazywasz" C: \ ab \ c.bat ", w tym ścieżkę wewnątrz Cytaty, może wywołanie C: \ "ab \ c.bat" działa? –

+0

@Pekka, otrzymuję to samo co Przykład 3, wydaje się, że pojedyncze cudzysłowy nie są znakami kontenerowymi, jak podwójne cudzysłowy. – Christian

Odpowiedz

3

Większość niestety poprawka nie działa zgodnie z oczekiwaniami, jednak pierwsza sugestia Pekka dał mi pomysł:

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

Jest to zależne od platformy i mam nadzieję, że nie będę musiał tego naprawiać również na Linuksie. Jak na razie działa dobrze!

+0

cześć, próbuję użyć twojego rozwiązania w moim kodzie, i odkryłem, że jest błąd składni.) Koniec linii 5. naprawiłbym to, ale przy edycji jest minimalny limit znaków. Pozdrawiam –

+1

@ ted.strauss Dzięki! Naprawione. – Christian

+1

To dobre rozwiązanie. Nie widzę powodu, dla którego to mogłoby zawieść na Linuksie. – Aust

0

To jest stan.

Nieprzetestowane pomysły rozwiązania:

  • użyć zmiennej środowiskowej przejściowych:

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

    (nie wiem, czy to będzie działać dla proc_open)

  • pomocą 8.3 filename jeśli może jakoś być pobrane w PHP - z pewnością byłoby wykonalne przy użyciu innego exec()

  • proc_open() ma możliwość ominięcia cmd.exe - może warto spróbować w przypadku plików jakoś uchwyty cytaty inaczej

  • Spróbuj uciec cytaty \"

+0

Ominięcie cmd.exe dał mi pomysł:' cmd "C: \\ ab \\ c.bat" ' – Christian

+0

proc_open ma argument do przekazania w zmiennych env lepiej go używać –

+0

@Christian ah, interesting. Może pracować. 'call' @ Viper dobry punkt! –

1

Innym sposobem rozwiązania tego problemu jest umieszczenie dodatkowych podwójnych cudzysłowów na początku i końcu polecenia.

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

Znalazłem rozwiązanie na https://bugs.php.net/bug.php?id=49139
To wygląda dziwnie, ale hej - to system Windows ...: D

+0

To rozwiązanie jest dziwne, ale działa i jest bardziej rozsądne niż przejście do katalogu tylko po to, aby uruchomić polecenie. –

+0

Uwaga: funkcja is_executable nie działa w przypadku ścieżek w cudzysłowach. – SWilk