При работе с реестром в операционных системах с 64-битной архитектурой могут возникать проблемы, связанные с доступом 32-битных программ к разделам реестра, предназначенным для 64-битных приложений. Одной из таких проблем является некорректное чтение значений реестра с помощью объекта TRegistry в 32-битных приложениях, запущенных на 64-битной системе.
Описание проблемы
Функция, предназначенная для чтения целочисленных значений из реестра, не возвращает корректные значения, если программа является 32-битной и выполняется на 64-битной операционной системе. Это происходит из-за того, что TRegistry по умолчанию работает с 32-битными разделами реестра, даже на 64-битной системе. В результате, если программа запущена вне среды разработки (IDE), она не сможет прочитать правильные значения из реестра.
Пример функции для чтения целочисленных значений из реестра:
function LB_ReadRegistryInteger(strSubKey: String; strValueName: String): Integer;
var
Key: HKey; // ключ реестра
TheInt: Integer; // возвращаемое целочисленное значение
IntSize: Integer; // размер целочисленного значения
TheType: Integer; // тип данных
begin
Result := 0;
TheType := REG_DWORD;
IntSize := SizeOf(TheInt);
if RegOpenKeyEx(HKEY_LOCAL_MACHINE, PChar(strSubKey), 0,
(KEY_READ or KEY_WOW64_64KEY), Key) = ERROR_SUCCESS then
begin
if RegQueryValueEx(Key, PChar(strValueName), nil, @TheType, @TheInt, @IntSize) = ERROR_SUCCESS then
Result := TheInt;
end;
RegCloseKey(Key);
end;
Решение проблемы
Для решения проблемы необходимо использовать флаг KEY_WOW64_64KEY, который позволяет 32-битным приложениям читать значения из 64-битных разделов реестра. В приведенном выше примере функции этот флаг уже используется.
Однако, в примере использования альтернативного ответа, указано, что проблема заключается в неверном указании пути к ключу реестра. Необходимо убрать первый обратный слэш (\), чтобы функция корректно работала:
Также стоит отметить, что можно использовать TRegistry для работы с 64-битными разделами реестра, установив соответствующий флаг в свойство Access:
function LB_ReadRegistryInteger(strSubKey: String; strValueName: String): Integer;
var
Reg: TRegistry;
begin
Result := 0;
Reg := TRegistry.Create;
try
Reg.Access := KEY_READ or KEY_WOW64_64KEY; // установить флаг для чтения 64-битного реестра
Reg.RootKey := HKEY_LOCAL_MACHINE;
if Reg.OpenKey(strSubKey, False) then
try
Result := Reg.ReadInteger(strValueName);
finally
Reg.CloseKey;
end;
finally
Reg.Free;
end;
end;
Важно отметить, что в более старых версиях Delphi (например, в Delphi 7) поддержка флагов KEY_WOW64_... может отсутствовать. В таких случаях необходимо использовать функцию RegOpenKeyEx напрямую, как показано в первоначальном примере функции LB_ReadRegistryInteger.
Таким образом, при работе с реестром в 64-битных операционных системах важно правильно использовать флаги доступа, чтобы обеспечить корректное чтение значений из нужных разделов реестра.
Проблема заключается в некорректном доступе 32-битного TRegistry к 64-битным разделам реестра в операционных системах с 64-битной архитектурой и её решение через использование соответствующих флагов доступа.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS