Can't load package C:\Program Files (x86)\Neos Eureka S.r.l\EurekaLog 7\Packages\Studio25\EurekaLogExpert250.bpl. Access is denied.Причём клиент утверждал, что файл существует, доступ к нему есть, переустановка EurekaLog не помогает.
Дополнительно было установлено, что код из пакета
EurekaLogExpert250.bpl
действительно не получает управления (не выполняется).IDE использует ту же функцию
LoadPackage
из модуля SysUtils
, что и вы (ваш код). Никакого секретного кода IDE не выполняет. Функция LoadPackage
реализована следующим образом:
function LoadPackage(const Name: string; AValidatePackage: TValidatePackageProc): HMODULE; begin Result := SafeLoadLibrary(Name); if Result = 0 then raise EPackageError.CreateResFmt(@sErrorLoadingPackage, [Name, SysErrorMessage(GetLastError)]); // ----- try InitializePackage(Result, AValidatePackage); except FreeLibrary(Result); raise; end; end;где функция
InitializePackage
реализована так:
procedure InitializePackage(Module: HMODULE; AValidatePackage: TValidatePackageProc); type TPackageLoad = procedure; var PackageLoad: TPackageLoad; begin CheckForDuplicateUnits(Module, AValidatePackage); @PackageLoad := GetProcAddress(Module, 'Initialize'); //Do not localize if Assigned(PackageLoad) then PackageLoad else raise EPackageError.CreateFmt(sInvalidPackageFile, [GetModuleName(Module)]); end;Как вы можете видеть: единственным местом, где при загрузке пакета может возбуждаться исключение с кодом ошибки от ОС (5 =
ERROR_ACCESS_DENIED
) является помеченная строка. Откуда следует, что ошибка Access Denied при загрузке пакета может произойти только при неудачном вызове функции LoadLibrary
.Поэтому клиенту было предложено создать новое пустое VCL приложение с таким тестовым кодом:
procedure TForm1.Button1Click(Sender: TObject); var Lib: HMODULE; begin Lib := LoadPackage('C:\Program Files (x86)\Neos Eureka S.r.l\EurekaLog 7\Packages\Studio25\EurekaLogExpert250.bpl'); if Lib = 0 then RaiseLastOSError else MessageBox(0, 'The package was loaded!', 'Test', 0); end;Как оказалось, тестовое приложение успешно загружает пакет.
Чтобы точно быть уверенным, что IDE не выполняет никакого дополнительного скрытого кода, мы попросили клиента создать новые Design-Time пакет с модулем, содержащим только тестовый код:
unit Unit1; procedure Register; implementation uses Windows, SysUtils; procedure Register; var Lib: HMODULE; begin Lib := LoadPackage('C:\Program Files (x86)\Neos Eureka S.r.l\EurekaLog 7\Packages\Studio25\EurekaLogExpert250.bpl'); if Lib = 0 then RaiseLastOSError else MessageBox(0, 'The package was loaded!', 'Test', 0); end; end.И при попытке загрузить этот тестовый модуль IDE снова выдала сообщение об ошибке.
Сделаем промежуточный итог:
- Тестовое приложение успешно загружает пакет;
- Тестовый пакет (и IDE) не могут загрузить пакет.
Мы также попытались сделать следующее:Поскольку и мы, и клиент уже по сто раз проверили права доступа к файлуДанный алгоритм не дал никакой новой информации: в отладчике мы увидели, что в отлаживаемом процессе функция
- Запустить IDE (без EurekaLog);
- Открыть пункт меню Run / Load Process;
- Указать
bds.exe
как целевой процесс для отладки;- Запустить второй экземпляр IDE. При этом первый экземпляр будет отладчиком, а второй - отлаживаемым;
- В отлаживаемом процессе попытаться добавить пакет
EurekaLogExpert250.bpl
;- В отладчике следить за возникающими исключениями.
LoadLibrary
возвращает 0, что и приводит к возбуждению ошибки - как мы и предполагали выше.
EurekaLogExpert250.bpl
и не увидели проблем, нужно было делать что-то ещё.Пакет
EurekaLogExpert250.bpl
является Design-Time пакетом. Он зависит от Run-Time пакета EurekaLogCore250.bpl
. Это означает, что если функция LoadLibrary
загружает пакет EurekaLogExpert250.bpl
, то она увидит, что пакет EurekaLogExpert250.bpl
ссылается на EurekaLogCore250.bpl
и попробует загрузить и его. И если проблема возникла при загрузке пакета EurekaLogCore250.bpl
- она всплывёт на верхний уровень и будет возвращаена вызывающему функцией LoadLibrary
.Поэтому клиент также проверил файл
EurekaLogCore250.bpl
(он находится в папке C:\Windows\System32
) и не нашёл проблем.Далее мы попросили клиента использовать утилиту Process Monitor от Microsoft / SysInternals, чтобы пронаблюдать за тем, как IDE производит доступ к файлам. Необходимо было запустить IDE, открыть диалог добавления пакета, затем запустить Process Monitor и указать фильтр "Process Name=bds.exe => include". После чего попытаться добавить пакет, увидеть сообщение об ошибке и сохранить полученный отчёт.
В полученном отчёте мы запустили поиск по слову "Eureka" и сразу же увидели, что
bds.exe
смогла открыть и прочитать файл EurekaLogExpert250.bpl
- что дополнительно подтверждает, что с файлом EurekaLogExpert250.bpl
всё в порядке.А вот строчки сразу ниже ввели нас в недоумение: Process Monitor сообщил, что
bds.exe
пытается получить доступ к EurekaLogCore250.bpl
из папки \bin
IDE. Это странно, потому что современные версии EurekaLog не трогают папку \bin
IDE.(Очень) старые версии EurekaLog устанавливали файлы ecc32.exe в папкуНо когда мы попытались проверить права доступа к файлу\bin
IDE. Нам пришлось убрать это поведение, потому что современные версии IDE могут выбросить ошибку проверки целостности/лицензии, если в папке\bin
будут находиться сторонние файлы:
Question: I’ve installed and registered C++ Builder or Delphi, yet when it starts I am brought to a web page with the error “Product or License Validation Error”. How can I fix this?Поэтому современные версии EurekaLog не копируют никаких файлов в папку
Answer: By far the most common cause for this error is having files or applications not provided by Embarcadero that are copied into the bin folder below where RAD Studio is installed. Only files provided by Embarcadero may reside in the bin folder.\bin
IDE.
\bin\EurekaLogCore250.bpl
, то... не нашли такого файла!Как оказалось: дело в том, что
\bin\EurekaLogCore250.bpl
- это каталог! Тайна раскрыта!Итак, происходило следующее:
- IDE вызывает функцию
LoadPackage
для загрузки пакета; - Функция
LoadPackage
вызывает функциюLoadLibrary
для загрузки файлаEurekaLogExpert250.bpl
; - Функция
LoadLibrary
(успешно) открывает и читает файлEurekaLogExpert250.bpl
; - Функция
LoadLibrary
видит, что файлEurekaLogExpert250.bpl
содержит ссылку на файлEurekaLogCore250.bpl
; - Функция
LoadLibrary
пытается загрузить файлEurekaLogCore250.bpl
; - Функция
LoadLibrary
использует стандартные правила поиска библиотек операционной системы и видит, чтоEurekaLogCore250.bpl
находится прямо тут: в папке\bin
IDE; - Функция
LoadLibrary
пытается загрузитьEurekaLogCore250.bpl
из папки\bin
IDE; - Функция
LoadLibrary
возвращает ошибку 5 (Access Denied), поскольку папкаEurekaLogCore250.bpl
из папки\bin
IDE не имеет права доступа "EXECUTE".
И, действительно, всё заработало после удаления папки
EurekaLogCore250.bpl
из папки \bin
IDE.Но откуда взялась папка
EurekaLogCore250.bpl
в папке \bin
IDE? Я не знаю. Установщик EurekaLog сделан с помощью InnoSetup. Разумеется, установочный файл InnoSetup для EurekaLog понятия не имеет про установленные у вас IDE и каталоги, в которые они установлены. И поэтому установочный файл InnoSetup для EurekaLog не сможет создать там папку - просто потому, что он не знает, где это.Регистрация же EurekaLog в IDE производится программой регистрации:
.exe
файлом, скомпилированным в Delphi из нашего исходного кода. Проблема в том, что в нашем исходном коде для регистрации EurekaLog нет ни одного вызова MkDir
или ForceDirectories
: программа регистрации EurekaLog не создаёт каталогов, она копирует файлы и вносит данные о них в реестр Windows.Даже если бы
EurekaLogCore250.bpl
в папке \bin
IDE создавался нашим установщиком: почему это каталог, а не файл? И почему он один? Почему там же нет EurekaLogExpert250.bpl
и EurekaLogComponent250.bpl
- ведь эти три файла идут вместе.Пока всё выглядит так, словно кто-то создал каталог
EurekaLogCore250.bpl
в папке \bin
IDE. Возможно, это какой-то IDE эксперт?Если вы наш клиент, если вы увидели эту ошибку и знаете, кто создаёт каталог
EurekaLogCore250.bpl
в папке \bin
IDE - пожалуйста, сообщите нам.
Комментариев нет:
Отправить комментарий
Можно использовать некоторые HTML-теги, например:
<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>
Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и (опционально) ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку.
Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.
Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.
Примечание. Отправлять комментарии могут только участники этого блога.