当 Apache 通过任务计划程序启动时,在 Windows 7 上通过 COM 从 PHP 5 调用 Excel 失败
嘿伙计们,这个问题不会太复杂。请提供一个解决方案,至少找出问题的最终根源。
我目前编写了一个应用程序,它通过 COM 控制 Excel:该应用程序创建一个 COM-基于 Excel 实例,打开一些 XLS 文件并读取其内容。
场景 I
在 Windows 7 上,我使用 具有系统管理员权限的 xmapp-control 启动 Apache 和 mySQL。一切都按预期进行。基于 PHP 的控制器脚本按预期与 Excel 进行交互。
场景 II
如果我将 Apache 和 mySQL 作为“后台作业”启动,则会出现问题。操作方法如下:
- 我使用 Windows 7 任务计划程序 创建了两个作业。一个运行 apache_start.bat,另一个运行 mysql_start.bat。
- 当 Windows 7 启动时,这两个任务都以具有提升权限的 SYSTEM 身份运行。
Apache 和 mySQL 按预期工作。具体来说,Apache 处理来自客户端的 HTTP 请求,并且 PHP 能够与 mySQL 通信。
当我调用 PHP 控制器(该控制器使用 COM 调用 Excel 并与之交互)时,我确实收到了错误。
错误消息来自 Excel [不是 COM 本身],内容如下:
- Excel 无法读取指定的 Excel 文件
- 由于工作表名称不正确,Excel 无法保存文件
有趣的是,第一个在首次运行基于 PHP 的控制器脚本期间,需要几秒钟的时间来呈现错误消息。随后的每次运行都会立即呈现错误消息。
Windows 系统日志未显示任何问题报告条目。
请注意,PHP 程序和 Apache 实例没有改变 - 除了 Apache 的启动方式之外。
至少 PHP 控制器脚本完全能够读取文件系统,因为它通过某个目录的 scandir() 提供 XLS 文件的路径。
并发问题不可能是问题的原因。特定 PHP 控制器的单个实例与 Excel 交互。
问题
有人可以提供详细信息,为什么会发生这种情况?或者提供隔离问题最终原因的方法(例如通过 PowerShell 2 脚本)?
UPDATE-1 :: 2011-11-29
根据建议,我将任务计划程序作业从 SYSTEM 切换到传统用户。作品。 Apache 和 MySQL 启动并处理请求。
不幸的是,Excel 的情况没有一点改变。尽管如此,我还是看到了错误。
如前所述,EXCEL COM 服务器启动。我可以通过 COM 实例毫无问题地更改各种设置(例如抑制对话框)。
调用此方法时会出现问题:
$excelComObject->Workbooks->Open( 'PathToXLSFile' );
UPDATE-2 :: 2011-11-30
添加了具有可读权限的帐户 USER、GUEST 和 EVERYONE 的访问控制列表XLS 文件。没有变化。
以这样的方式修改应用程序,PHP 部分创建 XLS 文件的副本作为临时文件,并将原始文件的内容移动到其中。只是为了确保问题不是由奇怪的文件/路径名造成的。
问题仍然存在。
UPDATE-2 :: 2011-12-05
我将以 Excel 创建的方式发送 EXCEL COM-Server 方法一个空白文件并将其保存到/tmp。让我们看看 Excel 是否无法读取该文件。
Hey folks, this question can't be too complicated. Please provide a solution to at least figure out the ultimate root cause of the problem.
I currently write an application, which controls Excel through COM: The app creates a COM-based Excel instance, opens some XLS files and reads their contents.
Scenario I
On Windows 7, I start Apache and mySQL using xmapp-control with system administrator rights. All works as expected. The PHP-based controller script interacts with Excel as expected.
Scenario II
A problem appears, if I start Apache and mySQL as 'background jobs'. Here is how:
- I created two jobs using Windows 7 Task Planner. One runs apache_start.bat, the other runs mysql_start.bat.
- Both tasks run as SYSTEM with elevated privileges when Windows 7 boots.
Apache and mySQL work as expected. Specifically, Apache serves HTTP request from clients and PHP is able to talk to mySQL.
When I call the PHP controller, which calls and interacts with Excel using COM, I do receive an error.
The error message comes from Excel [not COM itself] and reads like this:
- Excel can't read the specified Excel-file
- Excel failed to save the file due to an ill-name worksheet
Interestingly, the first during the first run of the PHP-based controller script, it takes a few seconds to render the error message. Each subsequent run immediately renders the error message.
Windows system logs didn't show a single problem report entry.
Note, that the PHP program and the Apache instance didn't change - except the way Apache was started.
At least the PHP controller script is perfectly able to read the file-system, since it provides the pathes to the XLS-file through scandir() of a certain directory.
Concurrency issues can't be the cause of the problem. A single instance of the specific PHP controller interacts with Excel.
Question
Could someone provide details, why this happens? Or provide ways to isolate the ultimate cause of the problem (e.g. by means of a PowerShell 2 script)?
UPDATE-1 :: 2011-11-29
As proposed, I switched the Task Planner job from SYSTEM to a conventional user. Works. Apache and MySQL get started and process request.
Unfortunately, the situation regarding Excel did't change a bit. Still, I see the error.
As assumed earlier, the EXCEL COM server starts. I'm able to change various settings (e.g. suppress dialogs) without a problem through the COM-instance.
The problem happens while calling this:
$excelComObject->Workbooks->Open( 'PathToXLSFile' );
UPDATE-2 :: 2011-11-30
Added the accounts USER, GUEST and EVERYONE with the READABLE right to the access control list of the XLS file . No change.
Modified the app in such a way, that the PHP part creates a copy of the XLS file as a temporary file and moves the contents of the original file into this. Just to ensure, that the problem isn't forced by odd file / path names.
Still, the problem persists.
UPDATE-2 :: 2011-12-05
I'm going to send the EXCEL COM-Server methods in such a way, that Excel creates a blank file and saves it to /tmp. Let's see, if Excel even isn't able to read this file.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
进入任务计划程序并让一切以本地用户身份运行。这可能需要您输入密码,因此如果您还没有密码,请创建一个。
Excel 是一个用户级应用程序,不应以系统身份运行。我确信有办法解决这个问题,但你应该让一切都在正确的水平上运行。
让 Apache 在用户级别运行不是问题。
Go into the task planner and let everything run as a local user. This will probably require that you enter a password so create one if you don't have one already.
Excel is a user-level application that shouldn't run as SYSTEM. I'm sure there are ways around it, but you should simply let everything run at the correct level.
Having Apache run on the user level isn't a problem.
尝试创建以下目录:
它对我有用:-)
http://social.msdn.microsoft.com/Forums/en-US/innovateonoffice/thread/b81a3c4e-62db-488b-af06-44421818ef91
Try creating the following directories:
it worked for me :-)
http://social.msdn.microsoft.com/Forums/en-US/innovateonoffice/thread/b81a3c4e-62db-488b-af06-44421818ef91
过去(阅读:Vista 之前)服务有一个名为“允许服务与桌面交互”的选项,该选项允许服务生成窗口等。从 Vista 开始,不再允许这样做。
我怀疑 Excel 失败了,因为它无法在此限制下运行。因此,任何在 Win7 安装中将其作为服务运行的尝试都会失败。
您可以使用 Windows XP 并允许 Apache 进程进行桌面交互,但由于显而易见的原因,我并不真正推荐这样做。
我采取的另一种方法是创建一个 PHP 脚本,该脚本作为常规进程运行并在无限循环中侦听套接字。在 Apache 下运行的 PHP 脚本将通过本地套接字与辅助脚本进行通信,并使辅助脚本生成 Excel。
这听起来可能很复杂,但实际上它并不是很多代码,而且它解决了您很快就会遇到的问题:您应该只运行一个 Excel 实例,否则可能会遇到问题。辅助脚本可以对请求进行排队,将请求逐一移交给 Excel,然后获取队列中的下一个请求。
In the past (read: pre Vista) services had an option called "Allow Service to interact with desktop" which allowed services to spawn windows etc. Starting Vista, this is no longer allowed.
I suspect Excel is failing because it can't function under this restriction. Thus, any attempt to run it as a service in your Win7 installation will fail.
You can Windows XP and allow desktop interaction for your Apache process, which I don't really recommend for obvious reasons.
Another approach I would take is to create a PHP script that runs as a regular process and listens on a socket in an infinite loop. Your PHP script that runs under Apache would communicate with the secondary script through the local socket and have the secondary script spawn Excel.
This may sound complicated but in fact it's not a lot of code and it fixes a problem you will soon have anyway: You should only have one instance of Excel running or you may run into problems. The secondary script could queue requests, handing off one by one to Excel then taking the next in the queue.