Вопрос:

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

sql-server delphi vcl delphi-10.2-tokyo dbexpress

84 просмотра

1 ответ

467 Репутация автора

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

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

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, либо из вызывающей программы, в Чтобы решить эту ошибку, но я просто не могу понять, что это может быть, поэтому этот вопрос.

Автор: SiBrit Источник Размещён: 01.04.2019 04:53

Ответы (1)


0 плюса

467 Репутация автора

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

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

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

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

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

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

Автор: SiBrit Размещён: 12.06.2019 09:53
Вопросы из категории :
32x32