我正在开发一个用 Lisp 编写的应用程序。我正在使用 Franz OLE 启动该过程。它打开excel很好,但是当我以交互方式关闭excel时,这个过程仍然存在。当我以交互方式关闭 excel 窗口时,我不确定如何终止该进程。有什么建议吗?
谢谢
当您通过自动化启动 Excel 时,只要它被引用1 ,它就会一直保持活动状态。以交互方式关闭它并不一定会退出应用程序,在这种情况下,因为您的ole:remote-autotool
for Excel 尚未发布。
让 Excel 退出的一种方法是去掉 autotool 包装器,例如,如果您有一个存储在变量或对象的插槽中,请将其值设置为nil
:
(let ((excel-app (ole:ask-for-autotool "Excel.Application"
ole:CLSCTX_LOCAL_SERVER)))
;; ...
;; Break the reference to all autotool wrappers you no longer need
(setf excel-app nil))
在 Allegro CL 的OLE 接口IUnknown
中,客户端包装器的创建注册了一个终结,该终结在它被垃圾收集时释放底层接口指针。
自动工具是另一个包装器,它包含一个IDispatch
客户端包装器(它继承自IUnknown
,就像所有 COM 接口一样),以与脚本语言相同的方式简化它的使用,即COM 自动化中的后期绑定。当您停止引用自动工具时,底层IDispatch
/IUnknown
客户端包装器可能会被垃圾收集,从而被释放。
但是,Excel 可能不会以这种方式立即退出,除非您期望或强制进行垃圾回收2。如果您希望 Excel 在没有交互的情况下立即退出,您应该将Quit
ExcelDisplayAlerts
设置为 false,然后设置ole:release
您的 autotool 对象(注意:我没有彻底测试过这个):
(let ((excel-app (ole:ask-for-autotool "Excel.Application"
ole:CLSCTX_LOCAL_SERVER)))
;; ...
;; Disable prompts asking to save unsaved workbooks
;; They will not be saved
(setf (ole:auto-getf excel-app "DisplayAlerts") nil)
(ole:auto-method excel-app "Quit")
;; Manually release all autotool wrappers you no longer need
(ole:release excel-app))
自动工具的预定完成在我们手动发布后不会失败。它检查底层接口指针包装器是否已被释放,可能通过检查其类现在是否为ole::released-IUnknown
3,因为它被记录在ole:release (ole:IUnknown-Client)
.
还有一种蛮力方式使用ole:release-process-client-interfaces
,但您应该确保您不会访问到目前为止在当前 lisp 进程(线程)中创建的任何 OLE 对象:
(mp:process-run-function
"Excel worker"
#'(lambda ()
(ole:start-ole)
(unwind-protect
(let ((excel-app (ole:ask-for-autotool "Excel.Application"
ole:CLSCTX_LOCAL_SERVER)))
;; ...
;; Disable prompts asking to save unsaved workbooks
;; They will not be saved
(setf (ole:auto-getf excel-app "DisplayAlerts") nil)
(ole:auto-method excel-app "Quit")
;; Make sure this is the last thing you do, the wrappers
;; created in the current process will become invalid
(ole:release-process-client-interfaces))
;; Given this call, the brute force doesn't make much sense anyway
(ole:stop-ole))))
1.只要持有任何注册工厂的锁或保留对由 excel.exe 创建的任何对象的引用,它就应该继续运行。这对于进程外服务器来说是正常的。
2.如果您的 autotool 实例已使用tenured,则需要对它的生成进行垃圾收集,这通常可以通过全局 GC 来实现,然后最终确定并释放。
3.在 Common Lisp 中,您可以更改对象的类。