mikehaertl / phpwkhtmltopdf

A slim PHP wrapper around wkhtmltopdf with an easy to use and clean OOP interface
MIT License
1.6k stars 238 forks source link

Warning: proc_open(): CreateProcess failed, error code - 2 #56

Closed Bilna75 closed 8 years ago

Bilna75 commented 10 years ago

Hi, I'm currently trying to use your wkhtmltopdf but I cannot get passed a Warning call saying :

Warning: proc_open() [function.proc-open]: CreateProcess failed, error code - 87 in Path/To/WkHtmlToPdf.php on line 325

I tried with a basic code given in the tutorial but it doesn't work.

$pdf = new WkHtmlToPdf; $pdf->addPage('http://google.com'); $pdf->send();

The error code 87 stands for invalid parameter. Anyone can help me ?

Thank you

mikehaertl commented 10 years ago

Sorry, I don't use Windows, so I can't really help. Other Windows users seem to have no problem with the library. You will have to play around with proc_open() yourself to find out, what's wrong. I'd try to build a simple PHP script and use more and more complex shell commands with proc_open().

Hope this helps.

tivie commented 9 years ago

There are a lot of issues with php proc_open on windows. See:

https://bugs.php.net/bug.php?id=51800

https://bugs.php.net/bug.php?id=60120

https://bugs.php.net/bug.php?id=65650

One workaround is to run the command yourself using exec().

However, as far as I know, there's no way to get the command woithout actually running it. I've created a pull request that should address this issue.

mikehaertl commented 9 years ago

If we wanted to fix this, we should do so in the underlying https://github.com/mikehaertl/php-shellcommand. But I'm hesitant to do so. proc_open() gives you full access to return value, STDIN and STDOUT. You can't do that with exec().

The problem seems only to happen with long output (longer than 4096 bytes) on windows.. So I wonder, if adding the quiet option doesn't fix the problem.

tivie commented 9 years ago

The problem seems only to happen with long output (longer than 4096 bytes) on windows.. So I wonder, if adding the quiet option doesn't fix the problem.

Unfortunately, this is not quite so simple. I've tested on two machines, a i7 3.4Ghz desktop and a dual Xeon E5-2695 server, both running the same exact OS and IIS 7.5)

On the desktop, the php script times-out when converting a 233Kb html file + 295K worth of images to a 757kb pdf. Increasing the time-out time (to hours) on php doesn't fix the problem. The strange thing is that while the script is running, the PDF in the temp directory is empty but immidiately after timing out, the PDF gets created correctly in the temp directory. I can't explain this behaviour.

Things get even weirder in the server. Sometimes the above script works without any problem, other times it behaves like the desktop. It's totally unreliable.

If we wanted to fix this, we should do so in the underlying https://github.com/mikehaertl/php- shellcommand. But I'm hesitant to do so. proc_open() gives you full access to return value, STDIN and STDOUT.

I agree. proc_open gives you more control over the process and works great on *nix environment. However, unless you're planning to add further features in error digest, as your script stands right now, there's no real difference in using exec or proc_open. Since you're not really digesting stdErr anyways, just using the exit code, passing a third argument to exec gets you the same result

What I propose is either:

mikehaertl commented 9 years ago

Since you're not really digesting stdErr anyways, just using the exit code, passing a third argument to exec gets you the same result

It is used. See https://github.com/mikehaertl/phpwkhtmltopdf/blob/master/src/Pdf.php#L248.

Things get even weirder in the server. Sometimes the above script works without any problem, other times it behaves like the desktop. It's totally unreliable.

So... there's an issue anyway, even on the shell? How can we know, that this is really related to proc_open() then? This sounds like a different problem to me.

I still recommend to try the quiet option with wkhtmltopdf. This should at least workaround the above proc_open() issues.

tivie commented 9 years ago

So... there's an issue anyway, even on the shell? How can we know, that this is really related to proc_open() then? This sounds like a different problem to me.

No, I might have not explained the issue clearly.

