Я работаю над тем, что динамически загружает специально разработанные DLL. Мне нужно иметь возможность проверить DLL и убедиться, что все ожидаемые функции существуют до того, как я подумаю об использовании этой DLL. Если у него отсутствуют некоторые определенные функции, я не должен пытаться его загрузить. Я знаю, что могу попытаться вызвать одну из функций и посмотреть, есть ли какое-то исключение, но я увижу ошибки в режиме отладки.Как проверить DLL, если существует функция?
Как мне проверить проверку DLL, если существует функция? Я хотел бы проверить его до Я загружаю его (используя LoadLibrary
), но я думаю, что это нормально, если мне нужно загрузить его, чтобы выполнить эту проверку тоже.
UPDATE
Я принял ответ Дэвида ниже, и думал, что я отправлю свой окончательный код, чтобы показать весь процесс. Я превратил его в функцию, возвращающую Bool, независимо от того, удалось это или нет, немного очистил код и добавил еще одну функцию внизу, которая использует эту, чтобы проверять каждое имя по одному.
Я решил использовать этот метод вместо чтения GetProcAddress
, потому что это поможет мне в будущем с другими вещами.
type
PIMAGE_NT_HEADERS = ^IMAGE_NT_HEADERS;
PIMAGE_EXPORT_DIRECTORY = ^IMAGE_EXPORT_DIRECTORY;
function ImageNtHeader(Base: Pointer): PIMAGE_NT_HEADERS; stdcall;
external 'dbghelp.dll';
function ImageRvaToVa(NtHeaders: Pointer; Base: Pointer; Rva: ULONG;
LastRvaSection: Pointer): Pointer; stdcall; external 'dbghelp.dll';
function ExportedFunctionNames(const ImageName: string; NamesList: TStrings): Bool;
var
i: Integer;
FileHandle: THandle;
ImageHandle: THandle;
ImagePointer: Pointer;
Header: PIMAGE_NT_HEADERS;
ExportTable: PIMAGE_EXPORT_DIRECTORY;
NamesPointer: Pointer;
Names: PAnsiChar;
NamesDataLeft: Integer;
begin
Result:= False;
NamesList.Clear;
FileHandle:= CreateFile(PChar(ImageName), GENERIC_READ, FILE_SHARE_READ,
nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if FileHandle = INVALID_HANDLE_VALUE then Exit;
try
ImageHandle:= CreateFileMapping(FileHandle, nil, PAGE_READONLY, 0, 0, nil);
if ImageHandle = 0 then Exit;
try
ImagePointer:= MapViewOfFile(ImageHandle, FILE_MAP_READ, 0, 0, 0);
if not Assigned(ImagePointer) then Exit;
try
Header:= ImageNtHeader(ImagePointer);
if not Assigned(Header) then Exit;
if Header.Signature <> $00004550 then Exit; // "PE\0\0" as a DWORD.
ExportTable:= ImageRvaToVa(Header, ImagePointer,
Header.OptionalHeader.DataDirectory[0].VirtualAddress, nil);
if not Assigned(ExportTable) then Exit;
NamesPointer:= ImageRvaToVa(Header, ImagePointer,
Cardinal(ExportTable.AddressOfNames), nil);
if not Assigned(NamesPointer) then Exit;
Names:= ImageRvaToVa(Header, ImagePointer, Cardinal(NamesPointer^), nil);
if not Assigned(Names) then Exit;
NamesDataLeft:= Header.OptionalHeader.DataDirectory[0].Size;
for i:= 0 to ExportTable.NumberOfNames - 1 do begin
NamesList.Add(Names);
while (Names^ <> chr(0)) and (NamesDataLeft > 0) do begin
Inc(Names);
Dec(NamesDataLeft);
end;
Inc(Names);
end;
Result:= True;
finally
UnmapViewOfFile(ImagePointer);
end;
finally
CloseHandle(ImageHandle);
end;
finally
CloseHandle(FileHandle);
end;
end;
function IsMyDLL(const Filename: String): Bool;
var
H: THandle;
L: TStringList;
function InList(const Func: String): Bool;
begin
Result:= L.IndexOf(Func) >= 0;
end;
begin
Result:= False;
L:= TStringList.Create;
try
if ExportedFunctionNames(Filename, L) then begin
Result:=//Names of functions which need to exist
InList('GetName') and
InList('GetDescription') and
InList('GetVersion') and
InList('Start') and
InList('Stop');
end;
finally
L.Free;
end;
end;
Выглядит многообещающе, и когда я вернусь к своему столу, я дам ему пойти: D Это может быть способ пойти на самом деле, я принял слишком рано ... –
Ну, это проверенный и проверенный код. Но что мешает вам использовать LoadLibrary и GetProcAddress? Зная, что это может помочь. –
Потому что на самом деле мне нужно будет выяснить, как в любом случае перечислить эти функции для этого проекта :) –