私はLispで書かれたアプリケーションに取り組んでいます。プロセスを開始するためにFranzOLEを使用しています。それはExcelをうまく開きますが、インタラクティブにExcelを閉じると、プロセスはまだそこにあります。Excelウィンドウをインタラクティブに閉じるときにプロセスを強制終了する方法がわかりません。なにか提案を?
ありがとう
オートメーションによって Excel を起動すると、参照されている限り、Excel は存続します1。対話的に閉じても、必ずしもアプリケーションが終了するとは限りません。この場合、ole:remote-autotool
Excel がリリースされていないためです。
Excel を終了させる 1 つの方法は、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 InterfaceIUnknown
では、クライアント ラッパーの作成により、ガベージ コレクション時に基になるインターフェイス ポインターを解放するファイナライズが登録されます。
autotool はさらにもう 1 つのラッパーであり、IDispatch
クライアント ラッパー (すべての COM インターフェイスと同様に から継承) を含み、COM オートメーションの遅延バインディングIUnknown
と呼ばれるものを使用して、スクリプト言語と同じように使用を容易にします。autotool の参照を停止すると、基になる/クライアント ラッパーがガベージ コレクションされ、解放される可能性があります。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))
autotool のスケジュールされたファイナライズは、手動でリリースした後に失敗することはありません。の説明で発生することが文書化されているように、おそらくそのクラスが現在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 インスタンスが使用されている場合、その世代はガベージ コレクションが必要であり、多くの場合、グローバル GC で達成可能であり、ファイナライズして解放する必要があります。
3. Common Lisp では、オブジェクトのクラスを変更できます。