Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Probleme mit Registry-Abfrage von zwei Registry-Pfaden
Little Tester
myCSharp.de - Member



Dabei seit:
Beiträge: 77

Themenstarter:

Probleme mit Registry-Abfrage von zwei Registry-Pfaden

beantworten | zitieren | melden

Zunächst: Ich habe eine Lösung für das Problem, aber der daraus entstandene Code ist sehr umständlich und lang geworden. Ich hatte überlegt den Code erst in die Rubrik Code-Reviews zu posten und um Vorschläge zu bitten. Da ich aber selbst schon eine Vorstellung davon habe, wie das am Ende aussehen könnte (sollte?), aber daran scheitere habe ich es hier gepostet.

Ich habe hier eine Abfrage in der Registry. Tests auf verschiedenen Rechnern ergab, dass sich der gesuchte Schlüssel in zwei Pfaden verstecken kann.
Ich hatte es mir so vorgestellt, dass ich den Code wie folgt schreibe, aber nun weiß ich nicht, wie ich an den Wert von GetValue komme. Selbst, wenn ich GetValue extra nochmal abfrage, fehlt mir die Variable um auf den Registry-Pfad zuzugreifen. Alle Versuche da was vorne an zu stellen münden in einem Fehler. Könnt ihr mir bitte helfen?


            // Citrix Workspace Version ermitteln
            try
            {
                if (RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64).OpenSubKey(@"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\CitrixOnlinePluginPackWeb").GetValue("DisplayVersion") == null)
                {
                    if (RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64).OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\CitrixOnlinePluginPackWeb").GetValue("DisplayVersion") == null)
                    {
                        MessageBox.Show("Nicht installiert");
                    }
                    else
                    {
                        MessageBox.Show("???");
                    }
                } else
                {
                    MessageBox.Show("???");
                }
            }
            catch (Exception)
            {
                MessageBox.Show("Problem im Abschnitt Citrix Workspace.");
            }

Edit: Achja: Sind beide Pfade ungültig ist der Debugger sehr unglücklich und gibt den gefürchteten "System.NullReferenceException: "Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt."-Fehler zurück. Ich habe den Beitrag dazu gelesen, komme damit aber nicht weiter.
Dieser Beitrag wurde 4 mal editiert, zum letzten Mal von Little Tester am .
private Nachricht | Beiträge des Benutzers
Palladin007
myCSharp.de - Member

Avatar #avatar-4140.png


Dabei seit:
Beiträge: 1496
Herkunft: Düsseldorf

beantworten | zitieren | melden


var value = GetDisplayVersionOrNull("...")
    ?? GetDisplayVersionOrNull("...");

if (value == null)
{
    // ...
}
else
{
    // ...
}

Muss keine eigene Methode sein, macht das aber cleaner.

Ach und guck dir das an:
Registry.GetValue(String, String, Object) Methode (Microsoft.Win32)
Erspart dir vermutlich die eigene GetDisplayVersion-Methode.

Und Thema NullReference:

Packs in eine Variable und prüf drauf, in der eigenen Methode kein Problem.
Oder so:


var value = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64).OpenSubKey("...")?.GetValue("DisplayVersion");
Beachte das Fragezeichen vor "GetValue".
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Palladin007 am .
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4093

beantworten | zitieren | melden

Hallo Little Tester,

du scheinst ja mehrere dieser Registry-Lesemethoden zu haben (und anscheinend immer mit demselben Aufbau)?! Schreib dir eine Methode (mit passenden Parametern) dafür.
Und außerdem solltest du Datenzugriff (Registry) und UI (MessageBox) nicht mischen (s. [Artikel] Drei-Schichten-Architektur), also verwende dafür zwei verschiedene Methoden (in verschiedenen Klassen).

Und dein Exception-Handling ist auch etwas unspezifisch (und nicht sehr aussagefähig): du solltest wenigstens die Exception Message(s) ausgeben bzw. noch besser zusätzlich loggen (Abt wird vermutlich wieder eine Logging-Komponente dafür vorschlagen ;-).

Edit: Am besten legst du dir für die Parameter (Registry-Werte, Texte, ...) eine eigene Datenstruktur an und erzeugst dann ein (statisches) Array davon und rufst dann in einer Schleife die Methode auf (Trennung von Code und Daten).
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Th69 am .
private Nachricht | Beiträge des Benutzers
Little Tester
myCSharp.de - Member



Dabei seit:
Beiträge: 77

Themenstarter:

beantworten | zitieren | melden

