2013-05-25 21 views
8

Sono riuscito a distillare uno dei problemi sottostanti radicato nella mia domanda How to trace _AddRef/_Release calls for OLE Automation objects nell'unità sottostante.Perché WINWORD.EXE non si chiude dopo aver chiuso il documento da Delphi?

Risponderò anche a questa risposta, nel caso in cui qualcun altro si imbattesse in questo.

La domanda: con il codice seguente, perché WINWORD.EXE non esce sempre (a volte non esce).

Probabilmente l'unità può essere ritagliata ancora di più.

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. 

risposta

6

Risposta parte 1:

commento la disconnessione in caso di seguito:

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

L'evento sarà chiamato durante il metodo DocumentClose (...), quindi scollegare ed eliminare l'interfaccia OLE dall'istanza FWordApplication.

Non ho ancora capito quale riferimento pende, ma ciò mantiene in modo efficace WINWORD.EXE vivo la maggior parte delle volte.

Risposta parte 2:

volte WINWORD.EXE non uscire perché evento punta WordApplication_DocumentBeforeClose non viene chiamato. Il motivo è che il codice viene eseguito così velocemente che Word non è ancora completamente inizializzato per eseguire l'evento.

Problemi correlati