Autor Beitrag
dolly
Hält's aus hier
Beiträge: 4



BeitragVerfasst: Do 19.03.09 15:00 
Hallo zusammen,

versuche gerade mich in C# (speziell Windows Forms) einzuarbeiten, daher bitte ich schonmal von vorne herein um Verzeihung, falls dieses Thema woanders bereits abgehandelt wurde - ich habe gesucht, hier im Forum und auch ueber Suchmaschinen.

Hier das Problem:
Ich lese einen Registry Key aus (HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall). Die Unterelemente sind GUIDs (also {A1B2C3xxxxx...}). Diese GUID Keys haben wiederum Key Value Tuple wie z.B. "DisplayName" und "UninstallString".
Wenn ich nun den ersten Teil dieser Tuples in die Listbox ausgebe (also DisplayName, heisst in der Liste stehen alle Applikationen, die auf dem System installiert sind), kann ich nicht zu dem anderen Teil des Tuples (UninstallString) aufloesen, weil die Listbox nur den DisplayName speichern kann.

Jetzt koennte ich ueber einen DataTable oder ein Dictionary "DisplayName" zu "UninstallString" aufloesen, das funktioniert aber deshalb nicht, weil z.B. MS Office 2007 SP1 mehrfach in der Liste auftaucht (bzw. verschiedene Keys haben in ihrem Subkey "DisplayName" den String "MS Office 2007 SP1"). DisplayName taugt also nicht als "unique identifier".

In HTML wuerde die Liste schlicht und einfach als hidden value oder einfach ueber <a href=scriptlink?id=ID> eingebunden und somit den Zugang zum Parent Key ermoeglichen. In einer Listbox kann ich das meines Wissens nicht tun...

Hat jemand eine Idee oder Tipp, wie das gemacht werden koennte? Ich habe was von XAML gelesen - ist das die einzige Loesung?



Hier ein bisschen Code dazu, lese Keys aus, speichere die Daten in einem 2-D Rectangular Array und gebe sie dann in einer Listbox aus:

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Win32;

namespace GetStarted
{
    class RegistryHandler
    {
        public String hostname;
        public RegistryKey rk;
        public String[,] regDataTuples;
        public ArrayList validEntries;
        public int validEntryCount;
        public String[] DisplayName;

        public RegistryHandler(String hostname)
        {
            this.hostname = hostname;
        }

        public bool checkHostname()
        {
            try
            {
                this.rk = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, this.hostname);
                return true;
            }
            catch { return false; }
        }

        public void getResults()
        {            
            if (this.rk != null
                this.rk = rk.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\");
                String[] regValues = this.rk.GetSubKeyNames();
                validEntryCount = 0;
                ArrayList validEntries = new ArrayList();
                foreach (String s in regValues)
                {
                      RegistryKey temprk = this.rk.OpenSubKey(s);
                      if (temprk.GetValue("DisplayName") != null && temprk.GetValue("UninstallString") != null && (String)temprk.GetValue("DisplayName") != "" && (String)temprk.GetValue("UninstallString") != "")
                      {
                          validEntryCount++;
                          validEntries.Add(s);
                      }
                }

                this.regDataTuples = new String[2,validEntryCount];
                this.DisplayName = new String[validEntryCount];
                int i = 0;
                foreach (String s in validEntries)
                {
                    RegistryKey temprk = this.rk.OpenSubKey(s);
                    this.DisplayName[i] = temprk.GetValue("DisplayName").ToString();
                    this.regDataTuples[0,i]=temprk.GetValue("DisplayName").ToString();
                    this.regDataTuples[1,i]=temprk.GetValue("UninstallString").ToString();
                    i++;
                }
                Array.Sort(this.DisplayName);
        }
    }
}



aufgerufen wird von der Windows Forms Applikation aus:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
 public void populateList()
        {
            listBox1.Items.Clear();
            if (this.hostname_entry_textbox.Text == "")
            {
                this.listBox1.Items.Add("no hostname entered");
            }
            else
            {
                RegistryHandler rh = new RegistryHandler(this.hostname_entry_textbox.Text);
                if (rh.checkHostname())
                {
                    this.hostname_entry_textbox.Clear();
                    rh.getResults();
                    for (int i = 0; i < rh.validEntryCount; i++)
                    {
                        this.listBox1.Items.Add(rh.DisplayName[i]);
                    }
                }
                else
                {
                    this.listBox1.Items.Add("unable to connect to host");
                }
            }

        }


