是否知道如何在DLL中创建单词ole对象。 我有一个应用程序加载DLL,后者又创建word ole对象。 我的应用程序每次都崩溃。
MSWord:= CreateOleObject('Word.Application');
答案 0 :(得分:2)
假设安装了Word,那么代码可能失败的主要原因是COM尚未在调用线程中初始化。这不应该从DLL中尝试,因为您希望DLL能够与已经初始化COM的消费者一起工作。
因此,解决这个问题的正确方法是声明DLL的接口契约的一部分,COM必须由调用者初始化。通常可以致电CoInitialize
或CoInitializeEx
。
另一个评论是,如果应用程序崩溃,则表明您的错误处理已被破坏。 DLL中的所有函数都应采取措施捕获任何异常并转换为错误代码以返回给调用者。我怀疑你没有这样做,并从DLL中抛出一个Delphi异常。你绝不能这样做。
请注意,我已经给出了广泛而一般的答案。这符合问题的广泛性质,以及问题中的细节很少。如果您提供了MCVE,我们可以提供更详细的回复。
答案 1 :(得分:1)
正如DavidH指出的那样,必须在调用线程中调用CoInitialize。
与VCL应用程序的主线程相关的一点是,VCL应用程序是否自动调用CoInitialize取决于它是否使用ComObj单元:如果是,则通过TApplication.Initialize调用CoInitialize并且ComObj中的InitComObj例程;如果没有,你必须自己调用它(或CoInitializeEx)。
测试这个的简单方法是从无TApplication的控制台应用程序调用DLL - 这样可以避免被Comobj误用到主单元以外的其他地方。
假设您有一个包含以下导出过程的DLL:
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;
然后你可以这样称呼它:
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.