我使用了下面的代码,代码工作正常,也检索到了数据,但是性能上存在问题。检索HKLM注册表节点需要大约6分钟的时间。请提出任何解决方案。
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发布于 2019-11-13 04:00:10
在我看来,您最大的问题之一是直接使用Nodes of TreeView。这需要每次添加节点时调用Paint()。如果以新的TreeNode作为根,并在此基础上构建树,则可以通过将根添加到TreeView中将整个内容添加到Nodes中。
我还发现,作为管理员运行VS大大减少了错误的数量,这也加快了它的速度。
通过使用从TreeNode继承的自定义Forms.TreeNode类,可以递归地填充类内的树。这还允许您在每个节点中存储实际的RegistryKey对象。以下是一种相对简单的方法:
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事件处理程序加载要展开的键的子节点。就像这样:
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类之外。如果需要,还可以在添加子节点之后循环遍历键的值。
https://codereview.stackexchange.com/questions/232234
复制相似问题