Bitte die Code Qualitaet zu entschuldigen, das war erstmal quick&dirty und wird aufgeraeumt, wenns einmal laeuft ;-)
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Do 19.03.09 15:19 
:welcome:


user profile icondolly hat folgendes geschrieben Zum zitierten Posting springen:
DisplayName taugt also nicht als "unique identifier".
Ganz genau. Also reicht es nicht, der ListBox nur diese Property mitzugeben, es muss schon das gesamte Tupel sein. Ein passenderer Datentyp als zwei Arrays wäre dafür eine List<KeyValuePair<stringstring>>. Eine solche sollte deine RegistryHandler.GetValues-Methode zurückgeben - und, schwupps, brauchst du in RegistryHandler überhaupt kein hässliches öffentliches Feld mehr :D .
Diese Liste weist du dann ListBox.DataSource zu. Jetzt musst du nur noch der ListBox über DisplayMember="Key" und ValueMember="Value" sagen, welchen Teil vom Tupel sie anzeigen bzw. bei SelectedValue zurückgeben soll.

user profile icondolly hat folgendes geschrieben Zum zitierten Posting springen:
Ich habe was von XAML gelesen - ist das die einzige Loesung?
WPF macht einiges eleganter, dafür lernt man es leider nicht an einem Wochenende ;) .

_________________
>λ=
dolly Threadstarter
Hält's aus hier
Beiträge: 4



BeitragVerfasst: Do 19.03.09 15:56 
Dankeschoen! Probier ich gleich mal aus..

Ich dachte Listbox koennte nur String values annehmen, da lag ich dann wohl grundlegend falsch!
dolly Threadstarter
Hält's aus hier
Beiträge: 4



BeitragVerfasst: Fr 20.03.09 14:04 
Ok das funktioniert in der Tat, danke!

Wie bringe ich der Liste jetzt bei, das anders zu formatieren. Denn so zeigt die Liste natuerlich die Key Value Pairs, also e.g.

[Adobe Flash Player 10 Active X, C:\Windows\system32\Macromed\Flash\uninstall_activeX.exe]

Mir waere lieber, wenn nur "Adobe Flash Player 10 Active X" angezeigt wuerde ;) Gibt es da eine Moeglichkeit?

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
   public void populateList()
        {
            listBox1.DataSource=null;
            if (this.hostname_entry_textbox.Text == "")
            {
                this.listBox1.Items.Add("no hostname entered");
            }
            else
            {
                RegistryHandler rh = new RegistryHandler(this.hostname_entry_textbox.Text);
                if (rh.checkHostname())
                {
                    this.hostname_entry_textbox.Clear();
                    this.listBox1.DataSource=rh.getResults();
                }
                else
                {
                    this.listBox1.Items.Add("unable to connect to host");
                }
            }

        }


ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
      public List<KeyValuePair<String, String>> getResults()
        {
            if (this.rk != null)
            {
                this.rk = rk.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\");
                String[] regValues = this.rk.GetSubKeyNames();
                List<KeyValuePair<stringstring>> list = new List<KeyValuePair<stringstring>>(); // = new String[2,validEntryCount];
                foreach (String s in regValues)
                {
                    RegistryKey temprk = this.rk.OpenSubKey(s);
                    if (temprk.GetValue("DisplayName") != null && temprk.GetValue("UninstallString") != null && (String)temprk.GetValue("DisplayName") != "" && (String)temprk.GetValue("UninstallString") != "")
                    {
                        list.Add(new KeyValuePair<stringstring>(temprk.GetValue("DisplayName").ToString(), temprk.GetValue("UninstallString").ToString()));
                    }
                }
                return list;
            }
            else return null;
        }
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4805
Erhaltene Danke: 1061

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Fr 20.03.09 14:34 
Das hatte Kha doch schon geschrieben:
Zitat:

Jetzt musst du nur noch der ListBox über DisplayMember="Key" und ValueMember="Value" sagen, welchen Teil vom Tupel sie anzeigen bzw. bei SelectedValue zurückgeben soll.
dolly Threadstarter
Hält's aus hier
Beiträge: 4



BeitragVerfasst: Fr 20.03.09 14:49 
whoops, sorry!!

und Problem geloest, vielen Dank!