Author Topic: Get App Installation Directories  (Read 5578 times)

Exergist

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 405
  • Ride the lightning
Get App Installation Directories
« on: January 17, 2018, 12:09:55 PM »
Continuing the work I posted here, below you will find a C# inline function that queries the Windows registry to find all application installation directory paths corresponding to a given application name. This works for finding 32-bit apps on 32-bit Windows as well as for finding 32 and 64-bit apps on 64-bit Windows as long as the app installation data can be found in the registry at one of these locations:
  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\
  • HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\
Please be aware that searching for app installation directories using this method may be unreliable due to the quality of the app data available in the above registry locations (if it's even there). The results are outputted directly to the VoiceAttack event log. You just need to provide a text string (AppName) that will be used to perform a case-insensitive comparison against the "DisplayName" for all registry entries found in the above keys. Note that if multiple directories are found for the same AppName they will all be outputted.

Referenced Assemblies = System.dll;
Code: [Select]
// Referenced Assemblies = System.dll

using System;
using Microsoft.Win32;

public class VAInline
{
    public void main()
    {
        string AppName = "VoiceAttack"; // Define app name you want to find (case-insensitive). You can use VA.GetText("Your VoiceAttack Variable Name") to import a VoiceAttack text variable into this code.
       
        string myPath = ""; // Initialize string variable for storing application directory
        string AllPaths = "."; // Initialize string variable for storing all found application directories (for repeat result filtering)
        int ResultCount = 1; // Initialize variable for storing number of matching applications
        RegistryKey RootKey = null; // Initialize RegistryKey for containing the root (base) key to evaluate
        string UninstallKey1 = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"; // Parent registry key for finding all 32-bit apps in 32-bit Windows and 64-bit apps in 64-bit Windows
        string UninstallKey2 = @"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"; // Parent registry key for finding 32-bit apps in 64-bit Windows
        string[] keyList; // Initialize string array for storing registry keys for process looping
        if (Environment.Is64BitOperatingSystem) // Check if operating system is 64-bit
        {
            RootKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64); // Opens registry's LocalMachine key with a 64-bit view
            keyList = new string[2]; // Resize keyList array
            keyList[0] = UninstallKey1; // Store registry key in string array
            keyList[1] = UninstallKey2; // Store registry key in string array
        }
        else // Operating system is 32-bit
        {
            RootKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32); // Opens registry's LocalMachine key with a 32-bit view
            keyList = new string[1]; // Resize keyList array
            keyList[0] = UninstallKey1; // Store registry key in string array
        }
        foreach (string parentKey in keyList) // Loop through each parentKey in keyList
        {
            using (RegistryKey childKey = RootKey.OpenSubKey(parentKey)) // Open subkey of parentKey and store in childKey. "using" implemented for proper disposal.
            {
                foreach (string subkeyName in childKey.GetSubKeyNames()) // Loop through each subkeyName in childKey
                {
                    using (RegistryKey subKey = childKey.OpenSubKey(subkeyName)) // Open subkey of childKey (based on subkeyName) and store in mySubKey. "using" implemented for proper disposal.
                    {
                        string DisplayName = ""; // Initialize string variable for storing app "DisplayName" from registry
                        try // Attempt the following code...
                        {
                            DisplayName = subKey.GetValue("DisplayName").ToString(); // Store "DisplayName" value of mySubKey
                        }
                        catch {} // Empty catch statement for handling exceptions in "try" statement (i.e., errors are ignored)
                        if (DisplayName.IndexOf(AppName, StringComparison.OrdinalIgnoreCase) >= 0)  // Check if AppName is found in DisplayName (case-insensitive)
                        {                       
                            string InstallDirectory; // Initialize string variable for storing application installation directory from registry
                            try // Attempt the following code...
                            {
                                InstallDirectory = subKey.GetValue("InstallLocation").ToString(); // Retrieve the "InstallLocation" of the current registry subKey (application)
                                if (InstallDirectory == "") // Check if InstallDirectory is blank
                                    InstallDirectory = null; // Set InstallDirectory as null
                                else if (InstallDirectory.EndsWith(@"\") == false) // Check if InstallDirectory does NOT end with "\"
                                    InstallDirectory += @"\"; // Append "\" to InstallDirectory
                            }
                            catch { InstallDirectory = null; } // subKey doesn't have an "InstallLocation" value, so set InstallDirectory as null
                            if (InstallDirectory == null) // Check if InstallDirectory is null
                            {
                                try // Attempt the following code...
                                {
                                    string InnoAppPath = subKey.GetValue("Inno Setup: App Path").ToString(); // Retrieve the "Inno Setup: App Path" of the current registry subKey (application)
                                    if (InnoAppPath == "") // Check if InnoAppPath is blank
                                        InstallDirectory = null; // Set InstallDirectory as null
                                    else if (InnoAppPath.EndsWith(@"\") == false) // Check if InnoAppPath does NOT end with "\"
                                        InstallDirectory = InnoAppPath + @"\"; // Append "\" to InnoPath and store this in InstallDirectory
                                    else
                                        InstallDirectory = InnoAppPath; // Set InstallDirectory equal to InnoAppPath
                                }
                                catch { InstallDirectory = null; } // subKey doesn't have an "Inno Setup: App Path" value, so keep InstallDirectory null
                                if (InstallDirectory == null) // Check if InstallDirectory is null
                                {
                                    try // Attempt the following code...
                                    {
                                        string DisplayIcon = subKey.GetValue("DisplayIcon").ToString(); // Retrieve the "DisplayIcon" of the current registry subKey (application)
                                        if (DisplayIcon.EndsWith(".exe") == true) // Check if DisplayIcon ends with ".exe"
                                            InstallDirectory = DisplayIcon.Remove(DisplayIcon.LastIndexOf(@"\") + 1); // Trim down DisplayIcon text and store the .exe folder path in InstallDirectory
                                    }
                                    catch { InstallDirectory = null; } // subKey doesn't have a "DisplayIcon" value, so keep InstallDirectory null
                                    if (InstallDirectory == null) // Check if InstallDirectory is null
                                    {
                                        try // Attempt the following code...
                                        {
                                            string InstallDir = subKey.GetValue("InstallDir").ToString(); // Retrieve the "InstallDir" of the current registry subKey (application)
                                            if (InstallDir == "") // Check if InstallDir is blank
                                                InstallDirectory = null; // Set InstallDirectory as null
                                            else if (InstallDir.EndsWith(@"\") == false) // Check if InstallDir does NOT end with "\"
                                                InstallDirectory = InstallDir + @"\"; // Append "\" to InstallDir and store in InstallDirectory
                                            else
                                                InstallDirectory = InstallDir; // Set InstallDirectory equal to InstallDir
                                        }
                                        catch { InstallDirectory = null; } // subKey doesn't have an "InstallDir" value, so keep InstallDirectory null
                                    }
                                }
                            }
                            if (InstallDirectory == null) // Check if InstallDirectory is null
                                continue; // Continue with foreach loop
                            else
                                myPath = InstallDirectory.Replace(@"""", "").Trim(); // Replace any double quotes, trim content in InstallDirectory, and store result in myPath
                            //myPath = mySubKey.GetValue("InstallLocation").ToString(); // Store "InstallationLocation" value of mySubKey in myPath
                            if (AllPaths.Contains(myPath) == false) // Check if any found directory paths do NOT contain myPath
                            {                                       
                                AllPaths += myPath; // Append myPath to AllPaths for future repeat result filtering
                                VA.WriteToLog(@"""" + AppName + @""" Directory " + ResultCount++ + " = " + myPath, "blue"); // Output result of app directory location search to VoiceAttack event log
                            }
                        }
                    }
                }
            }
        }
        if (AllPaths == ".") // Check if AppPaths is still the initial value (i.e., no matching application directories found)
            VA.WriteToLog(@"""" + AppName + @""" Directory = " + "not found", "blue"); // Output result of app directory location search to VoiceAttack event log
    }
}

// References:
// https://stackoverflow.com/questions/908850/get-installed-applications-in-a-system
// https://social.msdn.microsoft.com/Forums/windows/en-US/afb5012a-30f1-4b96-9931-a143fd76bab5/how-to-find-path-of-installed-programs-in-c?forum=winformssetup
// https://social.msdn.microsoft.com/Forums/en-US/94c2f14d-c45e-4b55-9ba0-eb091bac1035/c-get-installed-programs?forum=csharplanguage
// https://stackoverflow.com/questions/24909108/get-installed-software-list-using-c-sharp
// https://stackoverflow.com/questions/974038/reading-64bit-registry-from-a-32bit-application
// https://stackoverflow.com/questions/13030814/reading-value-from-registry
// https://stackoverflow.com/questions/444798/case-insensitive-containsstring

The above code searches for the AppName "VoiceAttack." A quick search through the registry on my PC shows the actual DisplayName for VoiceAttack is "VoiceAttack version 1.6.9." Since the AppName is found within the DisplayName the code should return the corresponding installation directory path.

Sometimes it isn't obvious what you should input as the AppName to find the installation directory for a particular application. To help with that this inline function will output DisplayNames for all installed applications to the VoiceAttack event log. So just copy the log's output into a text editor and search for keywords pertaining to your app of interest.

Edit: fixed some code issues and revised summary


Support This and Future Efforts
If you find this profile useful, please consider buying me a cup of coffee. Thank you for your support!
 


Cheers! :)
« Last Edit: June 02, 2020, 09:41:33 PM by Exergist »

LigerXT5

  • Guest
Re: Get App Installation Directories
« Reply #1 on: June 09, 2018, 12:13:38 PM »
Between Restream.io's chat and Discord, this should be a great help. Every time the app updates, it's launcher is in a new subfolder. I use a command to launch a series of programs, instead of letting them auto start on PC launch.

Exergist

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 405
  • Ride the lightning
Re: Get App Installation Directories
« Reply #2 on: June 09, 2018, 01:46:47 PM »
Hopefully this works for what you need! Finding app names as well as installation directories directly from the registry can be hit or miss.