首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >检索Windows10注册表的HKLM节点

检索Windows10注册表的HKLM节点
EN

Code Review用户
提问于 2019-11-12 09:55:50
回答 1查看 60关注 0票数 2

我使用了下面的代码,代码工作正常,也检索到了数据,但是性能上存在问题。检索HKLM注册表节点需要大约6分钟的时间。请提出任何解决方案。

代码语言:javascript
复制
Private Function f_AddNodes(ByVal WindowsRegistryKey As RegistryKey, ByVal TreeNode As TreeNodeCollection, ByVal RegParent As Integer) As Integer
        Dim root As TreeNode
        If count = 1 Then
            root = TreeNode(RegParent)
        Else
            Dim KeyName = WindowsRegistryKey.Name
            Dim nLastIndex = KeyName.LastIndexOf("\")
            KeyName = KeyName.Substring(nLastIndex + 1, (KeyName.Length - 1) - nLastIndex)
            root = TreeNode.Add(KeyName) 'Node adding
        End If

        For Each subkeyName As String In WindowsRegistryKey.GetSubKeyNames
            Try
                Form_LoadingBar.Value(WindowsRegistryKey.Name)
                count = count + 1
                Dim vSubKey As RegistryKey = WindowsRegistryKey.OpenSubKey(subkeyName)
                f_AddNodes(vSubKey, root.Nodes, -1)
            Catch ex As SecurityException
                sExceptionHandling.Append(WindowsRegistryKey.Name + "\" + subkeyName + "," + ex.Message + vbNewLine)
            Catch ex As Exception
                MsgBox(ex.ToString)
                Return -1
            End Try
        Next`enter code here`
        Return 0
    End Function
EN

回答 1

Code Review用户

发布于 2019-11-13 04:00:10

在我看来,您最大的问题之一是直接使用Nodes of TreeView。这需要每次添加节点时调用Paint()。如果以新的TreeNode作为根,并在此基础上构建树,则可以通过将根添加到TreeView中将整个内容添加到Nodes中。

我还发现,作为管理员运行VS大大减少了错误的数量,这也加快了它的速度。

通过使用从TreeNode继承的自定义Forms.TreeNode类,可以递归地填充类内的树。这还允许您在每个节点中存储实际的RegistryKey对象。以下是一种相对简单的方法:

代码语言:javascript
复制
Public Class RegistryTreeNode
    Inherits TreeNode
    Private Class SecurityExceptionLogger
        Private Shared Property Exceptions As New List(Of (String, SecurityException))
        Private Shared TempFileName As String = Path.GetTempFileName()
        Private Shared writer As StreamWriter
        Private Shared reader As StreamReader
        Public Shared Async Sub Add(exception As SecurityException)
            Exceptions.Add((Now.ToUniversalTime, exception))
            Using writer = New StreamWriter(TempFileName, True)
                Await writer.WriteLineAsync($"{Now.ToUniversalTime} - {exception.Message}")
            End Using
        End Sub
        Public Shared Sub PrintExceptions(stream As StreamWriter)
            Using stream
                Exceptions.ForEach(Async Sub(x)
                                       Await stream.WriteLineAsync($"{x.Item1} - {x.Item2.Message}")
                                   End Sub)
            End Using
        End Sub

    End Class
    Private _RegKey As RegistryKey

    Private Property RegKey As RegistryKey
        Get
            Return _RegKey
        End Get
        Set
            _RegKey = Value
            Name = _RegKey.Name
            Text = Name
            For Each key In _RegKey.GetSubKeyNames
                Try
                    Nodes.Add(New RegistryTreeNode(_RegKey.OpenSubKey(key)))
                Catch ex As SecurityException
                    SecurityExceptionLogger.Add(ex)
                Catch ex As Exception
                    MsgBox(ex.Message)
                End Try
            Next
        End Set
    End Property

    Public Sub New()
        MyBase.New()
        RegKey = Registry.LocalMachine
    End Sub
    Public Sub New(newRegistryKey As RegistryKey)
        MyBase.New()
        RegKey = newRegistryKey
    End Sub
End Class

我将默认密钥硬编码为Registry.LocalMachine,以供您使用。简单地说,Dim root = New RegistryTreeNode()和整棵树将构建自己。

您会注意到,我做了一个简单的记录器,它将写入文件,并将记录保存在内存中,而不仅仅是在内存中,这只是一个练习。

另一种加快速度的方法是,在启动时只加载节点的第一个子级别。然后,可以使用AfterSelect事件处理程序加载要展开的键的子节点。就像这样:

代码语言:javascript
复制
Public Class Form1
    Dim root = New RegistryTreeNode(Registry.LocalMachine)
    Public Sub New()

        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        TreeView1.Nodes.Add(root)
    End Sub


    Private Sub TreeView1_AfterSelect(sender As Object, e As TreeViewEventArgs) Handles TreeView1.AfterSelect
        Dim node = DirectCast(TreeView1.SelectedNode, RegistryTreeNode)
        For Each key In node.GetSubKeyNames
            Try
                Dim regKey = New RegistryTreeNode(node.OpenSubKey(key))
                If Not regKey Is Nothing Then
                    node.Nodes.Add(regKey)
                End If

            Catch ex As SecurityException
                SecurityExceptionLogger.Add(ex)
            Catch ex As Exception
                MsgBox(ex.Message)
            End Try
        Next

    End Sub

End Class
Class SecurityExceptionLogger
    Private Shared Property Exceptions As New List(Of (String, SecurityException))
    Private Shared TempFileName As String = Path.GetTempFileName()
    Private Shared writer As StreamWriter
    Private Shared reader As StreamReader
    Public Shared Async Sub Add(exception As SecurityException)
        Exceptions.Add((Now.ToUniversalTime, exception))
        Using writer = New StreamWriter(TempFileName, True)
            Await writer.WriteLineAsync($"{Now.ToUniversalTime} - {exception.Message}")
        End Using
    End Sub
    Public Shared Sub PrintExceptions(stream As StreamWriter)
        Using stream
            Exceptions.ForEach(Async Sub(x)
                                   Await stream.WriteLineAsync($"{x.Item1} - {x.Item2.Message}")
                               End Sub)
        End Using
    End Sub

End Class
Public Class RegistryTreeNode
    Inherits TreeNode

    Private _RegKey As RegistryKey

    Private Property RegKey As RegistryKey
        Get
            Return _RegKey
        End Get
        Set
            _RegKey = Value
            Name = _RegKey.Name
            Text = Name.Substring(Name.LastIndexOf("\"c) + 1)

        End Set
    End Property

    Public Sub New()
        MyBase.New()
        RegKey = Registry.LocalMachine
    End Sub
    Public Sub New(newRegistryKey As RegistryKey)
        MyBase.New()
        RegKey = newRegistryKey
    End Sub
    Public Function GetValueNames() As List(Of String)
        Return _RegKey.GetValueNames().ToList()
    End Function
    Public Function GetValueKind(name As String) As RegistryValueKind
        Return _RegKey.GetValueKind(name)
    End Function
    Public Function GetValue(name As String) As Object
        Return _RegKey.GetValue(name)
    End Function
    Public Function GetSubKeyNames() As String()
        Return _RegKey.GetSubKeyNames()
    End Function
    Public Function OpenSubKey(key As String) As RegistryKey
        Return _RegKey.OpenSubKey(key)
    End Function
End Class

我将SecurityExceptionLogger移到RegistryTreeNode类之外。如果需要,还可以在添加子节点之后循环遍历键的值。

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/232234

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档