RegistrySecurityException

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von Bagplatt.

    RegistrySecurityException

    Hallo zusammen,

    Ich wollte mir ein Programm zum abgleichen der Registry erstellen. Die Werte der Registry trage ich in eine Klasse ein. Doch beim inneren Instanzieren einer neuen SubkeyKlasse krachts. :S

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports Microsoft.Win32
    2. ''' <summary>
    3. ''' <code>Klasse mit allen SubKeys und Werten</code>
    4. ''' </summary>
    5. ''' <remarks></remarks>
    6. Public Class RegistryStammContainer
    7. Private SubContainer(0) As RegistrySubKey
    8. Public Sub New(ByVal hKey As RegistryKey)
    9. 'Erste SubKeys Öffnen
    10. For Each sbk As String In hKey.GetSubKeyNames()
    11. AddSubContainer(New RegistrySubKey(hKey.ToString & "\" & sbk & "\"))
    12. Next
    13. End Sub
    14. ''' <summary>
    15. ''' <code>Fügt einen SubKeyContainer in das Array ein.</code>
    16. ''' </summary>
    17. ''' <param name="container">Der Container der eingefügt werden soll.</param>
    18. ''' <remarks></remarks>
    19. Public Sub AddSubContainer(ByVal container As RegistrySubKey)
    20. ReDim Preserve SubContainer(SubContainer.Length)
    21. SubContainer(SubContainer.Length) = container
    22. End Sub
    23. End Class
    24. ''' <summary>
    25. ''' <code>Enthält die Subkeys und Werte</code>
    26. ''' </summary>
    27. ''' <remarks></remarks>
    28. Public Class RegistrySubKey
    29. Private hKey As RegistryKey
    30. Private subPfad As String
    31. Private RegistryValue(0) As RegistryValue
    32. Private RegistrySubKeys(0) As RegistrySubKey
    33. Public Sub New(ByVal CurrentPfad As String)
    34. 'Wird immer wieder aufgerufen. So dass alle Subkeys vorhanden sind
    35. 'Erst den Stammschlüsseln besorgen um die Subkeys auszulesen.
    36. 'Den Pfad vom Stammschlüssel trennen.
    37. With ParseString(CurrentPfad)
    38. hKey = .hKey
    39. subPfad = .SubPfad
    40. End With
    41. 'Eventuell vorhandene Valuebereiche einlesen
    42. For Each v As String In hKey.OpenSubKey(subPfad).GetValueNames()
    43. AddRegistryValue(CreateRegistryValue(v))
    44. Next
    45. 'Eventuell vorhandene Subkeys einlesen
    46. For Each s As String In hKey.OpenSubKey(subPfad).GetSubKeyNames
    47. Debug.WriteLine("Subkey wird erstellt : " & CurrentPfad & "\" & s & "\")
    48. AddSubContainer(CurrentPfad & "\" & s & "\") ' <- Überprüfen ob dass Format so stimmt
    49. Next
    50. End Sub
    51. ''' <summary>
    52. ''' <code>Löst den String in den Stammschlüssel und den SubPfad auf-</code>
    53. ''' </summary>
    54. ''' <param name="sValue">Der Pfad</param>
    55. ''' <returns></returns>
    56. ''' <remarks></remarks>
    57. Public Function ParseString(ByVal sValue As String) As RegParse
    58. If sValue.Contains(Registry.ClassesRoot.ToString) Then
    59. Dim rg As New RegParse With {.hKey = Registry.ClassesRoot, .SubPfad = sValue.Replace(Registry.ClassesRoot.ToString, "")}
    60. Return rg
    61. ElseIf sValue.Contains(Registry.CurrentConfig.ToString) Then
    62. Dim rg As New RegParse With {.hKey = Registry.CurrentConfig, .SubPfad = sValue.Replace(Registry.CurrentConfig.ToString, "")}
    63. Return rg
    64. ElseIf sValue.Contains(Registry.CurrentUser.ToString) Then
    65. Dim rg As New RegParse With {.hKey = Registry.CurrentUser, .SubPfad = sValue.Replace(Registry.CurrentUser.ToString, "")}
    66. Return rg
    67. ElseIf sValue.Contains(Registry.LocalMachine.ToString) Then
    68. Dim rg As New RegParse With {.hKey = Registry.LocalMachine, .SubPfad = sValue.Replace(Registry.LocalMachine.ToString, "")}
    69. Return rg
    70. ElseIf sValue.Contains(Registry.PerformanceData.ToString) Then
    71. Dim rg As New RegParse With {.hKey = Registry.PerformanceData, .SubPfad = sValue.Replace(Registry.PerformanceData.ToString, "")}
    72. Return rg
    73. ElseIf sValue.Contains(Registry.Users.ToString) Then
    74. Dim rg As New RegParse With {.hKey = Registry.Users, .SubPfad = sValue.Replace(Registry.Users.ToString, "")}
    75. Return rg
    76. Else
    77. Throw New Exception("Konnte den Pfad : " & sValue & " nicht auflösen.")
    78. End If
    79. End Function
    80. ''' <summary>
    81. ''' <code>Erstellt eine neue Struktur für die RegistryValue</code>
    82. ''' </summary>
    83. ''' <param name="ValName">Der Name des Eintrags</param>
    84. ''' <returns></returns>
    85. ''' <remarks></remarks>
    86. Public Function CreateRegistryValue(ByVal ValName As String) As RegistryValue
    87. Return New RegistryValue With {.value = hKey.OpenSubKey(subPfad).GetValue(ValName), .valueKind = hKey.OpenSubKey(subPfad).GetValueKind(ValName)}
    88. End Function
    89. ''' <summary>
    90. ''' <code>Fügt einen neuen Registryeintrag in das Array ein.</code>
    91. ''' </summary>
    92. ''' <param name="Eintrag"></param>
    93. ''' <remarks></remarks>
    94. Public Sub AddRegistryValue(ByVal Eintrag As RegistryValue)
    95. ReDim Preserve RegistryValue(RegistryValue.Length)
    96. RegistryValue(RegistryValue.Length) = Eintrag
    97. End Sub
    98. ''' <summary>
    99. ''' <code>Erstellt einen neuen Subkey und fügt ihn in dass Array ein.</code>
    100. ''' </summary>
    101. ''' <param name="sPfad">Der Pfad für den Subkey.</param>
    102. ''' <remarks></remarks>
    103. Public Sub AddSubContainer(ByVal sPfad As String)
    104. ReDim Preserve RegistrySubKeys(RegistrySubKeys.Length)
    105. RegistrySubKeys(RegistrySubKeys.Length) = New RegistrySubKey(sPfad)
    106. End Sub
    107. End Class
    108. ''' <summary>
    109. ''' <code>Struktur zum speichern eines Eintrages in der Registry.</code>
    110. ''' </summary>
    111. ''' <remarks></remarks>
    112. Public Structure RegistryValue
    113. Public valueKind As RegistryValueKind
    114. Public value As Object
    115. End Structure
    116. ''' <summary>
    117. ''' <code>Struktur zum speichern des Pfades.</code>
    118. ''' </summary>
    119. ''' <remarks></remarks>
    120. Public Structure RegParse
    121. Public hKey As RegistryKey
    122. Public SubPfad As String
    123. End Structure


    Genauer gesagt hier :

    VB.NET-Quellcode

    1. 'Eventuell vorhandene Valuebereiche einlesen
    2. For Each v As String In hKey.OpenSubKey(subPfad).GetValueNames() ' <---- Hier
    3. AddRegistryValue(CreateRegistryValue(v))
    4. Next


    Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.


    Ich kann ja den RegistryKey nicht neu Initalisieren. Zusätzlich ist dem defenetiv ein Object zugewiesen. Der Subpfad stimmt auch.

    Wenn ich in der Regedit nachschaue sind dort keine Werte enthalten die ich auslesen könnte. Wenn ich jedoch überprüfe ob der ValueCount von dem Key > 0 ist, knallts auch.

    Vielleicht liegt der Fehler auch gerade ganz wo anders. Aber die Werte sind alle Initialisiert und vorhanden.

    LG

    NACHTRAG

    Is ja schon peinlich ^^
    Lag daran gar nicht. Hab die Array falsch vergrößert. Jedoch hab ich jetzt wieder dass Problem dass ich gewisse schlüssel nicht öffnen darf.

    Wieder die gleiche Stelle : Der angeforderte Registrierungszugriff ist unzulässig.


    Programm hat Administrator rechte. Kann ich dass ohne TryCatch abfragen?

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Bagplatt“ ()

    @Bagplatt Setz einen Haltepunkt drauf und stell fest, welches Objekt nicht instanziiert wurde.
    Ich würde mal wetten, dass hKey = Nothing ist.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hey,

    Die Klasse instanzier ich einfach

    VB.NET-Quellcode

    1. Dim Contain As New RegistryStammContainer(Registry.CurrentUser)


    Den einen Fehler hab ich so weit schon selbst gefunden. Hab Die Arrays falsch vergrößert so dass gar nichts eingefügt worden ist.

    VB.NET-Quellcode

    1. ''' <summary>
    2. ''' <code>Fügt einen neuen Registryeintrag in das Array ein.</code>
    3. ''' </summary>
    4. ''' <param name="Eintrag"></param>
    5. ''' <remarks></remarks>
    6. Public Sub AddRegistryValue(ByVal Eintrag As RegistryValue)
    7. Dim c As Integer = RegistryValue.Length + 1
    8. ReDim Preserve RegistryValue(c)
    9. RegistryValue(c) = Eintrag
    10. End Sub
    11. ''' <summary>
    12. ''' <code>Erstellt einen neuen Subkey und fügt ihn in dass Array ein.</code>
    13. ''' </summary>
    14. ''' <param name="sPfad">Der Pfad für den Subkey.</param>
    15. ''' <remarks></remarks>
    16. Public Sub AddSubContainer(ByVal sPfad As String)
    17. Dim c As Integer = RegistrySubKeys.Length + 1
    18. ReDim Preserve RegistrySubKeys(c)
    19. RegistrySubKeys(c) = New RegistrySubKey(sPfad)
    20. End Sub


    So gehts besser ^^

    Doch bei bestimmten Schlüssel grieg ich den Fehler


    Security Exception
    Der angeforderte Registrierungszugriff ist unzulässig.


    VB.NET-Quellcode

    1. hKey.OpenSubKey(subPfad).GetAccessControl


    Damit kann ich mir (glaube ich) die Zugriffseinstellungen holen.
    Hab mir dass ein weinig angeschaut doch ich finde keine Eintrag wo angibt dass ich den Schlüssel bzw. den Wert lesen darf.

    Lg

    Nachtrag

    Ich kann mir damit auch nicht die Sicherheitseinstellungen holen, da ich ja die Rechte nicht besitze :D
    Als Lösung sollte ich ein Zertifikat verwenden. MSDN Verweis : msdn.microsoft.com/query/dev10…E&k=k(EHSECURITY)&rd=true
    Keine Lösung passt so auf dass Problem.

    Ich schau mal im ObjectBrowser durch.

    Die gesperrten Bereiche muss ich nicht mal umbedingt lesen, jedoch würde ich dass ganz gerne ohne TryCatch überprüfen.

    @Fakiz

    Dass Programm hat Adminrechte, und Benutzerkontensteuerung hab ich mal Testweise deaktiviert gehabt.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Bagplatt“ ()

    Also :D sowas sollte man auf keinen Fall eingeben :

    VB.NET-Quellcode

    1. Dim SecurytAcess As RegistrySecurity = hKey.OpenSubKey(subPfad).GetAccessControl()
    2. Dim AddRules As RegistryAccessRule = New RegistryAccessRule("Administrator", RegistryRights.ReadKey, InheritanceFlags.None, PropagationFlags.None, AccessControlType.Allow)
    3. SecurytAcess.AddAccessRule(AddRules)
    4. hKey.SetAccessControl(SecurytAcess)


    Sonder nur wenn man den Computer neu aufsetzen will. Nach einem schönem Tipp auf Msdn dachte ich mir propierste es mal aus.


    Absoluter Fehler. X(



    Wenn jemand eine Idee hat, wie ich ohne TryCatch überprüfen kann ob ich den Bereich lesen kann, wäre ich dankbar :)

    LG

    Bagplatt schrieb:

    VB.NET-Quellcode

    1. ReDim Preserve RegistryValue(c)
    Lass dieses Umdimensionieren.
    Nimm eine List(Of T) und feddich.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:

    Lass dieses Umdimensionieren.
    Nimm eine List(Of T) und feddich.


    Dachte dass das die Performance etwas schont, wobei die List(Of T) warscheinlich beim hinzufügen dass gleiche tut.

    Weist du wie ich ohne TryCatch überprüfen kann ob ich den SubKey öffnen kann?
    Hab es mal um beide Schleifen gehauen, doch dass geht schon arg auf die Geschwindigkeit, da einige Ausnahmen ausgelöst werden.
    Die List redimensioniert besser. Sie vergrößert das Array nicht um 1 sondern vergrößert das Array um 4 oder 8 Stellen (weiß es nicht mehr ganz genau, kann auch sein das es abhängig von der Anzahl der schon vorhandenen Werte ist).

    Und es gibt vermutlich keine Möglichkeit das ohne Try Catch zu lösen. Es gibt die Klasse RegistryPermission, aber die arbeitet auch mit Exceptions.
    Dies ist afaik auch der Ansatz von MS für die meisten "Fehlerbehandlungen".

    Ist das Ganze denn iwie extrem Performance kritisch ?
    Das ist meine Signatur und sie wird wunderbar sein!

    Mono schrieb:

    Ist das Ganze denn iwie extrem Performance kritisch ?


    Naja,
    Sind genau 1600 Exceptions die bei LOCAL_MACHINE auftreten. Würde dass schon als Perfomance Kritisch ansehen.
    Ich kann mir zur Zeit auch kein Ansatz für die Lösung machen. Da ich nicht einmal die Rechte des Schlüssel lesen darf.
    Und dass Programm selbst hat schon Erhöhte Rechte.
    Es gibt meines Wissens keinen anderen Ansatz in .NET. Mit performance kritisch meinte ich nicht, ob es lange dauert sondern ob es wichtig ist, dass es so schnell wie möglich geht.
    Eine komplette Registry einzulesen dauert halt für gewöhnlich, siehe iwelche RegScan Tools.
    Könntest vll Parallel.For() verwenden. Wie lang dauert es denn jetzt?

    Du könntest natürlich auch beide Registries komplett in eine Datei exportieren und diese dann vergleichen (zB mit WinDIFF) oder REGDIFF nutzen.

    LG
    Das ist meine Signatur und sie wird wunderbar sein!

    Mono schrieb:

    Wie lang dauert es denn jetzt?


    Also für den LOCAL_MACHINE Stamm dauert es 21 sekunden.

    Mir ist noch eventuell ein Ansatz eingefallen. In jedem Key ist ja ein Wert mit dem Namen (Standart). Über die Klasse Registry kann ich mir einen Wert holen, wenn es den nicht gibt, gibt er mir ein Vorgegebenen Wert zurück

    VB.NET-Quellcode

    1. Registry.GetValue("WERT", "NAME", Nothing)


    Muss ich nur ausprobieren, ob diese "Standart" Werte auch lesbar sind. Und ob dann tzd. eine RegistrySecurityException auftritt.

    LG
    Unter 10 Sekunden. ^^
    Ich probier dass gleich mal mit der ParallelFor

    Update

    Vielleicht liegt es an der ParallelForEach :

    VB.NET-Quellcode

    1. Dim ValNames() As String = hKey.OpenSubKey(subPfad, False, RegistryRights.ReadKey).GetValueNames
    2. Parallel.ForEach(ValNames, Sub(readValNames)
    3. AddRegistryValue(CreateRegistryValue(readValNames))
    4. End Sub)


    die ich heute zum ersten mal verwende :D aber da kracht es dann ordentlich, dass Redimensionieren klappt dann nicht mehr, und dass Programm lief so lang dass ich gar kein Ergebniss bekam und es Stoppte :rolleyes:
    Ist der Ablauf der ParallelForEach Schleife so richtig?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Bagplatt“ ()