问题就是do while 为什么循环了4次啊..我把启动项都读取到了list中,list1中竟然有个空的..
..我注册里面只有3个启动项(包括默认项是4个),就算读取了默认项它也读取到第一个空行啊..而它是他后面的..
项名:amd_dc_opt
项值:C:\Program Files\AMD\Dual-Core Optimizer\amd_dc_opt.exe
项名:360Safetray
项值:"C:\Program Files\360\360Safe\safemon\360Tray.exe" /start
项名:NvCplDaemon
项值:RUNDLL32.EXE C:\WINDOWS\system32\NvCpl.dll,NvStartup
项名:
项值:————————————————————————————————————代码:
'RegEnumValue,的第五个参数一定是Any类型的,否则会出错!
Private Sub Command1_Click()
         Dim LngKey As Long
      RegOpenKey HKEY_LOCAL_MACHINE, "SOFTWARE\Microsoft\Windows\CurrentVersion\Run", LngKey
      Dim ValueName As String: Dim ValueData As String: Dim Ret As Long: Dim RegIndex As Integer
         RegIndex = 0
         ValueName = String(255, Chr(0))
         ValueData = String(255, Chr(0))
         Do While RegEnumValue(LngKey, RegIndex, ValueName, 255, 0&, REG_SZ, ByVal ValueData, 255) = 0
           List1.AddItem "项名:" & Left(ValueName, InStr(1, ValueName, Chr(0)) - 1)
           List1.AddItem "项值:" & Left(ValueData, InStr(1, ValueData, Chr(0)) - 1) 
          RegIndex = RegIndex + 1
          ValueName = String(255, Chr(0))
          ValueData = String(255, Chr(0))
          n = n + 1
         Loop
         Debug.Print n
 end sub(还有个小问题:在DO WHILE 循环里面每读取一次就要重新初始化ValueName与ValueData变量--)(这个有必要?书上说有意义的,,,我去掉重新初始化的那两行后返回结果也是一样的啊...没有像书上说的返回值会不正确...)
唯独只有这个API函数RegEnumValue重新初始化其他都不用的,,,

