66

How to get the applications installed in the system using c# code?

10 답변


92

Iterating through the registry key "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" seems to give a comprehensive list of installed applications.

Aside from the example below, you can find a similar version to what I've done here.

This is a rough example, you'll probaby want to do something to strip out blank rows like in the 2nd link provided.

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

Alternatively, you can use WMI as has been mentioned:

ManagementObjectSearcher mos = new ManagementObjectSearcher("SELECT * FROM Win32_Product");
foreach(ManagementObject mo in mos.Get())
{
    Console.WriteLine(mo["Name"]);
}

But this is rather slower to execute, and I've heard it may only list programs installed under "ALLUSERS", though that may be incorrect. It also ignores the Windows components & updates, which may be handy for you.


  • It's worth noting that using the WMI Win32_Product class is a bad idea if you plan to run this query repeatedly. See this Microsoft KB article: support.microsoft.com/kb/974524/EN-US The core problem is the (a) Win32_Product is really slow and (b) it generates a "Windows Installer reconfigured the product." event log message for every installed product on your system... every time you run the query. Doh! This article recommends using the Win32reg_AddRemovePrograms class... which isn't present unless you have installed SMS. Doh! So probably better to stick with the registry query. - Simon Gillbee
  • Simon Gillbee's comment should be the accepted answer, or Kirtans! WMI WIN32_Product is not the way to go here, trust me! - bdd
  • Er, that's why the registry example is first in my answer. WMI was presented simply as an alternative solution, and even there I state "this is rather slower to execute" and other drawbacks. Read the answer from the beginning. ;) - Xiaofu
  • Kinda weird but if you uninstall a program and install it back then try to find it using using registry keys you can't unless you restart your machine - Yar
  • To answer my own question: stackoverflow.com/questions/27838798/… Although annoying that you might have to query both 64bit and 32bit. - Robert Koernke

10

You can take a look at this article. It makes use of registry to read the list of installed applications.

public void GetInstalledApps()
{
    string uninstallKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
    using (RegistryKey rk = Registry.LocalMachine.OpenSubKey(uninstallKey))
    {
        foreach (string skName in rk.GetSubKeyNames())
        {
            using (RegistryKey sk = rk.OpenSubKey(skName))
            {
                try
                {
                    lstInstalled.Items.Add(sk.GetValue("DisplayName"));
                }
                catch (Exception ex)
                { }
            }
        }
    }
}


  • I don't want whole list , I just need some selected install programs so what can i do for that . Thank you - Dhru 'soni

5

it's worth noting that the Win32_Product WMI class represents products as they are installed by Windows Installer[http://msdn.microsoft.com/en-us/library/aa394378%28v=vs.85%29.aspx].not every application use windows installer

however "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" represents applications for 32 bit. For 64 bit you also need to traverse "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" and since not every software has a 64 bit version the total applications installed are a union of keys on both locations that have "UninstallString" Value with them.

but the best options remains the same .traverse registry keys is a better approach since every application have an entry in registry[including the ones in Windows Installer].however the registry method is insecure as if anyone removes the corresponding key then you will not know the Application entry.On the contrary Altering the HKEY_Classes_ROOT\Installers is more tricky as it is linked with licensing issues such as Microsoft office or other products. for more robust solution you can always combine registry alternative with the WMI.



5

I agree that enumerating through the registry key is the best way.

Note, however, that the key given, @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", will list all applications in a 32-bit Windows installation, and 64-bit applications in a Windows 64-bit installation.

In order to also see 32-bit applications installed on a Windows 64-bit installation, you would also need to enumeration the key @"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall".


  • Are you sure about this? On my Windows 10 Enterprise 64bit the two lists look alike and the x86 applications show up in both. - Florian Straub

1

Iterate through "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" keys and check their "DisplayName" values.


1

Might I suggest you take a look at WMI (Windows Management Instrumentation). If you add the System.Management reference to your C# project, you'll gain access to the class `ManagementObjectSearcher', which you will probably find useful.

There are various WMI Classes for Installed Applications, but if it was installed with Windows Installer, then the Win32_Product class is probably best suited to you.

ManagementObjectSearcher s = new ManagementObjectSearcher("SELECT * FROM Win32_Product");



1

Use Windows Installer API!

It allows to make reliable enumeration of all programs. Registry is not reliable, but WMI is heavyweight.


  • sure is heavy weight - if run repeatedly, one will see performance drops like a heavy weight. if a feature of my app depends on another app, and know if installed properly, I only need the uninstall registry key for 32 or 64 only if the app is avail in 64 bit also) on the other hand if I must use wmi, I will limit to use only once during a application via a smart property trick. - gg89

1

I used Nicks approach - I needed to check whether the Remote Tools for Visual Studio are installed or not, it seems a bit slow, but in a seperate thread this is fine for me. - here my extended code:

    private bool isRdInstalled() {
        ManagementObjectSearcher p = new ManagementObjectSearcher("SELECT * FROM Win32_Product");
        foreach (ManagementObject program in p.Get()) {
            if (program != null && program.GetPropertyValue("Name") != null && program.GetPropertyValue("Name").ToString().Contains("Microsoft Visual Studio 2012 Remote Debugger")) {
                return true;
            }
            if (program != null && program.GetPropertyValue("Name") != null) {
                Trace.WriteLine(program.GetPropertyValue("Name"));
            }
        }
        return false;
    }


0

Your best bet is to use WMI. Specifically the Win32_Product class.



-1

My requirement is to check if specific software is installed in my system. This solution works as expected. It might help you. I used a windows application in c# with visual studio 2015.

 private void Form1_Load(object sender, EventArgs e)
        {

            object line;
            string softwareinstallpath = string.Empty;
            string registry_key = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
            using (var baseKey = Microsoft.Win32.RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64))
            {
                using (var key = baseKey.OpenSubKey(registry_key))
                {
                    foreach (string subkey_name in key.GetSubKeyNames())
                    {
                        using (var subKey = key.OpenSubKey(subkey_name))
                        {
                            line = subKey.GetValue("DisplayName");
                            if (line != null && (line.ToString().ToUpper().Contains("SPARK")))
                            {

                                softwareinstallpath = subKey.GetValue("InstallLocation").ToString();
                                listBox1.Items.Add(subKey.GetValue("InstallLocation"));
                                break;
                            }
                        }
                    }
                }
            }

            if(softwareinstallpath.Equals(string.Empty))
            {
                MessageBox.Show("The Mirth connect software not installed in this system.")
            }



            string targetPath = softwareinstallpath + @"\custom-lib\";
            string[] files = System.IO.Directory.GetFiles(@"D:\BaseFiles");

            // Copy the files and overwrite destination files if they already exist. 
            foreach (var item in files)
            {
                string srcfilepath = item;
                string fileName = System.IO.Path.GetFileName(item);
                System.IO.File.Copy(srcfilepath, targetPath + fileName, true);
            }
            return;

        }


  • foreach (string subkey_name in key.GetSubKeyNames()) <--No check here if null. - Burgo855

Linked


Related

Latest