0

The warning:

Warning: unlink(temp/1.pdf): Resource temporarily unavailable in C:\www\test.php on line 122

Warning: unlink(temp/2.pdf): Resource temporarily unavailable in C:\www\test.php on line 123

I'm using PHP's exec to run a batch file to perform some OCR, so the file cannot be deleted at the time the code is running, as CMD is busy creating the files. Once the files are created, I then use FPDF/FPDI to merge both PDFs, creating a new file in a different directory (merged/file.pdf)

So, what I need to do is wait for the batch file to finish executing, and for CMD to release the files so they can be deleted.

I just don't know how to do this.

$scriptName = 'wscript "launchquiet.vbs" "C:\www\OCR.bat"';
exec($scriptName,$out);
foreach($out as $key => $value) {echo $key." ".$value."<br>";}

That does not work, even though I should be forcing PHP to wait for the script's output by forcing it to wait for the script to finish.

I've also tried

exec('wscript "launchquiet.vbs" "C:\www\OCR.bat" &');

And

exec('wscript "launchquiet.vbs" "C:\www\OCR.bat" 2>&1 &');

With the & and 2>&1 &, which should (from Googling) force PHP to wait for the script to finish, but it doesn't.

So, my question namely becomes: is there a way to do this, forcing PHP to wait until the exec finishes; or, how do I make PHP wait, say, 10 seconds, upon deletion failure to try it again (and then wait again if there's another failure)

Edit: the code that does the deleting: unlink("temp/1.pdf"); and unlink("temp/2.pdf");

Edit 2: The whole code

exec('wscript "launchquiet.vbs" "C:\www\OCR.bat"');
    
PDF::Merge("temp/" . $newFileName . ".png", "temp/" . $newFileName . "_1.pdf", "temp/" . $newFileName . "_2.pdf", $newFileName);
unlink("OCR.bat"); // Delete Files
unlink("temp/" . $newFileName . ".png");
unlink("temp/" . $newFileName . "_1.pdf";
unlink("temp/" . $newFileName . "_2.pdf";
Community
  • 1
  • 1
Witold Kowelski
  • 924
  • 2
  • 12
  • 27
  • to answer your very last question: `while (1) { do some stuff; if stuff worked break; sleep(10); }` – But those new buttons though.. Nov 13 '18 at 04:19
  • can you please include the code the attempts to delete the file in question? I don't see anything like that in your question – But those new buttons though.. Nov 13 '18 at 04:26
  • Could you execute it all in PHP? This way you can check the process. Or wait for it to complete. – Twisty Nov 13 '18 at 04:26
  • @billynoah Added the unlink()'s. while (1) {unlink("temp/1.pdf"; if stuff worked break; sleep(10);} ... That's as far as I get. I don't know how to write the "if stuff worked" part...the closest thing I can think of is the "or die()", but I don't want it to die, just wait a few seconds. – Witold Kowelski Nov 13 '18 at 04:30
  • I'm asking you to include the code in context. I can see you used unlink but where? It doesn't make sense - the code above calls `exec()` and that would normally complete before the script continues. include *the actualy code you used* - we need an MCVE here – But those new buttons though.. Nov 13 '18 at 04:30
  • `unlink()` *"Returns TRUE on success or FALSE on failure."* - just check the return value – But those new buttons though.. Nov 13 '18 at 04:31
  • @Twisty I don't believe I can execute it in PHP, The OCR'ing needs to be done in the executable C:\Program Files (x86)\Tesseract-OCR\tesseract.exe, which is where the batch file points to and runs commands. – Witold Kowelski Nov 13 '18 at 04:32
  • `while (1) { if (unlink("temp/1.pdf")) { break; } sleep(10); }` – But those new buttons though.. Nov 13 '18 at 04:33
  • @billynoah I've edited it again. – Witold Kowelski Nov 13 '18 at 04:35
  • @WitoldKowelski what are you doing in the batch script that you can't do in PHP? – Twisty Nov 13 '18 at 04:35
  • @Twisty Taking a PNG file, running OCR on it, creating a just-text-layer PDF. Running OCR again, creating a HOCR file and TXT file, then running OCR again, just returning a PDF of the original image only...then I merge the image-only PDF with the text-only PDF in PHP after. – Witold Kowelski Nov 13 '18 at 04:38
  • @billynoah Fatal error: Maximum execution time of 30 seconds exceeded in C:\www\test.php on line 110 – Witold Kowelski Nov 13 '18 at 04:40
  • @billynoah It seems to me like my only option might be to just delete the files in the temp directory at a later time. Probably manually. Unless there's a way to get around that Fatal Error. – Witold Kowelski Nov 13 '18 at 04:41
  • @WitoldKowelski take a look at https://stackoverflow.com/questions/21353611/how-to-wait-for-a-process-executed-by-proc-open-in-php – Twisty Nov 13 '18 at 04:41
  • `ini_set('max_execution_time', 0);` – But those new buttons though.. Nov 13 '18 at 05:15
  • "On Windows `exec()` will first start cmd.exe to launch the command. If you want to start an external program without starting cmd.exe use `proc_open()` with the bypass_shell option set." – Twisty Nov 13 '18 at 05:37
  • @WitoldKowelski another example to look at: https://stackoverflow.com/questions/6014819/how-to-get-output-of-proc-open – Twisty Nov 13 '18 at 06:01

1 Answers1

1

Expanding on one of the examples I found, you could try the following code:

set_time_limit(1800);
ob_implicit_flush(true);

$scriptName = 'wscript "launchquiet.vbs" "C:\www\OCR.bat"';

$descriptorspec = array(
  0 => array("pipe", "r"),  // stdin
  1 => array("pipe", "w"),  // stdout -> we use this
  2 => array("pipe", "w")   // stderr 
);

$process = proc_open($scriptName, $descriptorspec, $pipes);

if (is_resource($process)){
  while( ! feof($pipes[1])){
    $return_message = fgets($pipes[1], 1024);
    if (strlen($return_message) == 0){
      break;
    }
    echo "$return_message<br />\r\n";
    ob_flush();
    flush();
  }
}

$exit=proc_close($process);
echo "exitcode $exit\r\n";

PDF::Merge("temp/" . $newFileName . ".png", "temp/" . $newFileName . "_1.pdf", "temp/" . $newFileName . "_2.pdf", $newFileName);
unlink("OCR.bat"); // Delete Files
unlink("temp/" . $newFileName . ".png");
unlink("temp/" . $newFileName . "_1.pdf";
unlink("temp/" . $newFileName . "_2.pdf";

This should launch the process, run through it, display STROUT, and then close the process before proceeding. This should wait and then closing the process should release any open files.

Hope that helps.

Twisty
  • 30,304
  • 2
  • 26
  • 45