解决方案 »

  1.   

    你的代码我没调试成功,用下面这个代码吧Const HKEY_LOCAL_MACHINE = &H80000002
    Const REG_SZ = 1
    Const REG_BINARY = 3
    Private Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As Long
    Private Declare Function RegOpenKey Lib "advapi32.dll" Alias "RegOpenKeyA" (ByVal hKey As Long, ByVal lpSubKey As String, phkResult As Long) As Long
    Private Declare Function RegEnumValue Lib "advapi32.dll" Alias "RegEnumValueA" (ByVal hKey As Long, ByVal dwIndex As Long, ByVal lpValueName As String, lpcbValueName As Long, ByVal lpReserved As Long, lpType As Long, lpData As Byte, lpcbData As Long) As Long
    Private Declare Function RegQueryValueEx Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, lpType As Long, lpData As Any, lpcbData As Long) As Long
    Private Sub Command1_Click()
      Dim hKey As Long, Cnt As Long, sSave As String
      '打开指定的注册表项,这个位置保存的就是启动项
      RegOpenKey HKEY_LOCAL_MACHINE, "SOFTWARE\Microsoft\Windows\CurrentVersion\Run", hKey
      Cnt = 0
      List1.Clear
      Do
        '创建一个缓冲区,用以保存每个开机启动项
        sSave = String$(255, 0)
        '枚举第Cnt个启动项,如果返回值不为0,说明已经枚举完成
        If RegEnumValue(hKey, Cnt, sSave, 255, 0, ByVal 0&, ByVal 0&, ByVal 0&) <> 0 Then Exit Do
        '添加到list1, StripTerminator函数的作用是去除多余的字符
        List1.AddItem RegQueryStringValue(hKey, StripTerminator(sSave))
        Cnt = Cnt + 1
      Loop
      '关闭注册表项
      RegCloseKey hKey
    End Sub'去除缓冲区中多余的Chr(0)
    Private Function StripTerminator(sInput As String) As String
      Dim ZeroPos As Integer
      '找到第一个Chr(0)
      ZeroPos = InStr(1, sInput, vbNullChar)
      If ZeroPos > 0 Then '如果存在,则去掉后面所有的内容
        StripTerminator = Left$(sInput, ZeroPos - 1)
      Else '如果不存在,不做任何操作
        StripTerminator = sInput
      End If
    End Function'读取注册表某项的值
    Function RegQueryStringValue(ByVal hKey As Long, ByVal strValueName As String) As String
      Dim lResult As Long, lValueType As Long, strBuf As String, lDataBufSize As Long
      '获取值的类型
      lResult = RegQueryValueEx(hKey, strValueName, 0, lValueType, ByVal 0, lDataBufSize)
      If lResult = 0 Then
        If lValueType = REG_SZ Then
          '建立缓冲区
          strBuf = String$(lDataBufSize, Chr$(0))
          '获取值
          lResult = RegQueryValueEx(hKey, strValueName, 0, 0, ByVal strBuf, lDataBufSize)
          If lResult = 0 Then
            '去掉多余的Chr(0)
            RegQueryStringValue = Left$(strBuf, InStr(1, strBuf, Chr$(0)) - 1)
          End If
        ElseIf lValueType = REG_BINARY Then
          Dim strData As Integer
          '获取值
          lResult = RegQueryValueEx(hKey, strValueName, 0, 0, strData, lDataBufSize)
          If lResult = 0 Then
            RegQueryStringValue = strData
          End If
        End If
      End If
    End Function
      

  2.   

    用 WMI 对象也可以枚举注册表的,不过API是比较快
      

  3.   

    谢谢,,没有关系..
    第二问题你知道?
    就是:
    (还有个小问题:在DO WHILE 循环里面每读取一次就要重新初始化ValueName与ValueData变量--)(这个有必要?书上说有意义的,,,我去掉重新初始化的那两行后返回结果也是一样的啊...没有像书上说的返回值会不正确...)
    唯独只有这个API函数RegEnumValue重新初始化其他都不用的,,,
      

  4.   


    是啊,,但是WMI我很少看到..书上基本没有说:但是WMI对象写起来代码比较少..
    我看过API写个进程枚举一大堆代码..但是WMI就比API少得多了..
      

  5.   

    RegQueryStringValue 汗..没有学过.
      

  6.   


    说实话,我没太明白你的这第二个问题,按我的理解,ValueName与ValueData变量还是要重新初始化的,这是程序开的两个缓冲区,对于函数RegEnumValue如何添充这个缓冲区的机制我们不清楚,所以还是用空字符先初始化一下吧,再用上面例程中的函数StripTerminator去除多余的空字符。这样应该更严谨一些。这里不出问题,并不能证明其它时候都对。另外例子中,只用ssave得到了值,没有取项名,你要加上的~~~
      

  7.   

    WMI 列启动项,变量未声明。    Const HKEY_LOCAL_MACHINE = &H80000002
        
        Set objReg = GetObject("winmgmts:\\.\root\default:StdRegProv")
        
        sSubKeyName = "SOFTWARE\Microsoft\Windows\CurrentVersion\Run"
        
        hDefKey = HKEY_LOCAL_MACHINE
        
        objReg.EnumValues hDefKey, sSubKeyName, sNames, iTypes  '枚举子项键名称->sNames,类型-> iTypes
        
        lReturnCode = objReg.GetStringValue(hDefKey, sSubKeyName, "", svalue)
        s = "默认:     " & svalue
        
        For Each sValueName In sNames
            lReturnCode = objReg.GetStringValue(hDefKey, sSubKeyName, sValueName, svalue)   '读键值
            If lReturnCode = 0 And Err.Number = 0 Then
                s = s & vbCrLf & sValueName & ":    " & svalue
            End If
        Next
        Debug.Print s
    详细函数在http://blog.csdn.net/z_wenqian/archive/2011/04/28/6368825.aspx中有。
      

  8.   

    哈哈,,,终于知道为什么循环4次了...我打开Msconfig看见有一个启动项竟然没有名字好值..不知道什么开机启动项,注册表也看不见..我已经禁用了...后来就读取成功了...
      

  9.   

    用 WMI 就不会出现这种情况。