加入收藏 收藏网站 设为首页 设为首页
招生考试网
学历类| 阳光高考 研 究 生 自学考试 成人高考 专 升 本 中考会考 外语类| 四 六 级 职称英语 商务英语 公共英语 日语能力
资格类| 公 务 员 报 关 员 银行从业 司法考试 导 游 证 教师资格 财会类| 会 计 证 经 济 师 会计职称 注册会计 税 务 师
工程类| 一级建造 二级建造 造 价 师 造 价 员 咨 询 师 监 理 师 医学类| 卫生资格 执业医师 执业药师 执业护士 国际护士
计算机| 等级考试 软件水平 应用能力 其它类| 书画等级 美国高考 驾 驶 员 书法等级 少儿英语 报 检 员 单 证 员 出国留学
 招生考试网 - 计算机等级考试 - 考试辅导 - 计算机二级 - 正文

 
Delphi实现对注册表的监视和扫描完整代码解析
来源:青年人 2010-8-17 编辑:zhanghaifeng 【字体:小 大】
Delphi自带的TRegistry类只能实现注册表的基本操作,如果我们要实时监视注册表的变化或者扫描注册表特定项下的所有子项,TRegistry类就无能为力了。我啃了半天SDK,终于实现了Delphi对注册表的监视与扫描,不敢独享,拿来献给广大的Delphi爱好者。

 

Delphi自带的TRegistry类只能实现注册表的基本操作,如果我们要实时监视注册表的变化或者扫描注册表特定项下的所有子项,TRegistry类就无能为力了。我啃了半天SDK,终于实现了Delphi对注册表的监视与扫描,不敢独享,拿来献给广大的Delphi爱好者。
  监视注册表相关项的改变要用到一个API:RegNotifyChangeKeyValue。
  LONG RegNotifyChangeKeyValue(
  HKEY hKey, // 要监视的一个项的句柄
  BOOL bWatchSubtree, // 是否监视此项的子键
  DWORD dwNotifyFilter, // 监视哪些变化
  HANDLE hEvent, // 接受注册表变化事件的事件对象句柄
  BOOL fAsynchronous// 注册表变化前报告还是注册表变化后才报告
  );
  注意上面的hEvent是接受注册表变化事件的事件对象句柄,我们要用API:CreateEvent来创建一个系统事件对象。
  HANDLE CreateEvent(
  LPSECURITY_ATTRIBUTES lpEventAttributes, // SECURITY_ATTRIBUTES结构
  BOOL bManualReset, // 是否自动重置
  BOOL bInitialState, // 是否设置初始状态
  LPCTSTR lpName// 事件对象的名称
  );
  新建一个工程,添加一个ListBox,两个Button。
  //先写个监视注册表的例子
  //监视HKEY_CURRENT_USER\\Software项下所有子键
  procedure TForm1.Button1Click(Sender: TObject);
  var
  hNotify : THandle;
  hKeyx : HKEY;
  dwRes : DWORD;
  begin
  hNotify := CreateEvent( nil, //不使用SECURITY_ATTRIBUTES结构
  FALSE, //不自动重置
  TRUE,//设置初始状态
  \’RegistryNotify\’ //事件对象的名称
  );
  if hNotify = 0 then
  begin
  Showmessage(\’CreateEvent failed.\’);
  exit;
  end;
  if RegOpenKeyEx( HKEY_CURRENT_USER, //跟键
  \’Software\’, //子键
  0, //reserved
  KEY_NOTIFY, //监视用
  hKeyx //保存句柄
  ) <> ERROR_SUCCESS then
  begin
  CloseHandle( hNotify );
  Showmessage(\’RegOpenKeyEx failed.\’);
  exit;
  end;
  if RegNotifyChangeKeyValue( hKeyx, //监视子键句柄
  TRUE, //监视此项的子键
  REG_NOTIFY_CHANGE_NAME or REG_NOTIFY_CHANGE_LAST_SET,
  hNotify, //接受注册表变化事件的事件对象句柄
  TRUE //注册表变化前报告
  ) <> ERROR_SUCCESS then

