Search code examples
phpexecpsexec

PHP exec(psexec.exe) hangs indefinitely


I have a development / testing setup on a windows box and need to test calling a background process. I am using http://www.somacon.com/p395.php as a list of options for running a background service.

Here is the sample code I am trying to run:

$string = "PsExec.exe -d cmd /c \"mspaint\"";
echo $string;
exec($string, $data);

This works when I type it into the command line.

I haven't attempted to do a lot of exec's on Windows, but it would be nice to be able to test it locally before moving to a Linux box.

Right now, I am thinking it has something to do with the fact that psexec opens a new window? I don't know how to fix that, however.

There are no apache or PHP error logs being generated, the page just never stops. This also seems to override PHP's max execution time.


Solution

  • EDIT:

    This is not fully correct answer. The command psexec \\machine cmd.exe /C 1 & dir won't hang because psexec first return saying that command 1 doesn't exists in remote machine and then dir is evaluated in the local machine. I got tricked by cmd operator order. The & operator is being invoked in the local cmd.exe process, not the remote one. But the logic still applies if you quote the command: psexec \\machine cmd.exe /C "1 & dir".

    Original Answer:

    There is something strange going on while invoking psexec within PHP in windows. No matter if you are using shell_exec(), exec(), popen() or proc_open(). It will hang anyway.

    Honestly I don't know what's going on, you could also download PsExplorer in order to trace your process command line, arguments, etc. You'll find this tool very useful.

    I'm using XAMPP on Windows, and after certain tests I found this:

    First of all create a test file (i.e. test.php) and place it in your web server so you can access it with this content:

       <?php
          echo "<pre>".shell_exec("psexec \\\\machine <options> cmd.exe /C dir")."</pre>";
       ?>
    

    Note that you could use GET arguments in order to create a more flexible example. To debunk that this indeed is working before you test over a webpage, issue the command php <path-to-the-file>\test.php. That will work perfectly. But, it won't work on a web browser.

    If you kill the process, you'll get the first line: El volumen de la unidad C no tiene etiqueta.. Next line, in my language there's an accent included so I thought It could be encoding (or code pages) issues. So instead of cmd.exe /C dir I tested cmd.exe /C chcp 850 && dir. That, for my surprise, works.

    Then, I realize that no matter what command you set before it will also work, for instance, cmd.exe /C 123 & dir (note the single & as I'm not evaluating the command output).

    Honestly, I don't know what is going on with psexec and PHP via web browser. More surprisingly, commands like cmd.exe /C copy cmd.exe cmd.exe.deleteme and cmd.exe /C mkdir deletethis will work!

    So, you could give it a try to cmd.exe /C 1 & \"mspaint\" as your problem and my seems similars. For single commands could be a workaround but I'm developing an unattended framework for installing software and all my files are .cmd or .exe or .bat files.

    Let me know If you found something interesting :)