Используйте RegNotifyChangeKeyValue для отслеживания изменений в 64-битном ключе - PullRequest
3 голосов
/ 15 января 2012

Я пытаюсь использовать RegNotifyChangeKeyValue для отслеживания изменений в 64-битном разделе реестра.Чтобы открыть этот ключ из 32-разрядного приложения, мы должны добавить флаг доступа KEY_WOW64_64KEY.

К сожалению, я не могу отслеживать изменения этого ключа, только его 32-разрядный аналог.

Я включаю демонстрационный проект вместе с модулем, который я использую для мониторинга реестра.Загрузите его здесь: RegMonitor

Действия по воспроизведению проблемы:

  1. Скомпилируйте программу.Запустите его от имени администратора.Нажмите кнопку Пуск.

  2. Откройте regedit и перейдите к

    HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Run

  3. Добавить новое значениетам.RegMonitor не обнаружит никаких изменений.

  4. Перейдите к

    HKEY_LOCAL_MACHINE \ SOFTWARE \ Wow6432Node \ Microsoft \ Windows \ CurrentVersion \ Run

  5. Добавьте туда новое значение.RegMonitor обнаружит это изменение.

Я добавил флаг доступа KEY_WOW64_64KEY при открытии реестра, но он по-прежнему не уведомляет о любых изменениях правильного ключа, только перенаправление Wow6432Node.

Есть идеи, можно ли использовать RegNotifyChangeKeyValue для мониторинга такого ключа?

1 Ответ

2 голосов
/ 15 января 2012

Следующий минимальный пример обнаруживает изменения в 64-битном представлении реестра от 32-битного процесса. Я не знаю, что отличает вашу программу, но этот код доказывает, что 32-битная программа действительно может обнаруживать изменения в обоих представлениях.

Я знаю, что это не решит твою проблему, но я надеюсь, что это поможет направить тебя в правильном направлении.

program RegMonitor;

{$APPTYPE CONSOLE}

uses
  SysUtils, Windows;

procedure Main;
const
  dwFilter: DWORD =
    REG_NOTIFY_CHANGE_NAME or
    REG_NOTIFY_CHANGE_ATTRIBUTES or
    REG_NOTIFY_CHANGE_LAST_SET or
    REG_NOTIFY_CHANGE_SECURITY;
var
  Error: Integer;
  key: HKEY;
begin
  Error := RegOpenKeyEx(
    HKEY_LOCAL_MACHINE,
    'Software\Microsoft\Windows\CurrentVersion\RunOnce',
    0,
    KEY_NOTIFY or KEY_WOW64_64KEY,
    key
  );
  if Error<>ERROR_SUCCESS then
    RaiseLastOSError(Error);
  try
    Error := RegNotifyChangeKeyValue(
      key,
      True,
      dwFilter,
      0,
      False
    );
    if Error<>ERROR_SUCCESS then
      RaiseLastOSError(Error);
    Writeln('Change detected');
    Readln;
  finally
    RegCloseKey(key);
  end;
end;

begin
  Main;
end.

Теперь, что касается вашей программы, похоже, с ней много проблем. Но основная проблема, которая означает, что вы не уведомлены об изменениях, заключается в том, что ваше событие создано неправильно. Вы создаете это так:

CreateEvent(Nil, True, False, 'RegistryChangeMonitorEvent')

но вам нужно создать его вот так

CreateEvent(nil, False, True, nil)

Я не вникал в требования к этому событию, документация не дает никаких подсказок. Все, что я сделал, это нашел различия между вашим кодом и кодом в примере MSDN .

Внесите это изменение в создание события, и у вас будет достаточно, чтобы начать получать уведомления. Однако, когда я сделал это изменение, ваша программа все еще не работала и потерпела неудачу с AV. Один из ваших объектов не был создан. Тем не менее, я думаю, что это довольно обычные ошибки, которые вы можете сами разобрать.


Интересно, почему вы используете KEY_ALL_ACCESS. Почему вы не используете KEY_NOTIFY, когда открываете ключ для передачи на RegNotifyChangeKeyValue? И когда вы пытаетесь создать отчет о том, что изменилось в ключе, почему вы не используете KEY_READ? Поскольку вы не пытаетесь писать когда-либо, KEY_ALL_ACCESS не подходит. Если вы внесете эти изменения, вам не нужно будет работать от имени администратора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...