Try the following which uses a class I found on StackOverflow (q.v.) to get the list of installed programs from the registry, though I've modified it to get the installation locations (where recorded) as well:
/* based on class written by Melnikovl in SO thread:
http://stackoverflow.com/questions/15524161/c-how-to-get-installing-programs-exactly-like-in-control-panel-programs-and-fe
*/
using System;
using System.Collections.Generic;
using Microsoft.Win32;
using System.Linq;
class Program
{
static void Main()
{
List<InstallationDetails> details = InstalledPrograms.GetInstalledPrograms();
var query = from id in details group id by id.DisplayName.Split(' ')[0] into g select g;
foreach(var g in query)
{
Console.WriteLine(g.Key.ToUpper());
Console.WriteLine();
foreach(InstallationDetails id in g) Console.WriteLine(id);
}
Console.ReadKey();
}
}
public class InstallationDetails
{
public string DisplayName {get; set;}
public string InstallLocation {get; set;}
public override string ToString()
{
return String.Format("{0}\n{1}\n", DisplayName, InstallLocation);
}
}
public static class InstalledPrograms
{
const string registry_key = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
public static List<InstallationDetails> GetInstalledPrograms()
{
var result = new List<InstallationDetails>();
result.AddRange(GetInstalledProgramsFromRegistry(RegistryView.Registry32));
result.AddRange(GetInstalledProgramsFromRegistry(RegistryView.Registry64));
return result;
}
private static IEnumerable<InstallationDetails> GetInstalledProgramsFromRegistry(RegistryView registryView)
{
var result = new List<InstallationDetails>();
using (RegistryKey key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, registryView).OpenSubKey(registry_key))
{
foreach (string subkey_name in key.GetSubKeyNames())
{
using (RegistryKey subkey = key.OpenSubKey(subkey_name))
{
if(IsProgramVisible(subkey))
{
InstallationDetails id = new InstallationDetails
{
DisplayName = (string)subkey.GetValue("DisplayName"),
InstallLocation = (string)subkey.GetValue("InstallLocation")
};
result.Add(id);
}
}
}
}
return result;
}
private static bool IsProgramVisible(RegistryKey subkey)
{
var name = (string)subkey.GetValue("DisplayName");
var releaseType = (string)subkey.GetValue("ReleaseType");
//var unistallString = (string)subkey.GetValue("UninstallString");
var systemComponent = subkey.GetValue("SystemComponent");
var parentName = (string)subkey.GetValue("ParentDisplayName");
return
!string.IsNullOrEmpty(name)
&& string.IsNullOrEmpty(releaseType)
&& string.IsNullOrEmpty(parentName)
&& (systemComponent == null);
}
}
On my machine this produces a heck of a long list and you might therefore want to write it to a file rather than to the console.