Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
 Загрузка библиотеки и функций из неё  [new]
Ss`st
Guest
Делаю проект, аудитория 200 человек. И на днях обратился ко мне пользователь, сказал что у него ничего не работает (AV)

Опытным путём было выявлено, что библиотека собранная на c++ не в какую не хочет у него работать (Не найдена dll)

От админа запуск приводил к AV

Я пересоздал все импорты со стандартной загрузки ; cdecl; external libraryPath name 'NameFunction';

На
+
function HRESULTStr(h: HRESULT): LPWSTR;
begin
  FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_FROM_SYSTEM,
    nil, h, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), @result, 0, nil);
end;

procedure LoadPHPFunc(var func: pointer; FuncName: LPCSTR);
const
  dll = 'DllName.dll';
begin
  if DllHandle = 0 then
    if FileExists(dll) then
    begin
      DllHandle := GetModuleHandlew(dll);
      if DllHandle = 0 then
        DllHandle := LoadLibraryw(dll);
      if DllHandle = 0 then
      begin
        ShowMessage('Не смог иницилизировать библиотеку (' + dll + ')' +
          HRESULTStr(GetLastError) + #10#13 + '- ' + dll);

        Exit;
      end;
    end;

  func := GetProcAddress(DllHandle, FuncName);
  if not assigned(func) then
    MessageBoxW(0, Pchar('Unable to link [' + FuncName + '] function'),
      'LoadFunction', 0);
end;



И того, без прав админа выводится сообщение "Не смог инициализировать библиотеку (DllName.dll) - DllName.dll"

При запуске от админа Unable to link [FunctionName] function


В чём может быть проблема ?
11 июн 18, 16:43    [21484724]     Ответить | Цитировать Сообщить модератору
 Re: Загрузка библиотеки и функций из неё  [new]
Лисъ
Guest
Ставлю на то, что DLL-ка не может подгрузить свои зависимости (например не установлена корректная версия сишного рантайма).

Смотри от чего зависит DLL-ка: туд
11 июн 18, 17:07    [21484741]     Ответить | Цитировать Сообщить модератору
 Re: Загрузка библиотеки и функций из неё  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 10313
Ss`st
В чём может быть проблема ?
dll у пользователя не той версии, что вы ожидаете. Или просто ее нет.

А код загрузки должен быть такой
procedure LoadPHPFunc(var func: pointer; FuncName: LPCSTR);
const
  dll = 'DllName.dll';
