从PHP exec()运行Windows上运行LibreOffice soffice.exe卡住了

时间:2018-05-09 10:09:08

标签: php windows iis libreoffice

我在使用LibreOffice 5.4.6中的soffice.exe将Word文档转换为PDF时出现问题 - 通过IIS在Windows Server 2012 R2上运行。

将目录更改为PHP(chdir)中的相关LibreOffice程序目录后,我在PHP中调用的命令是:

$cmd = "soffice.exe --headless -convert-to pdf -outdir ".sys_get_temp_dir()." ".$workingdoc;
exec($cmd);

其中 $ workingdoc 是.docx Word文件的完整路径。

我系统上的

sys_get_temp_dir()转换为C:\ Windows \ Temp

如果我将$ cmd变量回显给浏览器,然后在服务器上以交互方式将该输出复制粘贴到cmd.exe命令提示符中,则可以毫无问题地生成PDF。

例如,我复制粘贴到cmd.exe提示符中的回显$ cmd可能是:

soffice.exe --headless -convert-to pdf -outdir C:\Windows\TEMP C:\Windows\Temp\pdD125.docx

但是,在PHP中通过 exec()在与我交互式启动cmd.exe的用户上下文中运行此$ cmd变量只是挂起。我可以在任务管理器中看到soffice.exe,RAM使用率在10-20MB之间。此外,在我的C:\ Windows \ Temp文件夹中,我在soffice.exe保持运行时每秒都会连续创建多个空文件夹,所有文件的名称格式为 lu * .tmp

例如,生成的众多文件夹之一是 lu1124fq1pud.tmp

PDF不会被创建,并且允许PHP脚本完成并停止正在创建的 lu 文件夹(除了PHP超时)的唯一方法是强制结束soffice.exe任务任务经理。

那么,为什么soffice.exe命令在从cmd.exe调用时有效,但不能通过PHP调用,即使通过这两种方法在同一用户上下文中启动它们也是如此?

1 个答案:

答案 0 :(得分:0)

事实证明,这是一个已知的问题,reported here。简而言之,这似乎是用户权限问题。

我通过首先在系统的temp目录中创建一个临时的LibreOffice用户配置文件文件夹解决了我的问题(不要创建该目录,请允许soffice.exe对其进行初始化):

$tempLibreOfficeProfile = sys_get_temp_dir()."\\LibreOfficeProfile".rand(100000, 999999);

然后将 env 参数添加到soffice.exe命令:

$cmd = 'soffice "-env:UserInstallation=file:///'.str_replace("\\", "/", $tempLibreOfficeProfile).'" --headless --convert-to pdf -outdir "'.sys_get_temp_dir().'" '.$workingDoc;
exec($cmd);

确保完成后清理临时配置文件文件夹,以免阻塞您的温度,例如:

exec('rmdir /S /Q "'.$tempLibreOfficeProfile.'"');