VisualBasic Zurgriff auf HKEY_CLASSES_ROOT möglich?

Der Landvogt

Banned
Registriert
März 2010
Beiträge
4.401
Ich möchte mit VB2010 einen DWORD unter HKEY_CLASSES_ROOT auslesen. Ist das prinzipiell möglich?
Unter [HKEY_CURRENT_USER\Software\XYZ] konnte ich bereits eine Zeichenkette auslesen, das gleiche Schema funktioniert aber nicht unter HKEY_CLASSES_ROOT (auch nicht als Zeichenkette).

Dieser Code (welcher nur ein kleiner Test ist) will nicht so recht unter HKEY_CLASSES_ROOT:
Code:
Dim Favoriten As String
Favoriten = My.Computer.Registry.GetValue("HKEY_CLASSES_ROOT\CLSID\{323CA680-C24D-4099-B94D-446DD2D7249E}\ShellFolder", "Test", True)
CheckBox_Favoriten.Text = Favoriten
If Favoriten = "1" Then
  MsgBox("True (ON)")
 Else
  MsgBox("False (OFF)")
End If

Hat jemand eine Idee?

Ach ja, Zugriff auf diesen Schlüssel habe ich, per Regedit kann ich dort alles verändern.
 
Zuletzt bearbeitet:
HKEY_CLASSES_ROOT ist dynamisch und wird beim Start erstellt. Der Schlüssel HKEY_LOCAL_MACHINE\Software\Classes in den Arbeitsspeicher gelesen und als HKEY_CLASSES_ROOT zugänglich ist. Wenn Sie einen Schlüssel zum Bereich HKLM\Software\Classes hinzufügen, wird es sofort in HKCR repliziert.

http://support.microsoft.com/kb/269383/de
 
Klasse! Probiere ich morgen mal aus. :)
 
.net?
Code:
Microsoft.Win32.RegistryKey k = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey( ".txt" );
 
Zuletzt bearbeitet:
Reowulf schrieb:
HKEY_CLASSES_ROOT ist dynamisch und wird beim Start erstellt. Der Schlüssel HKEY_LOCAL_MACHINE\Software\Classes in den Arbeitsspeicher gelesen und als HKEY_CLASSES_ROOT zugänglich ist. Wenn Sie einen Schlüssel zum Bereich HKLM\Software\Classes hinzufügen, wird es sofort in HKCR repliziert.

http://support.microsoft.com/kb/269383/de
Muss ich jetzt den Schlüssel aus "HKEY_LOCAL_MACHINE\Software\Classes" einlesen anstatt aus "HKEY_CLASSES_ROOT"?
Denn das will auch nicht funktionieren.

Yuuri schrieb:
.net?
Code:
Microsoft.Win32.RegistryKey k = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey( ".txt" );
Kannst du das an meinem Beispiel erläutern?

Code:
Imports System
Imports System.Security.Permissions
Imports Microsoft.Win32

Public Class Main

    Private Sub Main_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        Dim Favoriten As String
        Favoriten = My.Computer.Registry.GetValue("HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{323CA680-C24D-4099-B94D-446DD2D7249E}\ShellFolder", "Attributes", True)
        CheckBox_Favoriten.Text = Favoriten
        If Favoriten = "a0900100" Then
            MsgBox("True (ON)")
        Else
            MsgBox("False (OFF)")
            '            CheckBox_Favoriten.Checked = True
            '        Else
            '           CheckBox_Favoriten.Checked = False
        End If
    End Sub
End Class
 
Der Landvogt schrieb:
Muss ich jetzt den Schlüssel aus "HKEY_LOCAL_MACHINE\Software\Classes" einlesen anstatt aus "HKEY_CLASSES_ROOT"?
Denn das will auch nicht funktionieren.
Kommt drauf an, ob es in HKLM oder HKCU hinterlegt ist.

http://msdn.microsoft.com/en-us/library/windows/desktop/ms724475%28v=vs.85%29.aspx schrieb:
Class registration and file name extension information is stored under both the HKEY_LOCAL_MACHINE and HKEY_CURRENT_USER keys. The HKEY_LOCAL_MACHINE\Software\Classes key contains default settings that can apply to all users on the local computer. The HKEY_CURRENT_USER\Software\Classes key contains settings that apply only to the interactive user. The HKEY_CLASSES_ROOT key provides a view of the registry that merges the information from these two sources. HKEY_CLASSES_ROOT also provides this merged view for applications designed for previous versions of Windows.
Code:
Microsoft.Win32.RegistryKey k = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey( @"CLSID\{323CA680-C24D-4099-B94D-446DD2D7249E}\ShellFolder" );
if( k != null )
{
	CheckBoxFavoriten.Text = k.GetValue( "Attributes" );
	if( CheckBoxFavoriten.Text == "a0900100" )
	{
		MessageBox( "True (ON)" );
	}
	else
	{
		MessageBox( "False (OFF)" );
	}
}
 
