终结部分没有在dll中运行

tmj*_*ac2 0 delphi twebbrowser

我正在尝试在Delphi XE2中创建一个DLL,它将弹出一个带有TWebBrowser组件的表单.调用WebBrowser.Navigate2方法时,应用程序结束时不会调用单元(或任何单元)的终结部分.如果未调用Navigate2,则终结部分就好了.

dll正在从C++(VS 2010 MFC控制台)调用,并通过导入库链接.

还有其他方法可以做到这一点,但我想重用我们已编写的代码.

有谁知道发生了什么事?

谢谢.

这是一个简单的问题重演:

library DisplayPatientAlertsIntf;
exports DisplayPatientAlertsA name 'DisplayPatientAlertsA@4';

begin
end.

unit uAlertWindow;

interface

uses
  Winapi.ActiveX,
  Forms,
  SHDocVw,
  Graphics, Controls;

function DisplayPatientAlertsA(PatientID : PAnsiChar): Integer; export; stdcall;

implementation

var ts : TStringList;

function DisplayPatientAlertsA(PatientID : PAnsiChar): Integer; export; stdcall;
  var Form1 : TForm;
      WebBrowser1 : TWebBrowser;
      DidCoInit : Boolean;
begin
  DidCoInit := Succeeded(CoInitialize(nil));
  try
    Form1 := TForm.Create(nil);
    try
      WebBrowser1 := TWebBrowser.Create(nil);
      try
        WebBrowser1.ParentWindow := Form1.Handle;
        WebBrowser1.Align := alClient;
        WebBrowser1.Navigate2('file://c:\temp.html');
        Form1.ShowModal;
      finally
        WebBrowser1.Free;
      end;
    finally
      Form1.Free;
    end;
  finally
    if DidCoInit then
      CoUninitialize;
  end;
  Result := 0;
end;

initialization
  ts := TStringList.Create;

finalization
  ts.Free;

end.
Run Code Online (Sandbox Code Playgroud)

更新2013.03.19 在解决另一个问题(dll中的dbExpress驱动程序)时,我将它从带有导入库的静态链接dll更改为动态加载的dll,一切都开始工作了.

Rem*_*eau 6

不要打电话CoInitialize()CoUninitialize()DLL的初始化/终止过程.这是一个非常糟糕的地方,而且,无论如何调用它们都不是DLL的责任.调用DLL函数的线程负责.如果你必须调用它们,那么至少在你导出的函数内部这样做.

至于导出的函数本身,使用WebBrowser1.Parent代替WebBrowser1.ParentWindow,Form1.Free代替Form1.Release,并Application.ProcessMessages完全摆脱.

最后,不要使用手动装饰的名称导出函数.这也不是DLL的责任.让编译器处理装饰.如果在导入函数时存在命名不匹配,则需要在调用应用程序中解决,而不是DLL本身.

您滥用COM和VCL(特别是因为只有在调用导出的DLL函数时才出现问题)可能会导致死锁,从而阻止DLL正确地从内存中卸载,因此它的所有终结部分都不会被调用,因为它的DLL入口点无法调用.COM在初始化/清理时非常敏感,因此您必须确保在正确的上下文中正确执行此操作.

试试这个:

library DisplayPatientAlertsIntf;

uses
  uAlertWindow;

exports
  DisplayPatientAlertsA;

begin
end.
Run Code Online (Sandbox Code Playgroud)

.

unit uAlertWindow;

interface

uses
  Winapi.ActiveX,
  Forms,
  SHDocVw,
  Graphics, Controls;

function DisplayPatientAlertsA(PatientID : PAnsiChar): Integer; stdcall;

implementation

function DisplayPatientAlertsA(PatientID : PAnsiChar): Integer; stdcall;
var
  Form1 : TForm;
  WebBrowser1 : TWebBrowser;
  DidCoInit: Boolean;
begin
  Result := 0;
  try
    DidCoInit = Succeeded(CoInitialize(nil));
    try    
      Form1 := TForm.Create(nil);
      try
        WebBrowser1 := TWebBrowser.Create(Form1);
        WebBrowser1.Parent := Form1;
        WebBrowser1.Align := alClient;
        WebBrowser1.Navigate2('file://c:\temp.html'); //This contains 'ASDF'
        Form1.ShowModal;
      finally
        Form1.Free;
      end;
    finally
      if DidCoInit then
        CoUninitialize;
    end;
  except
    Result := -1;
  end;
end;

end.
Run Code Online (Sandbox Code Playgroud)