Get Installed Applications in a System

Get installed applications in a system

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.

Get installed software list using C#

Source from : http://social.msdn.microsoft.com/Forums/en-US/94c2f14d-c45e-4b55-9ba0-eb091bac1035/c-get-installed-programs

The solution is to search for 3 places in registry:

  1. SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall inside CurrentUser
  2. SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall inside LocalMachine
  3. SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall in LocalMachine

the code below suits you needs.

public static bool IsApplicationInstalled(string p_name)
{
string displayName;
RegistryKey key;

// search in: CurrentUser
key = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall");
foreach (String keyName in key.GetSubKeyNames())
{
RegistryKey subkey = key.OpenSubKey(keyName);
displayName = subkey.GetValue("DisplayName") as string;
if (p_name.Equals(displayName, StringComparison.OrdinalIgnoreCase) == true)
{
return true;
}
}

// search in: LocalMachine_32
key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall");
foreach (String keyName in key.GetSubKeyNames())
{
RegistryKey subkey = key.OpenSubKey(keyName);
displayName = subkey.GetValue("DisplayName") as string;
if (p_name.Equals(displayName, StringComparison.OrdinalIgnoreCase) == true)
{
return true;
}
}

// search in: LocalMachine_64
key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall");
foreach (String keyName in key.GetSubKeyNames())
{
RegistryKey subkey = key.OpenSubKey(keyName);
displayName = subkey.GetValue("DisplayName") as string;
if (p_name.Equals(displayName, StringComparison.OrdinalIgnoreCase) == true)
{
return true;
}
}

// NOT FOUND
return false;
}

How to get the list of installed applications on Windows 10 from Java

You can't run PowerShell commands directly, you have to launch them through the PowerShell process:

powershell -command "PowerShell commands with parameters"

So change your exec call like this:

Process p = Runtime.getRuntime().exec("powershell -command \"Get-ItemProperty HKLM:\\Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\* | Select-Object DisplayName, DisplayVersion, Publisher, InstallDate | Format-Table –AutoSize\"");

C# On windows, how to get a list of installed programs' directories

You need to find all installed app from "HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall"
Here is the sample code

private string FindByDisplayName(RegistryKey parentKey, string name)
{
string[] nameList = parentKey.GetSubKeyNames();
for (int i = 0; i < nameList.Length; i++)
{
RegistryKey regKey = parentKey.OpenSubKey(nameList[i]);
try
{
if (regKey.GetValue("DisplayName").ToString() == name)
{
return regKey.GetValue("InstallLocation").ToString();
}
}
catch { }
}
return "";
}

RegistryKey regKey = Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Uninstall");
string location = FindByDisplayName(regKey, "MSN");
MessageBox.Show(location);

This example will compare the DisplayName keyvalue to your input name, if it find the value, then return the InstallLocation key value.

Sincerely,

Thiyagu Rajendran

**Please mark the replies as answers if they help and unmark if they don't.

Retrieve all currently installed software on Windows 7,8, and 10

If only it were that easy........

String command = "powershell.exe Get-ItemProperty HKLM:\\Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\* | DisplayName, DisplayVersion, InstallDate | ConvertTo-Json";
Process powerShellProcess = Runtime.getRuntime().exec(command);

I don't know where you found that snippet of code but unfortunately it doesn't quite work that way as you've already found out. The reason you are getting the error:

'DisplayName' is not recognized as an internal or external command, operable program or batch file.

is because the PowerShell command string you are trying to run needs to be applied to a PowerShell Command Prompt not the Windows Command Prompt the way you are doing it. To do that you need to start PowerShell first typing PowerShell then hitting the ENTER key. The window looks the same but you'll always know when you're working with a PowerShell Prompt when there is a whitespace between the prompt and the blinking caret and of course PowerShell is indicated within the Command Prompt Window Title Bar: Command Prompt - PowerShell. To exit the PowerShell Prompt simply type exit then hit the ENTER key. Notice the title bar now?

There is another way however and that is to use PowerShell's -Command command and enclose your command string in quotation marks but before we get into that you need to know that your command string is slightly flawed...you're missing a specific argument, the Select-Object argument and this would go just before the DisplayName property name:

          Here
┌─────┴─────┐
... | Select-Object DisplayName, DisplayVersion, InstallDate | ConvertTo-Json

You need this argument for your specific Command String to work, after all, you are selecting specific objects.

PowerShell help specifies that the -Command command:

executes the specified commands (and any parameters) as though they
were typed at the PowerShell Command Prompt, and then it exits, unless
NoExit is specified. The value of Command can be "-", a string, or a script block.

If the value of Command is "-", the command text is read from standard
input.

If the value of Command is a script block, the script block must be
enclosed in braces ({}). You can specify a script block only when
running PowerShell.exe in Windows PowerShell. The results of the
script block are returned to the parent shell as deserialized XML
objects, not live objects.

If the value of Command is a string, Command must be the last
parameter in the command , because any characters typed after the
command are interpreted as the command arguments.

To write a string that runs a Windows PowerShell command, use the
format: "& {}" where the quotation marks indicate a string
and the invoke operator (&) causes the command to be executed.

Well, this obviously puts a little light on the subject. So there are two ways you can accomplish this, enclose your command string in quotation marks or make the command string a invoked Command String Block:

In Quotation Marks:

String command = "PowerShell.exe -Command \"Get-ItemProperty HKLM:\\Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\* | Select-Object DisplayName, DisplayVersion, InstallDate | ConvertTo-Json\"";
Process powerShellProcess = Runtime.getRuntime().exec(command);

In A PowerShell Invoke Command String Block:

