216 Ошибка, выдаваемая токийской программой Delphi 10.2 при подключении к SQL через DLL-библиотеку Delphi - PullRequest
1 голос
/ 01 апреля 2019

Мы сообщали об этой ошибке в течение нескольких лет, и теперь мне нужно потратить некоторое время на ее исправление.

Несколько упоминанийэто из других источников:

https://forums.embarcadero.com/thread.jspa?threadID=112713

https://forums.devart.com/viewtopic.php?t=37398

https://forums.devart.com/viewtopic.php?f=10&t=16520

Я открыл тикет с DevArt, дав им копиюмоей тестовой программы и dll, но они совершенно справедливо ответили, что проблема возникает даже без драйверов DevArt, что я подтвердил, используя стандартный драйвер MSSQL, поставляемый с 10.2 Tokyo Enterprise, и вообще без драйверов DevArt.

DLL имеет одну функцию:

exports
  CheckConnection;

А вот код модуля в DLL:

unit Unit7;

interface

uses
  System.SysUtils, Data.SqlExpr, Data.DBXMSSQL;

function CheckConnection(const ServerName, DatabaseName, UserName, Password: PAnsiChar): Boolean; stdCall export;

implementation

function CheckConnection(const ServerName, DatabaseName, UserName, Password: PAnsiChar): Boolean; stdCall export;
var
  SQLConnection: TSQLConnection;
begin
  SQLConnection := TSQLConnection.Create(nil);

  try
    SQLConnection.DriverName := 'MSSQL';
    SQLConnection.LibraryName := 'dbxmss.dll';
    SQLConnection.VendorLib := 'sqlncli10.dll';
    SQLConnection.GetDriverFunc := 'getSQLDriverMSSQL';

    SQLConnection.Params.Values['HostName'] := ServerName;
    SQLConnection.Params.Values['Database'] := DatabaseName;
    SQLConnection.Params.Values['User_Name'] := UserName;
    SQLConnection.Params.Values['Password'] := Password;

    SQLConnection.LoginPrompt := False;
    SQLConnection.Open;

    Result := SQLConnection.Connected;
  finally
    SQLConnection.Close;
    FreeAndNil(SQLConnection);
  end;
end;

end.

Эта строка реализации позволяет использовать функцию DLL из основной программы:

function CheckConnection(const Server, Database, User, Password: PAnsiChar): Boolean; stdCall; external 'Project3.dll';

А вот код события нажатия кнопки для вызова DLL:

procedure TForm8.Button1Click(Sender: TObject);
var
  Server, Database, User, Password: AnsiString;
begin
  Server := Edit1.Text;
  Database := Edit2.Text;
  User := Edit3.Text;
  Password := Edit4.Text;

  if CheckConnection(@Server[1], @Database[1], @User[1], @Password[1]) then
    Label1.Caption := 'DLL connected OK'
  else
    Label1.Caption := 'DLL did not connect';
end;

Проблема связана с циклом в TDBXDriverRegistry.CloseAllDrivers , гдеэто звонит TDBXDriverRegistry.DBXDriverRegistry.FreeDriver для каждого установленного / используемого драйвера dbExpress.

Когда вызывается FreeDriver , поток выполнения переходит к этому методу:

destructor TDBXDynalinkDriver.Destroy;
begin
  if FMethodTable <> nil then
    FMethodTable.FDBXBase_Close(FDriverHandle);
  FDriverHandle := nil;
  FreeAndNil(FMethodTable);
  inherited Destroy;
end;

Это строка FMethodTable.FDBXBase_Close (FDriverHandle); , которая генерирует нарушение прав доступа, и поскольку она не перехватывается, она вызывает ошибку 216 в вызывающей программе.

Этот вызовпроисходит сбой только на последнем освобожденном драйвере, и только если мы действительно открываем TSQLConnection .

Учитывая мой опыт использования компонентов DevExpress VCL в DLL, где вам нужноЧтобы вызвать dxInitialize и dxFinalize для правильной работы с GDIPlus, я могу только думать, что нужно что-то делать либо в DLL, либо из вызывающей программы, чтобыустранить эту ошибку, но я просто не могу понять, что это может быть, поэтому этот вопрос.

1 Ответ

1 голос
/ 13 июня 2019

Я получил ответ от Embarcadero, в котором говорится, что мы должны добавить AutoUnloadDriver = True к параметрам в

"избегать проблем с оформлением заказа".

Единственное место, где мы можем добавить это и внести какие-либо изменения (в том, что оно исправило ошибку 216), находится в блоке [MSSQL] файла dbxdrivers.ini.

http://edn.embarcadero.com/article/39392/

DevArt сообщила мне, что теперь они добавили поддержку параметра AutoUnloadDriver в свой драйвер dbExpress для SQL Server . Они прислали мне ночную сборку, которая включала это исправление, поскольку его еще нет в их публичной версии.

С файлом dbxdrivers.ini в папке установки приложения и с параметром AutoUnloadDriver = True , добавленным в разделы [MSSQL] и [DevArtSQLServer], мы больше не получаем любые ошибки 216 при закрытии приложений, в которых для подключения к SQL Server использовалась DLL.

...