begin
  CloseHandle( hNotify );
  RegCloseKey( hKeyx );
  Showmessage(\’RegNotifyChangeKeyValue failed\’);
  exit;
  end;
  dwRes := WaitForSingleObject( hNotify, 60 * 1000 ); //监视一分钟
  if dwRes = 0 then
  Showmessage( \’Registry will be changed.\’ );
  CloseHandle( hNotify );
  RegCloseKey( hKeyx );
  end;
  要注意的是,API: WaitForSingleObject要等到注册表变化事件发生或者超时才会返回,在此期间我们的程序将失去响应。解决的办法是新建一个线程,在新线程中监视注册表。
  对注册表进行扫描要用到另外两个API: RegEnumKey和RegEnumValue。
  LONG RegEnumKey(
  HKEY hKey, // 要扫描的注册表项目句柄
  DWORD dwIndex, // 要扫描的subkey序号
  LPTSTR lpName, // 要扫描的subkey名称
  LPDWORD lpcbName, // 要扫描的subkey名称占用空间
  );
  此函数的使用方法是: 首先给dwIndex赋值0, 调用RegEnumKey; 然后Inc(dwIndex), 再调用RegEnumKey,直到返回值为ERROR_NO_MORE_ITEMS,表示没有更多的子项了。
  //扫描注册表的例子
  //只演示了如何枚举HKEY_CURRENT_USER\\Software下的一层子项
  procedure TForm1.Button2Click(Sender: TObject);
  var
  buf : array [0..255] of char;
  iRes: integer;
  hKeyx : HKEY;
  dwIndex, dwSize : DWORD;
  begin
  if RegOpenKeyEx( HKEY_CURRENT_USER, \’Software\’, 0, KEY_READ or
  KEY_ENUMERATE_SUB_KEYS, hKeyx ) <> ERROR_SUCCESS then
  begin
  Showmessage(\’RegOpenKeyEx failed.\’);
  exit;
  end;
  dwIndex := 0;
  repeat
  dwSize := 255;
  iRes := RegEnumKey( hKeyx, dwIndex, buf, dwSize );
  if iRes = ERROR_NO_MORE_ITEMS then
  break
  else if iRes = ERROR_SUCCESS then
  begin
  Listbox1.Items.Add( buf );
  Inc( dwIndex );
  end;
  until iRes <> ERROR_SUCCESS;
  RegCloseKey( hKeyx );
  end;

 try
  if NTNetGetDCName(nil, nil, pDomain) = 0 then
  Result := WideCharToString(pDomain);
  finally
  NTNetApiBufferFree(pDomain);
  end;
  finally
  FreeLibrary(Libhandle);
  end;
  end;
  function GetDomainName: AnsiString;
  type
  WKSTA_INFO_100 = record
  wki100_platform_id: Integer;
  wki100_computername: PWideChar;
  wki100_langroup: PWideChar;
  wki100_ver_major: Integer;
  wki100_ver_minor: Integer;
  end;
  WKSTA_USER_INFO_1 = record
  wkui1_username: PChar;
  wkui1_logon_domain: PChar;
  wkui1_logon_server: PChar;
  wkui1_oth_domains: PChar;
  end;
  type
  //Win9X ANSI prototypes from RADMIN32.DLL and RLOCAL32.DLL
  TWin95_NetUserGetInfo = function(ServerName, UserName: PChar; Level: DWORD; var
  BfrPtr: Pointer): Integer;
  stdcall;
  TWin95_NetApiBufferFree = function(BufPtr: Pointer): Integer;
  stdcall;
  TWin95_NetWkstaUserGetInfo = function(Reserved: PChar; Level: Integer; var
  BufPtr: Pointer): Integer;
  stdcall;
  //WinNT UNICODE equivalents from NETAPI32.DLL
  TWinNT_NetWkstaGetInfo = function(ServerName: PWideChar; level: Integer; var
  BufPtr: Pointer): Integer;
  stdcall;
  TWinNT_NetApiBufferFree = function(BufPtr: Pointer): Integer;
  stdcall;
  var
  Win95_NetUserGetInfo: TWin95_NetUserGetInfo;
  Win95_NetWkstaUserGetInfo: TWin95_NetWkstaUserGetInfo;
  Win95_NetApiBufferFree: TWin95_NetApiBufferFree;
  WinNT_NetWkstaGetInfo: TWinNT_NetWkstaGetInfo;
  WinNT_NetApiBufferFree: TWinNT_NetApiBufferFree;
  WSNT: ^WKSTA_INFO_100;
  WS95: ^WKSTA_USER_INFO_1;
  EC: DWORD;
  hNETAPI: THandle;
  begin
  try
  Result := \’\’;
  if IsWinNT then
  begin
  hNETAPI := LoadLibrary(\’NETAPI32.DLL\’);
  if hNETAPI <> 0 then

 



 
网站版权与免责声明
①由于各方面情况的不断调整与变化,本网所提供的相关信息请以权威部门公布的正式信息为准.
②本网转载的文/图等稿件出于非商业性目的,如转载稿涉及版权等问题,请在两周内来电联系.
推荐文章
  • 此栏目下没有推荐文章
  • 热门文章

    报名考试
    全国 | 黑龙江 | 吉林 | 辽宁 | 内蒙古
    青海 | 宁夏 | 甘肃 | 新疆 | 陕西
    西藏 | 北京 | 天津 | 河北 | 山东
    江苏 | 安徽 | 河南 | 上海 | 浙江
    福建 | 广东 | 山西 | 湖南 | 湖北
    江西 | 广西 | 海南 | 云南 | 贵州
    四川 | 重庆
    分省高校计算机考试
    黑龙江 | 吉林 | 辽宁 | 内蒙古 | 河北
    北京 | 天津 | 新疆 | 甘肃 | 宁夏
    青海 | 陕西 | 山西 | 河南 | 山东
    江苏 | 安徽 | 浙江 | 福建 | 广东
    海南 | 广西 | 江西 | 湖北 | 湖南
    四川 | 上海 | 重庆 | 贵州 | 云南
    西藏
    成绩查询
    报考指南
    试题答案
    模拟试题
    考试辅导
    计算机一级 | 计算机二级 | 计算机三级 | 计算机四级
    经验交流
    高校计算机