String command = "PowerShell.exe -Command \"& {Get-ItemProperty HKLM:\\Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\* | Select-Object DisplayName, DisplayVersion, InstallDate | ConvertTo-Json}\"";
Process powerShellProcess = Runtime.getRuntime().exec(command);

Hmmmmm...Now it is that easy.

Below is a method that can help take the hassle out of things. It automatically invokes PowerShell so all you need to supply is your command string without the "powershell.exe" in it.

/**
* Most PowerShell commands need to be run through a PowerShell Command
* Window (unless the -Command is used) which means that PowerShell needs
* to be run first before the command can be used otherwise you end up
* receiving an error something like:<pre>
*
* 'CommandName' is not recognized as an internal or external command,
* operable program or batch file.</pre><br>
* <p>
* This method solves that problem. Here you don't supply the "PowerShell"
* substring as the start of your Command String but instead you merely supply
* the Command String you would supply to PowerShell. As an example, suppose
* you want to collect the list of files and folders contained within the
* currently focused drive and directory within the local file system:
* <pre>
* {@code
* String command = "ls"; // A PowerShell command
* List<String> list = runPowerShellCommand(command);
*
* for (int i = 0; i < list.size(); i++) {
* System.out.println(list.get(i));
* }
* }</pre>
* <p>
* Your console window will display a list of files and folders.<br><br>
*
* @param commandString (String) The command string to run through
* PowerShell.<br>
*
* @param options (Optional - Two Of, Boolean):<pre>
* trimLines - (Boolean - Default is true) By default lines returned
* from the PowerShell process are added to a List Interface
* object with all lines trimmed. If you don't want this
* then supply false to this optional parameter. If you are
* retrieving data from PowerShell in a specific format like
* Json then you definitely want to pass boolean false to
* this parameter.
*
* If an argument is passed to the optional skipBlankLines
* parameter then you MUST pass an argument to this optional
* parameter as well.
*
* skipBlankLines - (Boolean - Default is true) By default blank lines returned
* from the PowerShell process are skipped and not added to the
* List Interface object that will be returned. If you don't want
* this then supply false to this optional parameter. If you are
* retrieving data from PowerShell in a specific format like
* Json then you definitely want to pass boolean false to
* this parameter.
*
* If an argument is passed to this optional parameter then
* you MUST pass an argument to the trimLines optional parameter
* as well.</pre>
*
* @return (List Interface of String ({@code List<String>})) PowerShell
* output data.<br>
*
* @throws java.io.IOException
*/
public List<String> runPowerShellCommand(String commandString, boolean... options) throws IOException {
List<String> list = new ArrayList<>();
boolean trimLines = true; // Default
boolean skipBlankLines = true; // Default
// Setup optional parameters if supplied.
if (options.length > 0) {
trimLines = options[0];
if (options.length >= 2) {
skipBlankLines = options[1];
}

}

// Fire up PowerShell and run the supplied command string through it.
Runtime runtime = Runtime.getRuntime();
String cmds[] = {"powershell", commandString};
Process proc = runtime.exec(cmds);
// Try With resources used here.
try (BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
if (trimLines) {
line = line.trim();
}
if (skipBlankLines) {
if (line.trim().equals("")) {
continue;
}
}
list.add(line); // Add line from input stream to list.
}
}
proc.destroy(); // Kill the process
return list; // return the goods if any
}

And here is how you might use it with your specific Command String:

String command = "Get-ItemProperty HKLM:\\Software\\Wow6432Node\\Microsoft\\"
+ "Windows\\CurrentVersion\\Uninstall\\* | Select-Object DisplayName, "
+ "DisplayVersion, InstallDate | ConvertTo-Json";

List<String> list;
try {
list = runPowerShellCommand(command, false, false);
// Display the list in console...
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
catch (IOException ex) {
System.err.println(ex.getMessage());
}

This will display your registry data query within the Console Window.

As a side note, there are actually three places within the Windows Registry that can hold specifically installed applications and you might consider poling all of them and ignore duplicates:

  • The list of programs that user sees in the section Programs and
    Features
    of the Control Panel is built on the base of the contents
    of the registry key:

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall

    The registry key above contains only programs installed “for all
    users”
    of Windows.

  • For 32-bit applications on a 64-bit operating system you would
    need to additionally get the contents of registry branch:

    HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall

  • If an application was installed in the “for this user” mode, then
    it should be present in the registry key:

    HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall

Accordingly, to get a complete list of installed software, you will need to pole information from all three branches of the Windows Registry.

Detecting installed programs via registry

User-specific settings should be written to HKCU\Software, machine-specific settings to HKLM\Software. Under these keys, structure [software vendor name]\[application name] (e.g. HKLM\Software\Microsoft\Internet Explorer) may be the most common, but that's just a convention, not a law of nature.

Many (most?) applications also add their uninstall entries to HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\[app name], but again, not all applications do this.

These are the most important keys; however, contents of the registry do not have to represent the installed software exactly - maybe the application was installed once, but then was manually deleted, or maybe the uninstaller didn't remove all traces of it. If you want to be sure, check the filesystem to see if the application still exists where its registry entries say it is.

Edit:

If you're a member of the group Administrators, you can check the HKEY_USERS hive - each user's HKCU actually resides there (you'll need to know the user SID, or go through all of them).

Note: As @Brian Ensink says, "installed" is a bit of a vague concept - are we trying to find what the user could run? Some software doesn't even write to the Registry at all: search for "portable apps" to see apps that have been specifically modified to run directly from media (CD/USB) and not to leave any traces on the computer. We may also have to scan the disks, and network disks, and anything the user downloads, and world-accessible Windows shares in the Internet (yes, such things exist legitimately - \\live.sysinternals.com\tools comes to mind). In this direction, there's no real limit of what the user can run, unless prevented by system policies.



Related Topics



Leave a reply



Submit