begin
  if DllHandle = 0 then
    if FileExists(dll) then
    begin
      DllHandle := LoadLibraryw(dll);
      if DllHandle = 0 then
      begin
        ShowMessage('Не смог иницилизировать библиотеку (' + dll + ')' +
          HRESULTStr(GetLastError) + #10#13 + '- ' + dll);

        Exit;
      end;
    end else begin
        ShowMessage('Файл ' + dll + ' не найден');
        Exit;
    end;

  func := GetProcAddress(DllHandle, FuncName);
  if not assigned(func) then
    MessageBoxW(0, Pchar('Unable to link [' + FuncName + '] function'),
      'LoadFunction', 0);
end;

А еще лучше так
procedure RaiseLastOSErrorEx(const AMsg: string);
var
  Code: Cardinal;
  Err: EOSError;
begin
  Code := GetLastError;
  Err := EOSError.CreateFmt('%s: %s (%u)', AMsg, SysErrorMessage(Code), Code);
  Err.ErrorCode := Code;
  raise Err;
end;

procedure LoadPHPFunc(var func: pointer; FuncName: PChar);
const
  dll = 'DllName.dll';
begin
  if DllHandle = 0 then
    if not FileExists(dll) then
      raise Exception.Create('Файл ' + dll + ' не найден');
    DllHandle := LoadLibrary(dll);
    if DllHandle = 0 then
      RaiseLastOSErrorEx('Не смог иницилизировать библиотеку (' + dll + ')');
  func := GetProcAddress(DllHandle, FuncName);
  if not Assigned(func) then
    RaiseLastOSErrorEx(Format('Unable to link [%s.%s] function', [dll, FuncName]))
end;
11 июн 18, 17:08    [21484742]     Ответить | Цитировать Сообщить модератору
 Re: Загрузка библиотеки и функций из неё  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 10313
И еще. Этот код
_Vasilisk_
    if not FileExists(dll) then
      raise Exception.Create('Файл ' + dll + ' не найден');
можно использовать только в том случае, если dll ожидается в текущем каталоге. В противном случае этот кусок вреден и его нужно убрать.

А если dll ищется только в каталоге программы, то тогда код нужно переписать так

_Vasilisk_
procedure LoadPHPFunc(var func: pointer; FuncName: PChar);
const
  dll = 'DllName.dll';
var
  fullName: string;
begin
  if DllHandle = 0 then begin
    fullName := ExtractFilePath(GetModuleName(HInstance)) + dll;
    if not FileExists(fullName) then
      raise Exception.Create('Файл ' + fullName + ' не найден');
    DllHandle := LoadLibrary(fullName);
    if DllHandle = 0 then
      RaiseLastOSErrorEx('Не смог иницилизировать библиотеку (' + fullName + ')');
  end;
  func := GetProcAddress(DllHandle, FuncName);
  if not Assigned(func) then
    RaiseLastOSErrorEx(Format('Unable to link [%s.%s] function', [dll, FuncName]))
end;
11 июн 18, 17:15    [21484747]     Ответить | Цитировать Сообщить модератору
 Re: Загрузка библиотеки и функций из неё  [new]
DarkMaster
Member

Откуда: Donetsk,Ukraine
Сообщений: 5909
_Vasilisk_,

Там есть нюанс с dll. Если dll (например host) тянет за собой еще какую-то dll (slave) и находится не в каталоге программы, то эту вторую slave.dll нужно грузить или по абсолютному пути или ложить рядом с .exe, но не рядом с host.dll.
11 июн 18, 18:00    [21484791]     Ответить | Цитировать Сообщить модератору
 Re: Загрузка библиотеки и функций из неё  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 10313
DarkMaster
Там есть нюанс с dll. Если dll (например host) тянет за собой еще какую-то dll (slave) и находится не в каталоге программы, то эту вторую slave.dll нужно грузить или по абсолютному пути или ложить рядом с .exe, но не рядом с host.dll.
Извини, но в такой формулировке написан бред

Все dll, используемые процессом должны лежать по известным путям

If SafeDllSearchMode is enabled, the search order is as follows:

The directory from which the application loaded.
The system directory. Use the GetSystemDirectory function to get the path of this directory.
The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.
The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
The current directory.
The directories that are listed in the PATH environment variable. Note that this does not include the per-application path specified by the App Paths registry key. The App Paths key is not used when computing the DLL search path.

If SafeDllSearchMode is disabled, the search order is as follows:

The directory from which the application loaded.
The current directory.
The system directory. Use the GetSystemDirectory function to get the path of this directory.
The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.
The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
The directories that are listed in the PATH environment variable. Note that this does not include the per-application path specified by the App Paths registry key. The App Paths key is not used when computing the DLL search path.
или должны быть загружены с указанием полного пути
11 июн 18, 18:36    [21484830]     Ответить | Цитировать Сообщить модератору
 Re: Загрузка библиотеки и функций из неё  [new]
Ss`st
Guest
Нашли причину. Проблема была в том, что система не могла найти 32 битный vcruntime140.dll

Но у пользователя он был установлен! Той же версии. Проблема решилась после того, как vcruntime140.dll попал в папку с исполняемым файлом.


Непонятно почему,нигде не было выведено ошибок об отсутствие этой библиотеки, или невозможности загрузить 64 битную версию vcruntime140.dll
11 июн 18, 19:57    [21484934]     Ответить | Цитировать Сообщить модератору
 Re: Загрузка библиотеки и функций из неё  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 10313
Ss`st
Но у пользователя он был установлен!
И где он находился?
Ss`st
Непонятно почему,нигде не было выведено ошибок об отсутствие этой библиотеки
Это вам лучше знать, почему вы не выводили код ошибки
Ss`st
или невозможности загрузить 64 битную версию vcruntime140.dll
А с какого перепугу в 32 битный процесс будет загружаться 64 битная dll?
11 июн 18, 21:05    [21484987]     Ответить | Цитировать Сообщить модератору
 Re: Загрузка библиотеки и функций из неё  [new]
Ss`st
Guest
_Vasilisk_
И где он находился?


По умолчанию загрузка происходит (У пользователя)
(Microsoft® C Runtime Library) F:\Windows\System32\VCRUNTIME140.dll : 14.14.26429.4 (64 bit 85,8 КБ (87 872 байт))

У меня - же, загрузка происходит по пути
(Microsoft® C Runtime Library) C:\Windows\SysWOW64\VCRUNTIME140.dll : 14.14.26429.4 (64 bit. 85,3 КБ (87 360 байт))

_Vasilisk_
Это вам лучше знать, почему вы не выводили код ошибки


Действительно, почему я не выводил код ошибки?

+
function HRESULTStr(h: HRESULT): LPWSTR;
begin
  FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_FROM_SYSTEM,
    nil, h, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), @result, 0, nil);
end;

....
  ShowMessage('Не смог иницилизировать библиотеку (' + dll + ')' +
          HRESULTStr(GetLastError) + #10#13 + '- ' + dll);



_Vasilisk_
А с какого перепугу в 32 битный процесс будет загружаться 64 битная dll?


И я не знаю,почему у пользователя 32 битное приложение пыталась загрузить 64 битную версию библиотеки (Запуская процесс от администратора)
Потому как, запуская с правами обычного пользователя, был вывод о не найденной библиотеки
11 июн 18, 21:35    [21485025]     Ответить | Цитировать Сообщить модератору
 Re: Загрузка библиотеки и функций из неё  [new]
Ss`st
Guest
Ss`st
Потому как, запуская с правами обычного пользователя, был вывод о не найденной библиотеки


Уточню, не найденной библиотеки - которую я пытаюсь использовать, а не эту VCRUNTIME140.dll

И это притом, что это было при использование " ; cdecl; external libraryPath name 'NameFunction';"
11 июн 18, 21:37    [21485031]     Ответить | Цитировать Сообщить модератору
 Re: Загрузка библиотеки и функций из неё  [new]
Ss`st
Guest
Решил с копипастить и быстро прописать, и допустил маленькую ошибку в описание (Так как я удалил уже информационный вывод, а он остался в переписки - с пользователем)

Ss`st
По умолчанию загрузка происходит (У пользователя)
(Microsoft® C Runtime Library) F:\Windows\System32\VCRUNTIME140.dll : 14.14.26429.4 (64 bit 85,8 КБ (87 872 байт))

У меня - же, загрузка происходит по пути
(Microsoft® C Runtime Library) C:\Windows\SysWOW64\VCRUNTIME140.dll : 14.14.26429.4 (32 bit. 85,3 КБ (87 360 байт))
11 июн 18, 21:41    [21485037]     Ответить | Цитировать Сообщить модератору
 Re: Загрузка библиотеки и функций из неё  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 10313
Ss`st
Действительно, почему я не выводил код ошибки?

+
function HRESULTStr(h: HRESULT): LPWSTR;
begin
  FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_FROM_SYSTEM,
    nil, h, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), @result, 0, nil);
