简体   繁体   中英

Delphi word automation: Create Ole Object inside Dll

Does anyon know how to create word ole object in DLL. I have one application that load a DLL which in turn create word ole object. My application crash every time.

MSWord:= CreateOleObject('Word.Application');

Assuming that Word is installed, then the primary reason why you code might fail is that COM has not been initialized in the calling thread. That is not something that should be attempted from the DLL, because you want the DLL to be able to work with consumers that have already initialized COM.

So, the correct way to tackle this is to state as part of the DLL's interface contract that COM must be initialized by the caller. Typically by calling CoInitialize or CoInitializeEx .

One further comment, is that it if the application crashes, that suggests that you error handling is broken. All the functions in your DLL should take steps to catch any exceptions and convert into error codes to be returned to the caller. I suspect that you have not done this and are throwing a Delphi exception out of the DLL. You must never do that.

Note that I have given a broad and general answer. That matches the broad nature of the question, and the fact that there are few details in the question. If you had provided an MCVE we could have offered a more detailed response.

As DavidH points out, CoInitialize has to be called in the calling thread.

A point to watch out for in connection with the main thread of a VCL application is that whether a VCL application calls CoInitialize automatically depends on whether it uses the ComObj unit: if it does the CoInitialize is called via TApplication.Initialize and the InitComObj routine in ComObj; if it does not, you must call it (or CoInitializeEx) yourself.

The easy way to test this is to call the DLL from a TApplication-less console application - this will avoid being misled by ComObj being used some other than your main unit.

Suppose you have a DLL that contains the following exported procedure:

procedure CreateWordDoc;
var
  DocText : String;
  MSWord,
  Document : OleVariant;
begin
  MSWord := CreateOleObject('Word.Application');
  MSWord.Visible := True;
  Document := MSWord.Documents.Add;
  DocText := 'Hello Word!';
  MSWord.Selection.TypeText(DocText);
end;

then you could call it like this:

program WordCaller;

{$APPTYPE CONSOLE}

uses
  SysUtils, Windows, ActiveX;

type
  TWordProc = procedure;

var
  LibHandle : THandle;
  WordProc : TWordProc;
begin
  CoInitialize(Nil);
  LibHandle := LoadLibrary('WordDll.Dll');
  try
    if LibHandle <> 0 then begin
      try
        WordProc := GetProcAddress(LibHandle, 'CreateWordDoc');
         if Assigned(WordProc) then
             WordProc;
       finally
         FreeLibrary(LibHandle);
       end;
    end;
  finally
    CoUnInitialize;
    Readln;
  end;
end.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM