Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#: How to get installing programs exactly like in control panel programs and features?

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 used:

  1. WMI Win32_Product class. It shows only msi installed programs.
  2. Registry keys. HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall. Again, some programs are not displayed in control panel, some programs displayed in control panel not in this registry node.

So, is there anyone in this world, who knew which algorithm use control panel to display installed programs?

UPD1:yes, i use 64 bit, i know there is another node for 64bit installed programs "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" but the following code enumerates twise HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall section, strange...

var programs = new List(); string registry_key = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"; using (Microsoft.Win32.RegistryKey key = Registry.LocalMachine.OpenSubKey(registry_key)) { foreach (string subkey_name in key.GetSubKeyNames()) { using (RegistryKey subkey = key.OpenSubKey(subkey_name)) { var name = (string)subkey.GetValue("DisplayName"); if(!string.IsNullOrEmpty(name)) { programs.Add(name); } } } } registry_key = @"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"; using (Microsoft.Win32.RegistryKey key = Registry.LocalMachine.OpenSubKey(registry_key)) { foreach (string subkey_name in key.GetSubKeyNames()) { using (RegistryKey subkey = key.OpenSubKey(subkey_name)) { var name = (string)subkey.GetValue("DisplayName"); if (!string.IsNullOrEmpty(name)) { programs.Add(name); } } } } foreach (var program in programs.OrderBy(x => x)) { Console.WriteLine(program); }
like image 351
MelnikovI Avatar asked Mar 20 '13 12:03

MelnikovI


Video Answer


2 Answers

Ok gyus, i wrote class that can get installed programs from registry without hotfixes and updates. It is still not exactly like in control panel but almost. I hope this helps anyone else.

public static class InstalledPrograms
{
    const string registry_key = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";

    public static List<string> GetInstalledPrograms()
    {
        var result = new List<string>();
        result.AddRange(GetInstalledProgramsFromRegistry(RegistryView.Registry32));
        result.AddRange(GetInstalledProgramsFromRegistry(RegistryView.Registry64));
        return result;
    } 

    private static IEnumerable<string> GetInstalledProgramsFromRegistry(RegistryView registryView)
    {
        var result = new List<string>();

        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((string)subkey.GetValue("DisplayName"));
                    }
                }
            }
        }

        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);
    }
}

like image 136
MelnikovI Avatar answered Oct 06 '22 01:10

MelnikovI


MelnikovI's answer is sufficient for most purposes -- I had 144 items in my list vs 143 in Programs and Features. For review, his solution is to hit these registry locations:

  • HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall
  • HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall
  • HKLM\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall

To qualify, each subkey MUST have:

  • The DisplayName REG_SZ value

And MUST NOT have:

  • The SystemComponent REG_DWORD (non-zero)
  • The ParentKeyName or ParentDisplayName REG_SZ values
  • The ReleaseType REG_SZ value

The one addtional enhancement I have found is for Windows Installer entries, defined as:

  • The key name is a standard GUID string
  • The WindowsInstaller REG_DWORD is present (and non-zero)

For such entries, you can take the additional step of using the Win32 function MsiGetProductInfoW from msi.dll, and asking for the "VersionString" property for the GUID represented by the key.

If this function returns 1605: ERROR_UNKNOWN_PRODUCT, it means that the entry is not installed according to Windows Installer, and should be excluded from display.

After implementing this minor tweak, my list is now identical to Programs and Features.

like image 26
Mike Avatar answered Oct 06 '22 00:10

Mike