使用RegNotifyChangeKeyValue监视对64位密钥的更改

时间:2012-01-15 18:34:13

标签: windows delphi winapi

我尝试使用RegNotifyChangeKeyValue来监控64位注册表项的更改。 要从32位应用程序打开此密钥,我们必须添加访问标志KEY_WOW64_64KEY。

不幸的是,我似乎无法监控此密钥的更改,只有它的32位对应方。

我包括一个演示项目以及我用来实现注册表监控的单元。在此处下载:RegMonitor

重现问题的步骤:

  1. 编译程序。以管理员身份运行它。单击“开始”按钮。

  2. 打开注册表并导航到

    HKEY_LOCAL_MACHINE \ SOFTWARE \微软\的Windows \ CurrentVersion \运行

  3. 在那里添加新值。 RegMonitor不会检测到任何变化。

  4. 导航至

    HKEY_LOCAL_MACHINE \ SOFTWARE \ Wow6432Node \微软\的Windows \ CurrentVersion \运行

  5. 在那里添加新值。 RegMonitor将检测到此更改。

  6. 我在打开注册表时添加了KEY_WOW64_64KEY访问标志,但它仍然没有通知对正确密钥的任何更改,只有Wow6432Node重定向。

    是否有可能使用RegNotifyChangeKeyValue来监控此类密钥?

1 个答案:

答案 0 :(得分:2)

以下最小示例从32位进程检测注册表的64位视图中的更改。我不知道你的程序有什么不同,但是这段代码证明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 example中的代码之间的差异。

对事件创建进行更改,您就可以开始接收通知了。但是,当我做了那个改变时,你的程序仍然没有工作,并且失败了AV。您的一个对象未​​创建。但是,我认为这些都是非常常见的错误,你可以自己解决。


我想知道你为什么要使用KEY_ALL_ACCESS。当您打开要传递给KEY_NOTIFY的密钥时,为什么不使用RegNotifyChangeKeyValue?当您尝试构建关键字中已更改内容的报告时,为什么不使用KEY_READ?由于您没有尝试永远写作,KEY_ALL_ACCESS不合适。如果您进行了这些更改,则无需以管理员身份运行。