Yuuri schrieb:
Kommt drauf an, ob es in HKLM oder HKCU hinterlegt ist.
Ist in HKLM hinterlegt.

Dein Codebeispiel bringt bei mir 18 Fehler. Sicher, dass das für VB2010 geeignet ist, mich hat das gleich etwas stutzig gemacht?
 
Der Landvogt schrieb:
Sicher, dass das für VB2010 geeignet ist, mich hat das gleich etwas stutzig gemacht?
Natürlich nicht, das ist C#. .Net gibts aber als allgemeine Basis, das musst du schon adaptieren oder einen Konverter nehmen. ;)

http://converter.telerik.com/:
Code:
Dim k As Microsoft.Win32.RegistryKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey("CLSID\{323CA680-C24D-4099-B94D-446DD2D7249E}\ShellFolder")
If k IsNot Nothing Then
	CheckBoxFavoriten.Text = k.GetValue("Attributes")
	If CheckBoxFavoriten.Text = "a0900100" Then
		MessageBox("True (ON)")
	Else
		MessageBox("False (OFF)")
	End If
End If
 
Yuuri schrieb:
Natürlich nicht, das ist C#.
Hehe, hab mir sowas in die Richtung gedacht. :D


Ich habe das Ganze jetzt etwas angepasst ("MessageBox" muss z.B. "MsgBox" heißen), aber es tut sich nichts. Es kommt weder diese MessageBox (die ja mit einer der beiden Meldungen erscheinen müsste), noch ändert sich was am Text der Checkbox.
Ergänzung ()

So, das ganze funktioniert inzwischen schon mit dem Code aus Post #1 (auch unter [HKEY_CLASSES_ROOT]) bzw. es hat schon die ganze Zeit funktioniert, allerdings nur wenn ich den DWORD-Wert dezimal eingebe anstatt hexadezimal wie er in Regedit standardmäßig angezeigt wird. Wie ich das ändere, dass dich den hexadezimalen im Code angeben kann tüftle ich gerade.
 
Der Landvogt schrieb:
allerdings nur wenn ich den DWORD-Wert dezimal eingebe anstatt hexadezimal wie er in Regedit standardmäßig angezeigt wird. Wie ich das ändere, dass dich den hexadezimalen im Code angeben kann tüftle ich gerade.
Bist du dir sicher, dass du das korrekt übergibst und ebenso auch ausliest? Die Übergabe eines ints (zu egal welcher Basis) ist jedenfalls nicht von Belang, da dieser intern so oder so als 10100110101 o.ä. dargestellt wird. Ist dabei natürlich nur noch die Frage, ob es als 10, 0x10 oder 010 übergeben wird und ob es dann genauso als 10, 16 oder 8 zurückgegeben wird. An der Übergabe sollte es denke ich nicht liegen, insofern du das korrekt machst.
 
Egal ob ich als Hexadezimal "a0900100" oder "0xa0900100" bei
If Favoriten = "**a0900100" Then
eintrage, es funktioniert nicht. Ich weiß da grad auch nicht so recht.
 
Was sagt der Debugger? Es ist sowieso ziemlich kurios bei dir. Wieso hat der Default-Wert bei dir true, du erwartest wohl aber einen int (DWORD) und prüfst es ab als String?!
 
Das ist das (funktionierende) Ergebnis von etwas Testerei. Was müsste ich denn anstatt String wählen?

Hintergrund: Ich fange langsam wieder an nach vielen Jahren mal wieder zu programmieren. Damals noch mit VB6, jetzt mit VB2010. Das aktuelle (kleine) Projekt erweist sich doch als etwas komplizierter als gedacht (in "HKEY_CLASSES_ROOT" zu lesen und schreiben ist wesentlich komplizierter als in "HKEY_CURRENT_USER\Software", was ich problemlos hinbekomme) und für die bisherigen (recht anspruchslosen) Projekte haben die alten Kenntnisse noch ausgereicht.
Ich müsste mich da mal wieder richtig einlesen, bin aber noch auf der Suche nach einem guten Buch und momentan voller Tatendrang. :)