Danke für eure Antworten. Jetzt sieht der Code so aus, ist viel schöner und übersichtlicher und funktioniert . War das so gemeint? Warum muss man bei der Abfrage ?? verwenden und nicht ||. Ist ?? sowas wie eine "X ODER Y"-Abfrage? Dann müsste doch || genauso funktionieren? Für was steht das ? vor dem GetValue? Ich kannte das noch gar nicht.
Die MessageBoxen habe ich nur während der Entwicklung. Wenn es funktioniert landen die Werte natürlich in Variablen.


            // Citrix Workspace Version ermitteln
            try
            {
                var test = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64).OpenSubKey(@"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\CitrixOnlinePluginPackWeb").GetValue("DisplayVersion") ?? 
                    RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64).OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\CitrixOnlinePluginPackWeb").GetValue("DisplayVersion");
                if(test == null)    
                {
                    MessageBox.Show("Nicht installiert");
                    }
                else
                {
                    MessageBox.Show(test.ToString());
                }
            }
            catch (Exception)
            {
                MessageBox.Show("Problem im Abschnitt Citrix Workspace.");
            }
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Little Tester am .
private Nachricht | Beiträge des Benutzers
JimStark
myCSharp.de - Member

Avatar #dOpLzh7hN1az1g0eGRc0.jpg


Dabei seit:
Beiträge: 284

beantworten | zitieren | melden

Zitat von Little Tester
Warum muss man bei der Abfrage ?? verwenden und nicht ||. Ist ?? sowas wie eine "X ODER Y"-Abfrage? Dann müsste doch || genauso funktionieren? Für was steht das ?


Damit kannst du auf null prüfen, siehe:
https://docs.microsoft.com/de-de/dotnet/csharp/language-reference/operators/conditional-operator
?? und ??= (Operatoren) – C#-Referenz
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4093

beantworten | zitieren | melden

Lies dir auch mal die Hinweise zu RegistryKey (bes. der "Wichtig"-Abschnitt) durch, also sollte der Code in eine using-Anweisung gepackt werden (auch wenn nur ausgelesen wird).
Dudurch sollte dein bisheriger Code auch leserlicher werden.

Auch macht m.E. das doppelte Abfragen der Registry (WOW6432Node) keinen Sinn - entweder du benötigst die 32 oder 64-Bit Variante.
Hast du "AnyCPU" im Projekt eingestellt?

Oder ist dein Programm nur ein Test für die installierten Komponenten und benutzt sie selber nicht?
private Nachricht | Beiträge des Benutzers
Little Tester
myCSharp.de - Member



Dabei seit:
Beiträge: 77

Themenstarter:

beantworten | zitieren | melden

Danke euch. Ich habe das using bei den Abfragen überall vorne angestellt, wo ein IDisposable in der Definition ist. Das ist ja bei ManagementObjectCollection auch der Fall.

Das Projekt steht definitiv auf AnyCDU, sowohl bei Debug, als auch Release. Den Fehler mache ich nicht noch einmal

Bei der in diesem Thread genannten Abfrage klappt das mit dem using aber nicht. Kann machen was ich will, endet immer in einem Fehler . Das diese Doppelte Abfrage so kompliziert sein muss *grummel*

Warum sich der Citrix Workspace-Client manchmal in HKLM und manchmal in HKCU einträgt weiß ich nicht. Bei mir hier zu Hause und bei meinem Arbeitsplatz bei meinem einen Arbeitgeber findet sich der Eintrag in HKLM, bei meinem Arbeitsplatz beim anderen Arbeitgeber in HKCU.
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15976

beantworten | zitieren | melden

Zitat
Oder ist dein Programm nur ein Test für die installierten Komponenten und benutzt sie selber nicht?
Er baut offenbar ein rudimentäres Software-Inventartool.
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4093

beantworten | zitieren | melden

Scheint so.

Little Tester: Bei vielen Installationen kann man auswählen, ob für alle Anwender (HKLM) oder nur für den aktuellen Anwender (HKCU) installiert werden soll.
private Nachricht | Beiträge des Benutzers
Little Tester
myCSharp.de - Member



Dabei seit:
Beiträge: 77

Themenstarter:

beantworten | zitieren | melden

Kann natürlich sein. Bei dem einen Arbeitgeber, wo ich der Admin installiere ich die Software immer als Admin von Hand. Habe da leider auch keinen Server der das machen könnte. Der zweite Arbeitgeber, wo ich nur ein kleines Licht in der Abteilung bin hat hingegen eine gigantische IT-Infrastruktur mit SCCM und co. zur Verfügung. Denke mal, dass es da deswegen anders installiert wurde. Aber so prüfe ich jetzt einfach beide Pfade. Schadet ja auch nicht und gelernt habe ich auch gleich was.
private Nachricht | Beiträge des Benutzers