请教:
    如何能够做到像IE保护器软件一样监控注册表,
发现注册表给改动后把它复原啊。

解决方案 »

  1.   

    有个vb的,请参考:
    网上冲浪的感觉爽心无比,可是万一遇到IE标题栏被某些不友好网站修改的事情,真会让人扫兴不已。虽然可以自己动手修复注册表,但是被动、手动向来不是程序员的风格,我们还是自己动手编写一个实时监测的IE标题反修改工具吧!
    因为IE标题栏的内容是放在注册表里的,所以想要实时监视标题栏的改变,那就要实时监视注册表相关项的改变。这里我们需要用到一个API函数——RegNotifyChangeKeyValue,函数的原形是:
    Declare Function RegNotifyChangeKeyValue Lib "advapi32.dll"
      Alias "RegNotifyChangeKeyValue" (ByVal hKey As Long,_
                    ByVal bWatchSubtree As Long,_
                    ByVal dwNotifyFilter As Long,_
                    ByVal hEvent As Long,_
                    ByVal fAsynchronus As Long) As Long
    其中,hKey是要监视的一个项的句柄;bWatchSubtree决定是否监视指定项的所有子项;dwNotifyFilter决定在指定项发生何种变化时才会发出通知;hEvent是一个事件对象(Event Object)的句柄,当指定的注册表项或它的任何一个子项的属性或内容发生变化时,RegNotifyChangeKeyValue将调用hEvent指定的事件;fAsynchronus指定了如何通知hEvent,如果为True,则函数会立即返回并触发由hEvent指定的一个事件,否则将一直等待直到项的内容改变为止。更具体的,请参考MSDN中的描述。
    下面还是让我们看看具体的例子吧。打开VB,首先新建一个工程,按照下表在窗体里添加并设置控件,最终设计结果请参考图1:
      CommandButton  Caption="开始监视"
      OptionButton   Caption="缺省的标题栏"
                     Name=Option1
                     Index=0
                     Value=True
      Optionbutton   Caption="自定义标题栏"
                     Name=Option1
                     Index=1
                     TextBoxText=""
    接着新建一个模块,代码如下,
      Option Explicit
      Enum Reg_Notify
        REG_NOTIFY_CHANGE_ATTRIBUTES = &H2
        REG_NOTIFY_CHANGE_LAST_SET = &H4
        REG_NOTIFY_CHANGE_NAME = &H1
        REG_NOTIFY_CHANGE_SECURITY = &H8
        REG_LEGAL_CHANGE_FILTER=(REG_NOTIFY_CHANGE_NAME Or
                           REG_NOTIFY_CHANGE_ATTRIBUTES Or
                           REG_NOTIFY_CHANGE_LAST_SET Or 
                           REG_NOTIFY_CHANGE_SECURITY)
      End Enum
      Public Const HKEY_CLASSES_ROOT = &H80000000
      Public Const HKEY_CURRENT_CONFIG = &H80000005
      Public Const HKEY_CURRENT_USER = &H80000001
      Public Const HKEY_DYN_DATA = &H80000006
      Public Const HKEY_LOCAL_MACHINE = &H80000002
      Public Const HKEY_PERFORMANCE_DATA = &H80000004
      Public Const HKEY_USERS = &H80000003
      Public Const REG_SZ=1
      Public Const REG_DWORD=4
      Public Const IESUBKEY="Software\Microsoft\Internet Explorer\Main"
      Public Const DEFAULT_CAPTION="Microsoft Internet Explorer"
      '下面这个函数的声明经过了修改,与从API浏览器里复制的不同,请注意
      Declare Function RegNotifyChangeKeyValue Lib "advapi32.dll"
      (ByVal hKey As Long,ByVal bWatchSubtree As Boolean,ByVal dwNotifyFilter
      As Reg_Notify,ByVal hEvent As Long,ByVal fAsynchronus As Boolean) As Long
      Declare Function RegOpenKey Lib "advapi32.dll" Alias "RegOpenKeyA" (ByValhKey As Long,ByVallpSubKey As
      String,phkResult As Long) As Long
      Declare Function RegCloseKey Lib "advapi32.dll" (ByValhKey As Long) As Long
      Declare Function RegQueryValueEx Lib "advapi32.dll" Alias "RegQueryValueExA"(ByValhKey As Long,ByVallpValueName
      As String,ByVallp ReservedAsLong,lpType As Long,lpData
      As Any,lpcbData As Long) As Long
      Declare Function RegSetValueEx Lib "advapi32.dll" Alias
      "RegSetValueExA" (ByValhKey As Long,ByVallpValueName
      As String,ByValReserved As Long,ByValdwType As Long,
      lpData As Any,ByValcbData As Long) As Long
      '下面这个函数也经过了修改,请注意
      Declare Function CreateEvent Lib "kernel32" Alias "CreateEventA"
      (lpEventAttributes As Long,ByValbManualReset As Long,ByVal
      bInitialState As Long,ByVallpName As String) As Long
      Declare Function ResetEvent Lib "kernel32" (ByValhEvent As
      Long) As Long
      Declare Function CloseHandle Lib "kernel32" (ByValhObject As
      Long) As Long
      Declare Function WaitForSingleObject Lib "kernel32" (ByVal
      hHandle As Long,ByValdwMilliseconds As Long) As Long
      '自定义函数,用来从注册表中得到当前的IE标题栏内容
      Public Function GetTitle() As String
      Dim hKey As Long
      Dim ret As Long
      Dim lType As Long,lLength As Long
      Dim sValue As String*260
      Dim lValue As Long
      ret = RegOpenKey(HKEY_CURRENT_USER,IESUBKEY,hKey)
      If ret <> 0 Then Exit Function
      ret = RegQueryValueEx (hKey,"WindowTitle",0,lType,ByVal0,lLength)
      If ret = 0 Then
         ret = RegQueryValueEx (hKey,"WindowTitle",0,0,ByValsValue,lLength)
         If ret = 0 Then
             GetTitle = Left(sValue,lLength-1)
         End If
        End If
        RegCloseKey hKey
      End Function
      '自定义函数,用来设置IE标题栏的内容,成功返回True
      Public Function SetTitle (OptionalByVal DefaultCaption As Boolean = True) As Boolean
      Dim hKey As Long
      Dim ret As Long
      ret = RegOpenKey (HKEY_CURRENT_USER,IESUBKEY,hKey)
      If ret <> 0 Then Exit Function
      If DefaultCaption Then
        ret = RegSetValueEx (hKey,"WindowTitle",0,REG_SZ,ByVal DEFAULT_CAPTION,Len(DEFAULT_CAPTION))
        If ret = 0 Then SetTitle = True
      Else
        ret = RegSetValueEx (hKey,"WindowTitle",0,REG_SZ,ByVal Form1.Text1.Text,Len(Form1.Text1.Text))
        If ret = 0 Then SetTitle = True
      End If
      RegCloseKey hKey
      End Function
    下面是窗体中的代码:
      Option Explicit
      Private Sub Command1_Click()
      StatichKey As Long,hEvent As Long
      Dim dwEvent As Long,ret As Long
      Dim iCount As Long
      If Command1.Caption ="停止监视" Then
         Command1.Caption = "开始监视"
         CloseHandle hEvent
         RegCloseKey hKey
      Else
         Command1.Caption = "停止监视"
      RegOpenKey HKEY_CURRENT_USER,IESUBKEY,hKey
      hEvent = CreateEvent(ByVal 0&,True,True,"RegEvent")
         ret = RegNotifyChangeKeyValue(hKey,False,REG_NOTIFY_CHANGE_LAST_SET,hEvent,True)
      If ret = 0 Then
          dwEvent = WaitForSingleObject(hEvent,&HFFFF)
          Select Case dwEvent
             Case 0
                     '注册表项发生变化
                   Call DoFix
             Case Else
              '超时,注册表项没有改动
          End Select
          ResetEvent hEvent
         End If
       End If
      End Sub
      Private Sub DoFix()
      Dim CaptionNow As String
      CaptionNow = GetTitle()
      If CaptionNow = DEFAULT_CAPTION Or CaptionNow = Text1.Text Then Exit Sub
      If Option1(0).Value Then
         If MsgBox("IE标题栏已被修改,是否恢复为缺省的标题栏?",vbYesNo+vbQuestion) = vbYes Then
               Call SetTitle
         End If
       Else
          If MsgBox("IE标题栏已被修改,是否恢复为自定义标题栏?",vbYesNo+vbQuestion) = vbYes Then
               Call SetTitle(False)
         End If
       End If
      End Sub
    代码写完了,
    我们就来试验一下吧!首先运行程序,单击“开始监视”按钮,然后打开注册表编辑器,并依次展开HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main,在右边的窗口中找到“WindowTitle”这个串值(如果没有的话就新建一个),双击它并任意修改它的值之后单击确定按钮,这时我们的程序就会弹出对话框提醒你了!当然,这个简单的程序只是一个不太完善的演示,特别表现在WaitForSingleObject的无限等待上,如果你把这段代码放在一个线程中效果会好得多。