EDIT: Boah, das Projekt war auf x86 eingestellt anstatt AnyCPU. Da kann es unter x64 Probleme geben. Jetzt funktioniert auch der Schreibzugriff unter "HKEY_CLASSES_ROOT".
 
Zuletzt bearbeitet:
Der Landvogt schrieb:
Boah, das Projekt war auf x86 eingestellt anstatt AnyCPU. Da kann es unter x64 Probleme geben. Jetzt funktioniert auch der Schreibzugriff unter "HKEY_CLASSES_ROOT".
Vielleicht einfach von der Registry Redirection betroffen gewesen? Die CLSID-Verzeichnisse werden nämlich in HKCU und HKLM umgeleitet, entsprechend in den Wow6432Node.
 
Reowulf hatte ja bereits in Beitrag #2 geschrieben, dass "HKEY_CLASSES_ROOT" eigentlich "HKEY_LOCAL_MACHINE\Software\Classes" ist und quasi eine Verlinkung ist (da sind auch immer die gleichen Schlüssel und Werte drin und erscheinen ja parallel. Ich hatte es mit beiden versucht, aber es hat unter x64 erst funktioniert als ich das Projekt von x86 auf AnyCPU umgestellt hatte.

Momentan bin dabei herauszufinden wie ich den DWORD als Hexadezimal anstatt als Dezimal vergleichen kann (in Beitrag #5 wäre das die Zeile 11, so wie da möchte ich es angeben).
 
Der Landvogt schrieb:
Reowulf hatte ja bereits in Beitrag #2 geschrieben, dass "HKEY_CLASSES_ROOT" eigentlich "HKEY_LOCAL_MACHINE\Software\Classes" ist
... was nicht bzw. nur zum Teil stimmt, denn HKCR ist ein Verbund aus HKLM + HKCU, wobei HKCU immer Priorität genießt.
Der Landvogt schrieb:
Momentan bin dabei herauszufinden wie ich den DWORD als Hexadezimal anstatt als Dezimal vergleichen kann (in Beitrag #5 wäre das die Zeile 11, so wie da möchte ich es angeben).
Ja, was sagt der Debugger? Wie gesagt, du vermischst hier grundsätzlich drei unterschiedliche Typen. Auch wenn es ein Object zurück gibt: Einige dich auf einen und prüf dann entsprechend korrekt. Wenn ein DWORD (int) zurück kommt, wirst du beim Vergleich mit nem String wohl immer ein false erhalten, insofern nicht automatisch der int in einen string gecastet wird. Der Default von true ist hier wiederum weder mit dem erwartetem Wert, noch mit dem Vergleichswert in Einklang - null hätte ich schon eher verstanden.

Ein
Code:
If Favoriten = "**a0900100" Then
wird zusätzlich auch nicht funktionieren, denn hier prüfst du nach nem Muster, also müsstest du nen regulären Ausdruck verwenden.

Wie gesagt: Einige dich auf nen Typ (vorzugsweise int) und sieh dir an was im Debugger zurück kommt. Hast du schon mal auf
Code:
If Favoriten = &Ha0900100 Then
geprüft (wenn so die Hex-Notation in VB aussieht...)?
 
Yuuri schrieb:
Wie gesagt: Einige dich auf nen Typ (vorzugsweise int) und sieh dir an was im Debugger zurück kommt. Hast du schon mal auf
Code:
If Favoriten = [B]&H[/B]a0900100 Then
geprüft (wenn so die Hex-Notation in VB aussieht...)?
Bingo, das funktioniert. Vielen Dank!


Soweit läuft das Programm wie gewünscht, ich habe alles soweit in den Griff bekommen bis auf eine Sache von der ich nicht weiß, ob es überhaupt möglich ist:
Normalerweise sind bestimmte Schlüssel wie
HKEY_CLASSES_ROOT\CLSID\{323CA680-C24D-4099-B94D-446DD2D7249E}\ShellFolder
schreibgeschützt. Manuell kann man diesen natürlich per Regedit durch ändern der Besitzverhältnisse aufheben. Mein Programm verlangt beim Start Adminrechte, wäre es möglich, dass mein Programm die Änderung die Besitzübername vollzieht?
 
Der Landvogt schrieb:
Normalerweise sind bestimmte Schlüssel wie
HKEY_CLASSES_ROOT\CLSID\{323CA680-C24D-4099-B94D-446DD2D7249E}\ShellFolder
schreibgeschützt. Manuell kann man diesen natürlich per Regedit durch ändern der Besitzverhältnisse aufheben. Mein Programm verlangt beim Start Adminrechte, wäre es möglich, dass mein Programm die Änderung die Besitzübername vollzieht?
Klar, sieh dir mal die Methode RegistryKey.SetAccessControl an.
 
Das hätte ich ja fast nicht erwartet, dass das geht. :D
Ich habe die Methode RegistryKey.SetAccessControl und die RegistrySecurity-Klasse angeschaut, bin damit aber etwas überfordert. Kannst du mir ein kurzes Beispiel geben wie ich den Schlüssel
HKEY_CLASSES_ROOT\CLSID\{323CA680-C24D-4099-B94D-446DD2D7249E}\ShellFolder
für den aktuell angemeldeten Benutzer (das Programm hat Adminrechte) modifizierbar mache?



Inzwischen tut sich ein anderes Problem auf:

Ich möchte einen Registry-Eintrag abfragen und als Variable zwischenspeichern, dieser kann jedoch ein DWord (Bsp: "&H11") sein aber auch eine Zeichenkette (Bsp "C:")(weiß ich im voraus nicht). Diese Variable soll mit Werten aus einer ComboBox (bei der mehrere Einträge vorgegeben sind) abgeglichen werden:
Code:
If Variable1 = &H0 Then
ComboBox1.Text = "Irgendwas"
End If
Insgesamt habe ich 5 ComboBoxen. Die eingelesen Werte aus der Registry werden korrekt eingelesen und als Text in die ComboBox eingetragen. Allerdings funktioniert die Liste der ComboBoxen nur dann solange, solange der Wert eines Registry-Eintrags ein DWord wie "&H11" ist, bei einer Zeichenkette wie "C:" wird die Liste der nächsten ComboBoxen nicht mehr angezeigt.

Beispiel:
1. ComboBox: Textinhalt "Irgendwas 1" basierend auf Registry-Eintrag "&H11" (DWord) -> ComboBox-Liste wird korrekt angezeigt
2. ComboBox: Textinhalt "Irgendwas 2" basierend auf Registry-Eintrag "&H12" (DWord) -> ComboBox-Liste wird korrekt angezeigt
3. ComboBox: Textinhalt "C:" basierend auf Registry-Eintrag "C:" (Zeichenkette) -> ComboBox-Liste wird korrekt angezeigt
4. ComboBox: Textinhalt "C:\ABC" basierend auf Registry-Eintrag "C:\ABC" (Zeichenkette) -> ComboBox-Liste wird nicht angezeigt
5. ComboBox: Textinhalt "D:\ABC DEF" basierend auf Registry-Eintrag "D:\ABC DEF" (Zeichenkette) -> ComboBox-Liste wird nicht angezeigt

Ich nehme mal an, dass das an der Deklaration o.Ä. liegt:
Code:
Dim Variable1 As Object
Variable1 = My.Computer.Registry.GetValue("HKEY_CURRENT_USER\Software\XYZ", "Irgendwas", "Default Value")
ComboBox1.Text = Variable1
Dies habe ich auch versucht:
Code:
Dim Variable1 As String
Variable1 = My.Computer.Registry.GetValue("HKEY_CURRENT_USER\Software\XYZ", "Irgendwas", Nothing)
ComboBox1.Text = Variable1
Und auch das:
Code:
Dim Variable1 = My.Computer.Registry.GetValue("HKEY_CURRENT_USER\Software\XYT", "Irgendwas", Nothing)
ComboBox1.Text = Variable1
Hast du da eine Idee?
 
Zuletzt bearbeitet: (Formatierung)
Der Landvogt schrieb:
für den aktuell angemeldeten Benutzer (das Programm hat Adminrechte) modifizierbar mache?
Laut den Berechtigungen hat nur den TrustedInstaller Zugriff auf den Schlüssel. Dafür wirst du aber ein wenig basteln müssen, denn so einfach einen Prozess als TrustedInstaller laufen zu lassen, ist es nicht. Vielleicht das als Anreiz.
Der Landvogt schrieb:
Ich möchte einen Registry-Eintrag abfragen und als Variable zwischenspeichern, dieser kann jedoch ein DWord (Bsp: "&H11") sein aber auch eine Zeichenkette (Bsp "C:")(weiß ich im voraus nicht).
Sieh dir dazu die Funktion GetValueKind() an. Dann kannst du entsprechend reagieren und die folgenden ComboBoxen ein-/ausblenden oder de-/aktivieren.
 
Zurück
Oben