XE6 ClientDataSet AV пытается загрузить данные из Firebird

У меня есть минималистский проект с FireDac FDConnection и FDSqlQuery, DataSetProvider и ClientDataSet, и я пытаюсь получить доступ к примеру Employee.FDB, который поставляется с пакетом Firebird 2.5, который я сегодня скачал с SourceForge.

Все установлено по умолчанию, поскольку они вышли из палитры, за исключением имени базы данных на всплывающей вкладке информации FDConnection и Sql FDQuery, для которого установлено значение select * from employee.

FDQuery открывается нормально, но как только я пытаюсь открыть CDS в среде IDE или запускаю свое приложение, я получаю нарушение прав доступа.

Это весь мой код:

  FDQuery1.Open;
  Caption := IntToStr(FDQuery1.RecordCount);  // this shows 42 on the form's caption
  CDS1.Open;  // AV here

Таким образом, FDQuery открывается нормально, а CDS — нет.

Во время выполнения здесь возникает исключение:

  function TCustomClientDataSet.CreateDSBase: IDSBase;
  begin
    CreateDbClientObject(CLSID_DSBase, IDSBase, Result);
    Check(Result.SetProp(dspropANSICODEPAGE, DefaultSystemCodePage)); <-- Exception here
    Check(Result.SetProp(dspropUTF8METADATA, NativeUInt(True)));
    Check(Result.SetProp(dspropUTF8ERRORMSG, NativeUInt(True)));
  end;

Сообщение об исключении

Проект FBTest1 поднял класс исключения $C0000005 с сообщением «нарушение доступа по адресу 0x0075d05b: чтение адреса 0x00000000».

В среде IDE я получаю аналогичное исключение, если пытаюсь установить Active = True на CDS, что, как сказано в сообщении, произошло в DSnap200.Bpl.

В первый раз, когда это произошло во время выполнения, у меня появилось всплывающее окно «Отчет об инциденте», предлагающее сообщить об этом в Embarcadero. Впервые такое вижу.

Если я подставлю SqlConnection и SqlQuery для компонентов FDac, я получу ту же ошибку.

Итак, я думаю, мой вопрос заключается в том, можно ли спровоцировать CDS на такое поведение, просто используя настройки свойств по умолчанию для такого простого проекта, как этот, то есть я пропустил какой-то шаг, или это, вероятно, вещь EMBA QC?


person MartynA    schedule 05.08.2014    source источник
comment
Зачем вам CDS1, FDQuery это уже ClientDataSet.   -  person Peter    schedule 06.08.2014
comment
Спасибо за ваш интерес. а) потому что я начал пытаться получить доступ к FB DB через DBX (что я все еще хочу сделать), и я хотел проверить, существует ли та же проблема с FD, что и происходит; б) я хочу получить сервер привязки данных с CDS в клиенте; и c), тем не менее, CDS не должен был так AV.   -  person MartynA    schedule 06.08.2014
comment
Похоже, что CreateDbClientObject(CLSID_DSBase, IDSBase, Result) возвращает nil в результате. Можно предположить, что он не может загрузить MIDAS.DLL или что-то в этом роде. Я бы подумал, что это вызовет ошибку времени выполнения, но кто знает. Вы можете попробовать добавить MidasLib в пункт использования вашего проекта.   -  person Graymatter    schedule 06.08.2014
comment
@Graymatter: Да. Утром попробую MidasLib. Дело в том, что я использую Midas и CDS со времен D5, почти ежедневно, почти никогда не возникает проблем, и у меня есть буквально десятки проектов CDS, но проблема есть только у этого.   -  person MartynA    schedule 06.08.2014


Ответы (1)


Решено! Благодаря предложению Graymatter попробовать использовать MidasLib, я добрался до сути проблемы и исправил ее, так что теперь приложение работает с Midas.Dll. Я публикую это как ответ, а не комментарий, во-первых, потому что это слишком длинно для этого, но, что более важно, причина была на самом деле довольно странной, и решение может помочь любому, кто столкнется с проблемой.

Во-первых, я попробовал использовать MidasLib, и приложение работало нормально, без AV, о котором идет речь.

Итак, убедившись, что проблема не возникает с текущим кодом MidasLib, я вернулся к попытке заставить приложение работать с Midas.Dll. Я проверил версии Midas.Dll в каталоге bin XE6 и \Windows\SysWOW64, и обе они оказались такими, как я и ожидал: 20.0.16277.1276 от 16 июня 2014 года.

Отслеживая CheckDBlient в DataSnap.DSIntf и внимательно наблюдая, копейка упала, и я понял, что происходит:

procedure CheckDbClient(const CLSID: TGUID);
[...]
begin
  [...]
      if DbClientHandle = 0 then
      begin
        Size := 256;
        SetLength(FileName, Size);
        if RegQueryValue(HKEY_CLASSES_ROOT, PChar(Format('CLSID\%s\InProcServer32',
          [GUIDToString(CLSID)])), PChar(FileName), Size) = ERROR_SUCCESS then
          SetLength(FileName, Size) else
        begin
        [...]
        end;
        DbClientHandle := LoadLibrary(PChar(FileName));

Это получает путь к Midas.Dll из ключа InProcServer в его регистрации, и это указывало не на каталог bin XE6 или SysWOW64, а на другое место, которое не было моим созданием и которое содержало версию Midas.Dll, начиная с 2007. Как ни странно, в отличие от имеющейся у меня копии Dll эпохи D7, эта Dll не имеет информации о версии на странице свойств, но имеет дату создания 9 августа 2002 г. и размер файла 351 КБ.

Итак, как только я это обнаружил, решить проблему было так же просто, как переименовать эту Dll, чтобы ОС не загружала ее, и перерегистрировать версию в SysWOW64.

Откуда взялся мошеннический Midas.Dll, неясно, но он определенно прибыл с прошлой недели, потому что его нет в резервной копии, которая у меня была с вечера прошлого четверга.

Единственное, что я установил с тех пор, — это несколько сторонних утилит с графическим интерфейсом для управления/доступа к базам данных Access, IB и Firebird, поэтому виновником, похоже, была одна из них.

person MartynA    schedule 06.08.2014