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;
// 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 EffortsIf you find this profile useful, please consider buying me a cup of coffee. Thank you for your support!
Cheers!