TEST 1

I created the following script (gist) and tested it in both my Desktop and my Home Server.

Results:

(produced phpWkHtmlToPdf command) wkhtmltopdf --no-outline --enable-local-file-access --encoding "UTF-8" --disable-smart-shrinking --margin-left "0" --margin-right "0" --margin-top "45mm" --margin-bottom "25mm" --header-html "F:\tmp\wktest\inc\header.html" --footer-html "F:\tmp\wktest\inc\footer.html" "htmlfile.html" "F:\tmp\tmpEAAD.tmp.pdf"

TEST 2

I changed mikehaertl\shellcommand\Command execute() method as seen in this gist, to use exec instead of proc_open().

Results

tivie commented 9 years ago

Since you're not really digesting stdErr anyways, just using the exit code, passing a third argument to exec gets you the same result

It is used. See https://github.com/mikehaertl/phpwkhtmltopdf/blob/master/src/Pdf.php#L248.

Yes, I know it's used but it's not being parsed. wkHtmlToPdf library writes progress to STDERR: see https://code.google.com/p/wkhtmltopdf/issues/detail?id=825. This is by deisgn since they support dumping the actual PDF to STDOUT.

So what I meant was: since your library does not really use STDOUT for anything, and since wkHtmlToPdf dumps the progress to STDERR, regardless of it having error messages, using proc_open or exec is the same thing.

Why?

Because you can pipe STDERR to STDOUT (and STDOUT to Nul) with exec and then read from it which, in pratical terms it's the same as reading from STDERR with proc_open.

GIST

public function execute()
{
    $command = $this->getExecCommand();

    if (!$command) {
        return false;
    }

    $command = $command . ' 2>&1';

    $lastLine = exec($command, $otp, $this->_exitCode);
    $this->_stdErr = implode('', $otp);

    if ($this->_exitCode!==0) {
        $this->_error = $lastLine ? $lastLine : "Failed without error message: $command";
        return false;
    }
    $this->_executed = true;
    return true;
}
mikehaertl commented 9 years ago

@tivie I've now update the php-shellcommand. You should be able to do this now:

<?php
use mikehaertl\wkhtmlto\Pdf;
$pdf = new Pdf([
    'commandOptions' => [
        'useExec' => true,
    ],
]);
...

Can you please help testing?

tivie commented 9 years ago

@mikehaertl Thanks Michael. I will be testing it and post the results soon.

tivie commented 9 years ago

@mikehaertl The new commandOption is working good (passed all my tests). However, error reporting is lacking. I've fixed this issue in this pull request. Michael, if you don't mind, please have a look.

tivie commented 9 years ago

@mikehaertl I've created a command exec library that address inconsistencies between linux and windows environments. You might wanna consider using it to build your lib commands.

https://github.com/tivie/command

If you wish, I can help you implement this.

mikehaertl commented 9 years ago

@tivie That looks nice. Maybe something to consider for a 3.0 release. On the other hand, from looking at the code I couldn't actually find a big difference in the core part (proc_open()). If you have some hints how to improve my php-shellcommand, I'm happy to include those changes. Your class makes sense for more advanced scenarios (method chaining, etc.). But our use case here is pretty simple. And I still believe in my own php-shellcommand implemenation ;).

BTW you may also hit this problem: https://github.com/mikehaertl/php-shellcommand/issues/6. Maybe worth adding to your class, too?

tivie commented 9 years ago

@mikehaertl thanks.

The only big difference is in the automatic selection of proc_open or exec based on OS (in windows it uses exec, otherwise uses proc_open.)

If you have some hints how to improve my php-shellcommand, I'm happy to include those changes

Maybe add this:

Those two would be awesome.

BTW you may also hit this problem: mikehaertl/php-shellcommand#6. Maybe worth adding to your class, too? Yeah, that's worth adding as an opt-in option when dealing with long outputs. Thanks for the suggestion. =)

doshu commented 7 years ago

use the bypass_shell options of proc_open to make it works on windows