2013-05-25 9 views
8

Ich habe es geschafft, eines der zugrunde liegenden Probleme in meiner Frage How to trace _AddRef/_Release calls for OLE Automation objects in der folgenden Einheit zu destillieren.Warum wird WINWORD.EXE nach dem Schließen des Dokuments aus Delphi nicht beendet?

Ich werde diese Antwort auch beantworten, nur für den Fall, dass noch jemand in diese Frage hineinstößt.

Die Frage: mit dem folgenden Code, warum WINWORD.EXE immer nicht beendet (manchmal wird es beendet).

Das Gerät kann wahrscheinlich noch mehr getrimmt werden.

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. 

Antwort

6

Antwort Teil 1:

Kommentar aus dem disconnect im folgenden Fall:

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

Die Veranstaltung wird während der DocumentClose (...) -Methode, dann trennen und löschen aufgerufen werden die OLE-Schnittstelle von der FWordApplication-Instanz.

Ich habe noch nicht herausgefunden, welche Referenz baumelt, aber das hält effektiv WINWORD.EXE die meiste Zeit am Leben.

Antwort Teil 2:

Manchmal ist WINWORD.EXE nicht beenden, weil Zehen WordApplication_DocumentBeforeClose Ereignis nicht aufgerufen. Der Grund ist, dass der Code so schnell ausgeführt wird, dass Word noch nicht vollständig initialisiert ist, um das Ereignis auszuführen.

Verwandte Themen