2016-05-26 14 views
1

Ich versuche, die Registrierung aufzuzählen, um eine Liste der installierten Anwendungen abzurufen und sie über Linq an eine DataTable in C# zurückzugeben.C# Linq Registrierungswerte zu DataTable

Ich habe verschiedene Dinge ausprobiert, einschließlich der Desinfektion als XML (was funktionierte), aber es schien ziemlich ineffizient, da ich dies letztendlich als DataTable-Objekt benötige.

Hier ist, wo ich zur Zeit bin:

  //Warning 
    public static DataRow DataRowInstalledApplication (this RegistryKey rgkey, string keyName) 
     { 
      RegistryKey key = rgkey.OpenSubKey(keyName, false); 
      try 
      { 
       //Application Name is mandetory for a given key. 
       if (key == null|| key.RegToString("DisplayName", false) == null)return null; 
       //Build a sanitised data row 
       var rowBuilder = new DataTable().NewRow(); 
       rowBuilder["DisplayName"] = key.RegToString("DisplayName"); 
       rowBuilder["UninstallString"] = key.RegToString("UninstallString"); 
       rowBuilder["InstallLocation"] = key.RegToString("InstallLocation"); 
       rowBuilder["Publisher"] = key.RegToString("Publisher"); 
       rowBuilder["DisplayIcon"] = key.RegToString("DisplayIcon"); 

       return rowBuilder; 
      } 
      finally 
      { 
       if (key != null) key.Close(); 
      } 

     } 

Hier ist die Methode, die die Linq enthält:

 public DataTable GetRegistryApplicationDataTable(RegistryKey registryKey, string tableName) 
    { 

     if (registryKey != null) 
     { 
      try 
      { 
       //change to throw non critical error 
       var installedListXml = new DataTable(tableName, from name in registryKey.GetSubKeyNames() 
                   let app = registryKey.DataRowInstalledApplication(name) 

                   select app); 
       return installedListXml; 
      } 
      catch 
      { 
       return new DataTable(tableName); 
      } 
      finally 
      { 
       registryKey.Close(); 
      } 

     } 
     return null; 
    } 

Das Hauptproblem ich habe, ist, dass ich wirklich nicht Linq sehr gut verstehen . Hauptsächlich werden, wie einzelne Werte während der Iteration verwendet, um andere Dinge zu

ähnlich zu nennen
foreach (string value in collection) 
{ 
    Somefunction(value); 
} 

im Fall der Registrierungswerte i abzurufen versuchen, ich verstehe nicht, wie eine Linq Abfrage jeden Schlüssel Namen übergibt machen zu funktionieren, die eine Zeile generieren und die Linq-Abfrage als Datentabelle zurückgegeben werden.

Ich wäre dankbar für alle Hinweise! Dank

ps Ich nenne die oben mit

private static readonly RegistryKey HKLMUninstallKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"); 

GetRegistryApplicationDataTable(HKLMUninstallKey, "Computer") 

und erwarten, dass eine Datentabelle zurück Computer genannt.

Antwort

1

Ihr erstes Problem ist Ihre Linq-Anweisung. Sie versuchen, einen IEnumerable in einem Konstruktor zu übergeben, der entweder ein (string) oder ein (string, string) erwartet. Wenn Sie Ihre Logik auf diese ändern:

var query = from name in registryKey.GetSubKeyNames() 
let app = registryKey.DataRowInstalledApplication(name) 
select app; 

foreach(var result in query) 
{ 
    var installedListXml = new DataTable(tableName, result); 
} 

, die funktionieren würde, wenn das Ergebnis tatsächlich eine Zeichenfolge war, aber es ist ein DataRow, die kein gültiger Parameter für einen DataTable Konstruktor ist. Stattdessen gibt es eine Erweiterung Methode, die Sie auf der resultierende Abfrage aufrufen kann auf eine Datentabelle zu kopieren, etwa so:

var query = from name in registryKey.GetSubKeyNames() 
let app = registryKey.DataRowInstalledApplication(name) 
select app; 

var installedListXml = query.CopyToDataTable(); 

Wenn Sie eine LINQ-Abfrage-Anweisung schreiben, wird er erst ausgeführt, wenn Sie versuchen, über die aufzuzählen Ergebnisse. CopyToDataTable tut dies, also wenn Sie Ihren Code durchgehen würden, werden Sie bemerken, dass Ihre Funktion DataRowInstalledApplication nicht aufgerufen wird, bis Sie CopyToDataTable aufrufen und nicht, wenn Sie zuerst query zuweisen. Das Ergebnis, das Sie erhalten, ist eine Enumerator, die Sie wie jede andere behandeln können, ob das in einer foreach Schleife oder Aufruf ToList oder so weiter verwendet wird. Innerhalb der linq-Abfrage selbst iterieren Sie tatsächlich über andere Werte, in diesem Fall GetSubKeyNames. Es wäre funktional gleichwertig, wenn Sie dies stattdessen tun würden:

var dataRows = new List<DataRow>(); 
foreach(var name in registryKey.GetSubKeyNames()) 
{ 
    dataRows.Add(registryKey.DataRowInstalledApplication(name)); 
} 

return dataRows.CopyToDataTable(); 
+0

Vielen Dank für das Beispiel und die Erklärung, sehr hilfreich! – DIG