2013-05-25 18 views
8

Tôi đã quản lý để chưng cất một trong các vấn đề cơ bản bắt nguồn từ câu hỏi của tôi How to trace _AddRef/_Release calls for OLE Automation objects trong đơn vị bên dưới.Tại sao WINWORD.EXE không thoát sau khi đóng tài liệu từ Delphi?

Tôi cũng sẽ trả lời câu trả lời này, chỉ trong trường hợp bất kỳ ai khác gặp phải vấn đề này.

Câu hỏi: với mã bên dưới, tại sao WINWORD.EXE không thoát (đôi khi nó thoát).

Đơn vị có thể có thể được cắt bớt nhiều hơn.

unit Unit2; 

interface 

uses 
    Winapi.Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, 
    Forms, Dialogs, StdCtrls, 
    WordXP; 

type 
    TForm2 = class(TForm) 
    WordXPFailsToQuitButton: TButton; 
    procedure WordXPFailsToQuitButtonClick(Sender: TObject); 
    private 
    FWordApplication: TWordApplication; 
    strict protected 
    function GetWordApplication: TWordApplication; virtual; 
    function GetWordApplication_Documents: Documents; virtual; 
    procedure WordApplication_DocumentBeforeClose(ASender: TObject; const Doc: _Document; var Cancel: WordBool); virtual; 
    procedure WordApplication_Quit(Sender: TObject); virtual; 
    property WordApplication: TWordApplication read GetWordApplication; 
    property WordApplication_Documents: Documents read GetWordApplication_Documents; 
    end; 

var 
    Form2: TForm2; 

implementation 

uses 
    Vcl.OleServer; 

{$R *.dfm} 

function TForm2.GetWordApplication: TWordApplication; 
begin 
    if not Assigned(FWordApplication) then 
    begin 
    FWordApplication := TWordApplication.Create(nil); 

    FWordApplication.AutoConnect := False; 
    FWordApplication.AutoQuit := False; 
    FWordApplication.ConnectKind := ckNewInstance; 
    FWordApplication.OnDocumentBeforeClose := WordApplication_DocumentBeforeClose; 
    FWordApplication.OnQuit := WordApplication_Quit; 
    FWordApplication.Connect; 
    end; 
    Result := FWordApplication; 
end; 

function TForm2.GetWordApplication_Documents: Documents; 
begin 
    Result := WordApplication.Documents; 
    if not Assigned(Result) then 
    raise EAccessViolation.Create('WordApplication.Documents'); 
end; 

procedure TForm2.WordXPFailsToQuitButtonClick(Sender: TObject); 
begin 
    try 
    WordApplication_Documents.Add(EmptyParam, EmptyParam, EmptyParam, EmptyParam); 
    WordApplication.Visible := True; 
    WordApplication.ActiveDocument.Close(False, EmptyParam, EmptyParam); 
    finally 
    WordApplication.OnQuit := nil; 
    WordApplication.OnDocumentBeforeClose := nil; 
    WordApplication.AutoQuit := True; 
    WordApplication.Disconnect; 
    WordApplication.Free; 
    FWordApplication := nil; 
    end; 
end; 

procedure TForm2.WordApplication_DocumentBeforeClose(ASender: TObject; const Doc: _Document; var Cancel: WordBool); 
begin 
    FWordApplication.Disconnect; 
end; 

procedure TForm2.WordApplication_Quit(Sender: TObject); 
begin 
    FWordApplication.Disconnect; 
end; 

end. 

Trả lời

6

trả lời phần 1:

Comment ra ngắt kết nối trong trường hợp dưới đây:

procedure TForm2.WordApplication_DocumentBeforeClose(ASender: TObject; const Doc: _Document; var Cancel: WordBool); 
begin 
// FWordApplication.Disconnect; 
end; 

Sự kiện này sẽ được gọi trong phương pháp DocumentClose (...), sau đó ngắt kết nối và xóa giao diện OLE từ cá thể FWordApplication.

Tôi chưa tìm ra tham chiếu nào đang treo lơ lửng, nhưng điều này giúp WINWORD.EXE hoạt động hiệu quả hầu hết các lần.

trả lời phần 2:

Đôi khi Winword.exe không bỏ vì sự kiện toe WordApplication_DocumentBeforeClose không được gọi. Lý do là mã chạy quá nhanh đến mức Word chưa được khởi tạo đầy đủ để thực hiện sự kiện.

Các vấn đề liên quan