end;

....
  ShowMessage('Не смог иницилизировать библиотеку (' + dll + ')' +
          HRESULTStr(GetLastError) + #10#13 + '- ' + dll);

Вот и мне интересно
+
Ss`st
procedure LoadPHPFunc(var func: pointer; FuncName: LPCSTR);
const
  dll = 'DllName.dll';
begin
  if DllHandle = 0 then
    if FileExists(dll) then  // else не обнаружено
    begin
      DllHandle := GetModuleHandlew(dll);
      if DllHandle = 0 then
        DllHandle := LoadLibraryw(dll);
      if DllHandle = 0 then
      begin
        ShowMessage('Не смог иницилизировать библиотеку (' + dll + ')' +
          HRESULTStr(GetLastError) + #10#13 + '- ' + dll);

        Exit;
      end;
    end;

  func := GetProcAddress(DllHandle, FuncName);
  if not assigned(func) then
    MessageBoxW(0, Pchar('Unable to link [' + FuncName + '] function'),
      'LoadFunction', 0);
end;

Ss`st
И я не знаю,почему у пользователя 32 битное приложение пыталась загрузить 64 битную версию библиотеки (Запуская процесс от администратора)
Потому как, запуская с правами обычного пользователя, был вывод о не найденной библиотеки
Порядок поиска я указал 21484830 а теперь смотрите, как в этом списке оказался 64 System32 вместо 32 битного SysWOW64. Одна из причин - в SysWOW64 dll не было, а System32 был занесен в Path
11 июн 18, 23:30    [21485254]     Ответить | Цитировать Сообщить модератору
Все форумы / Delphi Ответить