2015-12-05 3 views
0

Знает ли кто-нибудь, как создать объект word ole в DLL. У меня есть одно приложение, которое загружает DLL, которая, в свою очередь, создает объект word ole. Мое приложение краш каждый раз.Delphi word automation: Создать Ole Object внутри Dll

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

Уточнитните "аварии". MCVE тоже было бы неплохо. – kobik

ответ

1

Как указывает DavidH, CoNitialize должен быть вызван в вызывающей нити.

Точка наблюдения в связи с основным потоком приложения VCL заключается в том, что независимо от того, использует ли приложение VCL CoInitialize, зависит ли он от модуля ComObj: если он вызывает CoInitialize, вызывается через TApplication.Initialize и подпрограмма InitComObj в ComObj; Если это не так, вы должны должен сам позвонить (или CoInitializeEx).

Простой способ протестировать это - вызвать DLL из консольного приложения без TApplication - это позволит избежать того, что 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. 
+0

Это категорически неправильное решение. Потребитель должен нести ответственность за инициализацию COM. Кроме того, я не согласен с тем, что есть более подробная информация. Вы ничего не объясняете, ни инициализация COM, ни обработка исключений, оба из которых выполняются неправильно в вашем коде. –

+0

@DavidHeffernan: Вы, конечно, совершенно правы: мне удалось ввести себя в заблуждение, используя тестовое приложение для загрузки DLL, которое косвенно использует ComObj. Я обновил свой ответ, чтобы отразить это, и изменил вызывающее приложение на консольный, где, конечно же, CoInitialize не вызывается через TApplication, поэтому менее легко сделать вводящее в заблуждение тестовое приложение. – MartynA

2

Предполагая, что Слово установлен, то основная причина, почему вы код, возможно, не в том, что COM не был инициализирован в вызывающем потоке. Это не то, что должно быть предпринято в DLL, потому что вы хотите, чтобы DLL могла работать с потребителями, которые уже инициализировали COM.

Итак, правильный способ решения этой проблемы заключается в том, чтобы заявить как часть интерфейса интерфейса DLL, что COM должен быть инициализирован вызывающим абонентом. Обычно звоните CoInitialize или CoInitializeEx.

Еще один комментарий, заключается в том, что если приложение аварийно завершает работу, это говорит о том, что обработка ошибок нарушена. Все функции в вашей DLL должны предпринять шаги, чтобы поймать любые исключения и преобразовать в коды ошибок, которые будут возвращены вызывающему. Я подозреваю, что вы этого не сделали и выбрали исключение Delphi из DLL. Вы никогда не должны этого делать.

Обратите внимание, что я дал широкий и общий ответ. Это соответствует широкому характеру вопроса и тому факту, что в этом вопросе мало деталей. Если бы вы предоставили MCVE, мы могли бы предложить более подробный ответ.