I read a lot of information of getting programs. None of algorithms did do what I want. I need to get installed programs exactly like in control panel.
So I
I took the code that MelnikovI wrote (which was super helpful) and added a couple things. First, it search four places in the registry:
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall
HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
HKCU\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall
It also checks to see if there are any subkeys - if not it skips that one.
Lastly, it does a regex to only allow a certain set of characters [^a-zA-Z0-9 .()+-].
I'm only starting at C#, so I didn't know a way to loop through all four reg locations, so I have two loops (one for HKLM and one for HKCU).
public static class InstalledPrograms
{
public static List GetInstalledPrograms()
{
var result = new List();
result.AddRange(GetInstalledProgramsFromRegistry(RegistryView.Registry32));
result.AddRange(GetInstalledProgramsFromRegistry(RegistryView.Registry64));
result.Sort();
return result;
}
private static string cleanText(string dirtyText)
{
Regex rgx = new Regex("[^a-zA-Z0-9 .()+-]");
string result = rgx.Replace(dirtyText, "");
return result;
}
private static IEnumerable GetInstalledProgramsFromRegistry(RegistryView registryView)
{
var result = new List();
List uninstall = new List();
uninstall.Add(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall");
uninstall.Add(@"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall");
foreach (string registry_key in uninstall)
{
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))
{
result.Add(cleanText(subkey.GetValue("DisplayName").ToString()).ToString());
}
}
}
}
using (RegistryKey key = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, registryView).OpenSubKey(registry_key))
{
if (key != null)
{
foreach (string subkey_name in key.GetSubKeyNames())
{
using (RegistryKey subkey = key.OpenSubKey(subkey_name))
{
if (IsProgramVisible(subkey))
{
result.Add(cleanText(subkey.GetValue("DisplayName").ToString()).ToString());
}
}
}
}
}
}
return result;
}
If anyone is interested, I compared the results to the PowerShell I've been using and they are the same.
##Get list of Add/Remove programs
if (!([Diagnostics.Process]::GetCurrentProcess().Path -match '\\syswow64\\'))
{
$uninstallPath = "\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\"
$uninstallWow6432Path = "\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\"
@(
if (Test-Path "HKLM:$uninstallWow6432Path" ) { Get-ChildItem "HKLM:$uninstallWow6432Path"}
if (Test-Path "HKLM:$uninstallPath" ) { Get-ChildItem "HKLM:$uninstallPath" }
if (Test-Path "HKCU:$uninstallWow6432Path") { Get-ChildItem "HKCU:$uninstallWow6432Path"}
if (Test-Path "HKCU:$uninstallPath" ) { Get-ChildItem "HKCU:$uninstallPath" }
) |
ForEach-Object { Get-ItemProperty $_.PSPath } |
Where-Object {
$_.DisplayName -and !$_.SystemComponent -and !$_.ReleaseType -and !$_.ParentKeyName -and ($_.UninstallString -or $_.NoRemove)
} |
Sort-Object DisplayName |
Select-Object DisplayName
}
else
{
"You are running 32-bit Powershell on 64-bit system. Please run 64-bit Powershell instead." | Write-Host -ForegroundColor Red
}