При разработке программного обеспечения на языке Object Pascal, особенно в среде Delphi, разработчики часто сталкиваются с различными проблемами, связанными с особенностями работы 64-битных операционных систем. Одной из таких проблем является ошибка при получении имени модуля процесса в Windows 8 и более поздних версиях, работающих в 64-битном режиме.
Вот пример функции, которая пытается получить имя модуля процесса:
function NazwaProcesu(const uchwyt: Thandle): string;
var
pid: DWORD;
hProcess: Thandle;
sciezka: array [0..MAX_PATH - 1] of char;
begin
GetWindowThreadProcessId(uchwyt, pid);
hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, FALSE, pid);
if hProcess <> 0 then
try
GetModuleFileNameEx(hProcess, 0, sciezka, MAX_PATH)
finally
Result := sciezka;
CloseHandle(hProcess);
end;
end;
На 32-битной Windows 7 данная функция работает корректно, но на 64-битной Windows 8 и выше может возвращать некорректные результаты, например, вместо ожидаемого explorer.exe возвращается мусор.
Причины проблемы
Причиной проблемы является различие в битности между приложением и целевым процессом. Функция GetModuleFileNameEx возвращает имя модуля для модулей того же битности, что и приложение. В 64-битной Windows используется эмулятор WOW64 для запуска 32-битных приложений, что может приводить к проблемам при попытке получить информацию о 64-битных процессах из 32-битного процесса и наоборот.
Решения проблемы
Перекомпиляция приложения в 64-битную версию. Это позволит избежать использования эмулятора WOW64 и обеспечит корректную работу с 64-битными процессами.
Использование отдельного 64-битного процесса и IPC для получения информации. Это может быть сложным решением, но оно позволит обойти проблемы с битностью.
Использование WMI для получения имени модуля. WMI предоставляет более высокоуровневый интерфейс для получения информации о системе, включая имя модуля процесса.
Использование функции QueryFullProcessImageName. Эта функция доступна начиная с Windows Vista и предназначена для получения полного пути к исполняемому файлу процесса.
Проверка PE-заголовков. Можно использовать чтение файла в бинарном режиме и проверку на соответствие подписи PE, чтобы определить битность исполняемого файла.
Важность проверки ошибок
Необходимо всегда проверять возвращаемые функции Windows API на ошибки. В приведенном выше примере функция GetModuleFileNameEx не проверяется на ошибки, что приводит к тому, что буфер для текста остается неинициализированным и возвращает мусорные данные.
Пример исправленной функции
function NazwaProcesu(const uchwyt: Thandle): string;
type
TQueryFullProcessImageName = function(hProcess: Thandle; dwFlags: DWORD; lpExeName: PChar; nSize: PDWORD): BOOL; stdcall;
var
pid: DWORD;
hProcess: Thandle;
sciezka: array [0 .. MAX_PATH - 1] of Char;
QueryFullProcessImageName: TQueryFullProcessImageName;
nSize: cardinal;
begin
Result := '';
GetWindowThreadProcessId(uchwyt, pid);
hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, false, pid);
if hProcess <> 0 then
try
if GetModuleFileNameEx(hProcess, 0, sciezka, MAX_PATH) then
if GetLastError = ERROR_SUCCESS then
Result := sciezka
else if Win32MajorVersion >= 6 then
begin
nSize := MAX_PATH;
ZeroMemory(@sciezka, MAX_PATH);
@QueryFullProcessImageName := GetProcAddress(GetModuleHandle('kernel32'), 'QueryFullProcessImageNameW');
if Assigned(QueryFullProcessImageName) then
if QueryFullProcessImageName(hProcess, 0, sciezka, @nSize) then
Result := sciezka;
end;
finally
CloseHandle(hProcess);
end;
end;
В этом примере добавлена проверка на успех выполнения функции и обработка возможных ошибок, что повышает надежность и предсказуемость поведения программы.
Следуя этим рекомендациям, разработчики могут избежать многих проблем, связанных с получением имени модуля в 64-битных операционных системах Windows.
и способов решения ошибок при получении имени модуля в 64-битной Windows, возникающих при работе с функциями Windows API и влияющих на корректность работы программ на Object Pascal, особенно в среде Delphi.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.