getting a list of installed browsers on the computer - c#

I would like to know is there are any possibility to get a list of installed browsers on the computer using c#?
I'm using Selenium WebDriver in my task and I need to know which browsers are installed because in Selenium I can only run a specific browser, for example for Firefox it will be:
IWebDriver driver = new FirefoxDriver();
I will appreciate any help.

Look at localmachine registry...
Microsoft.Win32.RegistryKey key =
Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Clients\StartMenuInternet");
var browsers = key.GetSubKeyNames();

You also need to take into account the machine architecture (x64 vs x86) and the fact that Microsoft Edge will not be under the specified key. Here is what I ended up using (based on multiple solutions found online):
private List<Browser> GetBrowsers()
{
RegistryKey browserKeys;
browserKeys = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\WOW6432Node\Clients\StartMenuInternet");
if (browserKeys == null)
browserKeys = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Clients\StartMenuInternet");
string[] browserNames = browserKeys.GetSubKeyNames();
List<Browser> browsers = new List<Browser>();
for (int i = 0; i < browserNames.Length; i++)
{
Browser browser = new Browser();
RegistryKey browserKey = browserKeys.OpenSubKey(browserNames[i]);
browser.Name = (string)browserKey.GetValue(null);
RegistryKey browserKeyPath = browserKey.OpenSubKey(#"shell\open\command");
browser.Path = browserKeyPath.GetValue(null).ToString().StripQuotes();
browsers.Add(browser);
if (browser.Path != null)
browser.Version = FileVersionInfo.GetVersionInfo(browser.Path).FileVersion;
else
browser.Version = "unknown";
}
Browser edgeBrowser = GetEdgeVersion();
if (edgeBrowser != null)
{
browsers.Add(edgeBrowser);
}
return browsers;
}
private Browser GetEdgeVersion()
{
RegistryKey edgeKey =
Registry.CurrentUser.OpenSubKey(
#"SOFTWARE\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppModel\SystemAppData\Microsoft.MicrosoftEdge_8wekyb3d8bbwe\Schemas");
if (edgeKey != null)
{
string version = edgeKey.GetValue("PackageFullName").ToString().StripQuotes();
Match result = Regex.Match(version, "(((([0-9.])\\d)+){1})");
if (result.Success)
{
return new Browser
{
Name = "MicrosoftEdge",
Version = result.Value
};
}
}
return null;
}
And the object returned is a simple DTO:
public class Browser{
public string Name { get; set; }
public string Path { get; set; }
public string Version { get; set; }
}

I've written a NuGet package for this:
https://www.nuget.org/packages/MintPlayer.PlatformBrowser/ targetting .net core.
You can get a list of all installed webbrowsers (including Edge) and the default webbrowser. I've also written a package with a dialog to let you pick a browser: https://www.nuget.org/packages/MintPlayer.BrowserDialog/

As far as I know there is no list of browsers in Windows.
However you could check for browser's existence by simply testing the *.exe file's existence:
if (File.Exists(#"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe") ||
File.Exists(#"C:\Program Files\Google\Chrome\Application\chrome.exe")) {
// chrome is installed
}
if (File.Exists(#"C:\Program Files (x86)\Mozilla Firefox\firefox.exe") ||
File.Exists(#"C:\Program Files\Mozilla Firefox\firefox.exe") {
// firefox is installed
}

Related

How to check the application path installed with ClickOnce

Install three applications, A, B, and C, on one PC as ClickOnce.
And is there a way to know the installation path for B and C when you run application A?
My final goal is to get the installation paths of B and C from A and run these two programs from A.
Thanks.
You can start your ClickOnce application from windows start menu path, for that you need application's publisher name, suite name and product name. You can set those information from project property page -> publish section -> click on options button and set publisher name, suite name and product name.
Now you can use below code to start any ClickOnce application.
string StartMenuProgramDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Programs);
string Publisher = "<<Publisher Name>>";
string SuiteName = "<<Suite Name>>";
string ProductName = "<<Product Name>>.appref-ms";
Process.Start(Path.Combine(StartMenuProgramDirectory, Publisher, SuiteName, ProductName));
If you still want to know installation location of ClickOnce application, I am using below way (not sure this is ideal way or not)
You need to set your application display icon with below Code. (This will used to display icon in Control Panel -> Programs and Features)
private void Application_Startup(object sender, StartupEventArgs e)
{
if (ApplicationDeployment.IsNetworkDeployed && ApplicationDeployment.CurrentDeployment.IsFirstRun)
{
string IconPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Resources", "MyIcon.ico");
if (File.Exists(IconPath))
{
RegistryKey registryKey = Registry.CurrentUser.OpenSubKey(#"Software\Microsoft\Windows\CurrentVersion\Uninstall");
string[] subKeys = registryKey.GetSubKeyNames();
for (int i = 0; i < subKeys.Length; i++)
{
RegistryKey subRegistryKey = registryKey.OpenSubKey(subKeys[i], true);
object DisplayName = subRegistryKey.GetValue("DisplayName");
if (DisplayName != null && (DisplayName + "").ToUpper() == ("<<Product Name>>").ToUpper())
{
subRegistryKey.SetValue("DisplayIcon", IconPath);
break;
}
}
}
}
}
Now, Application's ClickOnce registry file is set with icon's path and your icon is available in installation directory, later you can fetch display icon's path with below code and based on that you can also able to find installation location.
string DisplayIconPath;
RegistryKey InstalledClickOncesRegistryKey = null;
RegistryKey InstalledProgramRegistryKey = null;
InstalledClickOncesRegistryKey = Registry.CurrentUser.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall");
if (InstalledClickOncesRegistryKey != null && InstalledClickOncesRegistryKey.SubKeyCount > 0)
{
string[] InstalledClickOncesList = InstalledClickOncesRegistryKey.GetSubKeyNames();
if (InstalledClickOncesList != null && InstalledClickOncesList.Length > 0)
{
foreach (var InstalledClickOnces in InstalledClickOncesList)
{
InstalledProgramRegistryKey = Registry.CurrentUser.CreateSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + InstalledClickOnces);
if (InstalledProgramRegistryKey != null && InstalledProgramRegistryKey.ValueCount > 0)
{
string RegistryApplicationName = Convert.ToString(InstalledProgramRegistryKey.GetValue("DisplayName"));
if (string.Equals(RegistryApplicationName, "<<Product Name>>"))
DisplayIconPath = Convert.ToString(InstalledProgramRegistryKey.GetValue("DisplayIcon"));
}
}
}
}

Ho to take server offline / bring server online IIS web farm server programmatically

I am developing a C# application to automate process of deploying website to the server.The website is hosted in a web farm in WINDOWS SERVER 2012 R2. So the problem here is I am trying to take server offline or bring it online by means of some programming interface. but I couldn't find anything related inside Microsoft docs. How do I get the job done?
UPDATE:
As suggested by Timur I did as following, but it didn't work.
ServiceController p = new ServiceController("W3SVC","SERVER_IP");
p.Start();
p.WaitForStatus(ServiceControllerStatus.Running);
This is the sample that generated by configuration manager. It take server offline/online by change the Enabled property of server item in web farm collection.
using System;
using System.Text;
using Microsoft.Web.Administration;
internal static class Sample
{
private static void Main()
{
using (ServerManager serverManager = new ServerManager())
{
Configuration config = serverManager.GetApplicationHostConfiguration();
ConfigurationSection webFarmsSection = config.GetSection("webFarms");
ConfigurationElementCollection webFarmsCollection = webFarmsSection.GetCollection();
ConfigurationElement webFarmElement = FindElement(webFarmsCollection, "webFarm", "name", #"123213");
if (webFarmElement == null) throw new InvalidOperationException("Element not found!");
ConfigurationElementCollection webFarmCollection = webFarmElement.GetCollection();
ConfigurationElement serverElement = FindElement(webFarmCollection, "server", "address", #"11.1.1.1");
if (serverElement == null) throw new InvalidOperationException("Element not found!");
serverElement["enabled"] = false;
serverManager.CommitChanges();
}
}
private static ConfigurationElement FindElement(ConfigurationElementCollection collection, string elementTagName, params string[] keyValues)
{
foreach (ConfigurationElement element in collection)
{
if (String.Equals(element.ElementTagName, elementTagName, StringComparison.OrdinalIgnoreCase))
{
bool matches = true;
for (int i = 0; i < keyValues.Length; i += 2)
{
object o = element.GetAttributeValue(keyValues[i]);
string value = null;
if (o != null)
{
value = o.ToString();
}
if (!String.Equals(value, keyValues[i + 1], StringComparison.OrdinalIgnoreCase))
{
matches = false;
break;
}
}
if (matches)
{
return element;
}
}
}
return null;
}
}
IIS is a Windows service. Therefore the easiest way to start/stop it will be to do something along the lines of this SO answer.
You'll be looking for service name, which likely depends on your version.
UPD see an artist's impression on how your management tool might look like
var hostNames = new List<string> { "appServer1", "webServer1", "webServer2" };
foreach (var host in hostNames)
{
var svc = new ServiceController("W3SVC", host);
svc.Stop();
svc.WaitForStatus(ServiceControllerStatus.Stopped);
Thread.Sleep(10000);// or your custom logic
svc.Start();
svc.WaitForStatus(ServiceControllerStatus.Running);
}
bear in mind, you'll need to run this as a user with sufficient privileges to successfully change service state: as in you need to run this as Admin.
You've got at least two options to do it:
Run your IDE as admin
Update your application manifest as described in this answer
UPD2 apparently you can interface with WFF controller like so

Programmatically open a page in IIS/IIS Express in the default browser on click of a button

I want to open a html page (in AppData/Roaming folder and not in the project/solution) with IIS/IIS Express in the default browser on click of a button. I have been able to find the default browser using the following:-
//This method is used to get the default browser
private static string GetDefaultBrowserPath()
{
string urlAssociation = #"Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http";
string browserPathKey = #"$BROWSER$\shell\open\command";
RegistryKey userChoiceKey = null;
string absBrowserPath = "";
const string exeSuffix = ".exe";
FileInfo browserPath;
try
{
//reading default browser path from userChoiceLKey
userChoiceKey = Registry.CurrentUser.OpenSubKey(urlAssociation + #"\UserChoice", false);
//If user choice was not found, try machine default
if (userChoiceKey == null)
{
//reading default browser path from Win XP registry key
var browserKey = Registry.ClassesRoot.OpenSubKey(#"HTTP\shell\open\command", false);
//if browser path not found, try Win Vista (and newer) registry key
if (browserKey == null)
{
browserKey =
Registry.CurrentUser.OpenSubKey(
urlAssociation, false);
}
var path = browserKey.GetValue(null);
browserKey.Close();
return path.ToString();
}
else
{
//if user defined browser choice was found
string progId = (userChoiceKey.GetValue("ProgId").ToString());
userChoiceKey.Close();
//looking up the path of the executable
string concreteBrowserKey = browserPathKey.Replace("$BROWSER$", progId);
var kp = Registry.ClassesRoot.OpenSubKey(concreteBrowserKey, false);
try
{
absBrowserPath = kp.GetValue(null).ToString().ToLower().Replace("\"", "");
if (!absBrowserPath.EndsWith(exeSuffix))
{
absBrowserPath = absBrowserPath.Substring(0, absBrowserPath.LastIndexOf(exeSuffix, StringComparison.Ordinal) + exeSuffix.Length);
browserPath = new FileInfo(absBrowserPath);
}
}
catch (Exception)
{
throw;
}
kp.Close();
return absBrowserPath;
}
}
catch(Exception ex)
{
return "";
}
}
After locating the default browser, I want to open a html page located in AppData/Roaming folder with IIS. How can this be achieved?
Edit: I am thinking of first publishing the pages with the IIS using ServerManager class of Microsoft.Web.Administration and then trying to open it.
is this a right approach? Once published, how would it be possible to open that page(a locally published site now) on click of some button?

Selenium cannot find element in chrome

SetUpTest:
public void SetupTest()
{
IWebDriver driver = new ChromeDriver();
selenium = new DefaultSelenium(
"localhost",
4444,
"*googlechrome C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",
"http://localhost");
selenium.Start();
verificationErrors = new StringBuilder();
}
Test function:
[Test]
public void LoginTest()
{
selenium.Open("http://localhost:8085/");
// login
for (int second = 0; ; second++)
{
if (second >= 60) Assert.Fail("timeout");
try
{
if (IsElementPresent(By.CssSelector("#username"))) break;
}
catch (Exception)
{ }
Thread.Sleep(1000);
}
driver.FindElement(By.Id("username")).SendKeys("admin");
driver.FindElement(By.Id("password")).SendKeys("123456");
driver.FindElement(By.CssSelector(".btn.btn-primary")).Click();
}
private bool IsElementPresent(By by)
{
try
{
driver.FindElement(by);
return true;
}
catch (NoSuchElementException)
{
return false;
}
}
I download Chrome Driver at this link: http://chromedriver.storage.googleapis.com/index.html
The newest version is 2.7.
My chrome version is 31.0.1650.63.
The problem is, driver cannot find element, although it exists in view.
How to make it work?
I'd recommend Selenium IDE and login manually while recording in Selenium IDE. It will help you identifying the correct names of the elements you want to select.
I use something like that
using Selenium;
ISelenium sel = new DefaultSelenium("localhost", 4444, "*firefox", "");
sel.Start();
sel.Open("www.whateveryourwebsideis.com");
sel.Type("id=user_email", "username");
sel.Type("id=user_password", "password");
sel.Click("name=commit");
Update:
seems to me as if you don't use your IDriver to navigate.
You have
selenium.Open("http://localhost:8085/");
but I guess you should use
driver.Navigate().GoToUrl("http://localhost:8085/");
Try
string htmlSource = driver.PageSource;
after loading the page to check if you actually have any HTML to search elements in.
I just tried installing ChromeDriver but it doesn't really work and I don't actually need it, so I'm afraid I have to leave it to you to find a solution...good luck.

Get installed applications in a system

How to get the applications installed in the system using c# code?
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.
I wanted to be able to extract a list of apps just as they appear in the start menu. Using the registry, I was getting entries that do not show up in the start menu.
I also wanted to find the exe path and to extract an icon to eventually make a nice looking launcher. Unfortunately, with the registry method this is kind of a hit and miss since my observations are that this information isn't reliably available.
My alternative is based around the shell:AppsFolder which you can access by running explorer.exe shell:appsFolder and which lists all apps, including store apps, currently installed and available through the start menu. The issue is that this is a virtual folder that can't be accessed with System.IO.Directory. Instead, you would have to use native shell32 commands. Fortunately, Microsoft published the Microsoft.WindowsAPICodePack-Shell on Nuget which is a wrapper for the aforementioned commands. Enough said, here's the code:
// GUID taken from https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid
var FOLDERID_AppsFolder = new Guid("{1e87508d-89c2-42f0-8a7e-645a0f50ca58}");
ShellObject appsFolder = (ShellObject)KnownFolderHelper.FromKnownFolderId(FOLDERID_AppsFolder);
foreach (var app in (IKnownFolder)appsFolder)
{
// The friendly app name
string name = app.Name;
// The ParsingName property is the AppUserModelID
string appUserModelID = app.ParsingName; // or app.Properties.System.AppUserModel.ID
// You can even get the Jumbo icon in one shot
ImageSource icon = app.Thumbnail.ExtraLargeBitmapSource;
}
And that's all there is to it. You can also start the apps using
System.Diagnostics.Process.Start("explorer.exe", #" shell:appsFolder\" + appModelUserID);
This works for regular Win32 apps and UWP store apps. How about them apples.
Since you are interested in listing all installed apps, it is reasonable to expect that you might want to monitor for new apps or uninstalled apps as well, which you can do using the ShellObjectWatcher:
ShellObjectWatcher sow = new ShellObjectWatcher(appsFolder, false);
sow.AllEvents += (s, e) => DoWhatever();
sow.Start();
Edit: One might also be interested in knowing that the AppUserMoedlID mentioned above is the unique ID Windows uses to group windows in the taskbar.
2022: Tested in Windows 11 and still works great. Windows 11 also seems to cache apps that aren't installed per se, portable apps that don't need installing, for example. They appear in the start menu search results and can also be retrieved from shell:appsFolder as well.
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".
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)
{ }
}
}
}
}
While the accepted solution works, it is not complete. By far.
If you want to get all the keys, you need to take into consideration 2 more things:
x86 & x64 applications do not have access to the same registry.
Basically x86 cannot normally access x64 registry. And some
applications only register to the x64 registry.
and
some applications actually install into the CurrentUser registry instead of the LocalMachine
With that in mind, I managed to get ALL installed applications using the following code, WITHOUT using WMI
Here is the code:
List<string> installs = new List<string>();
List<string> keys = new List<string>() {
#"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
#"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
};
// The RegistryView.Registry64 forces the application to open the registry as x64 even if the application is compiled as x86
FindInstalls(RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64), keys, installs);
FindInstalls(RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Registry64), keys, installs);
installs = installs.Where(s => !string.IsNullOrWhiteSpace(s)).Distinct().ToList();
installs.Sort(); // The list of ALL installed applications
private void FindInstalls(RegistryKey regKey, List<string> keys, List<string> installed)
{
foreach (string key in keys)
{
using (RegistryKey rk = regKey.OpenSubKey(key))
{
if (rk == null)
{
continue;
}
foreach (string skName in rk.GetSubKeyNames())
{
using (RegistryKey sk = rk.OpenSubKey(skName))
{
try
{
installed.Add(Convert.ToString(sk.GetValue("DisplayName")));
}
catch (Exception ex)
{ }
}
}
}
}
}
it's worth noting that the Win32_Product WMI class represents products as they are installed by Windows Installer. 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.
string[] registryKeys = new string[] {
#"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
#"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" };
public class InstalledApp
{
public string DisplayName { get; set; }
public string DisplayIcon { get; set; }
public string Version { get; set; }
public string InstallLocation { get; set; }
}
private void AddInstalledAppToResultView(RegistryHive hive, RegistryView view, string registryKey,Dictionary<string,InstalledApp> resultView)
{
using (var key = RegistryKey.OpenBaseKey(hive, view).OpenSubKey(registryKey))
{
foreach (string subKeyName in key.GetSubKeyNames())
{
using (RegistryKey subkey = key.OpenSubKey(subKeyName))
{
var displayName = subkey.GetValue("DisplayName");
var displayIcon = subkey.GetValue("DisplayIcon");
if (displayName == null || displayIcon == null)
continue;
var app = new InstalledApp
{
DisplayName = (string)displayName,
DisplayIcon = (string)displayIcon,
InstallLocation = (string)subkey.GetValue("InstallLocation"),
Version = (string)subkey.GetValue("DisplayVersion")
};
if(!resultView.ContainsKey(app.DisplayName))
{
resultView.Add(app.DisplayName,app);
}
}
}
}
}
void Main()
{
var result = new Dictionary<string,InstalledApp>();
var view = Environment.Is64BitOperatingSystem ? RegistryView.Registry64 : RegistryView.Registry32;
AddInstalledAppToResultView(RegistryHive.LocalMachine, view, registryKeys[0],result);
AddInstalledAppToResultView(RegistryHive.CurrentUser, view, registryKeys[0],result);
AddInstalledAppToResultView(RegistryHive.LocalMachine, RegistryView.Registry64, registryKeys[1],result);
Console.WriteLine("==============" + result.Count + "=================");
result.Values.ToList().ForEach(item => Console.WriteLine(item));
}
Iterate through "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" keys and check their "DisplayName" values.
Use Windows Installer API!
It allows to make reliable enumeration of all programs. Registry is not reliable, but WMI is heavyweight.
The object for the list:
public class InstalledProgram
{
public string DisplayName { get; set; }
public string Version { get; set; }
public string InstalledDate { get; set; }
public string Publisher { get; set; }
public string UnninstallCommand { get; set; }
public string ModifyPath { get; set; }
}
The call for creating the list:
List<InstalledProgram> installedprograms = new List<InstalledProgram>();
string registry_key = #"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(registry_key))
{
foreach (string subkey_name in key.GetSubKeyNames())
{
using (RegistryKey subkey = key.OpenSubKey(subkey_name))
{
if (subkey.GetValue("DisplayName") != null)
{
installedprograms.Add(new InstalledProgram
{
DisplayName = (string)subkey.GetValue("DisplayName"),
Version = (string)subkey.GetValue("DisplayVersion"),
InstalledDate = (string)subkey.GetValue("InstallDate"),
Publisher = (string)subkey.GetValue("Publisher"),
UnninstallCommand = (string)subkey.GetValue("UninstallString"),
ModifyPath = (string)subkey.GetValue("ModifyPath")
});
}
}
}
}
As others have pointed out, the accepted answer does not return both x86 and x64 installs. Below is my solution for that. It creates a StringBuilder, appends the registry values to it (with formatting), and writes its output to a text file:
const string FORMAT = "{0,-100} {1,-20} {2,-30} {3,-8}\n";
private void LogInstalledSoftware()
{
var line = string.Format(FORMAT, "DisplayName", "Version", "Publisher", "InstallDate");
line += string.Format(FORMAT, "-----------", "-------", "---------", "-----------");
var sb = new StringBuilder(line, 100000);
ReadRegistryUninstall(ref sb, RegistryView.Registry32);
sb.Append($"\n[64 bit section]\n\n{line}");
ReadRegistryUninstall(ref sb, RegistryView.Registry64);
File.WriteAllText(#"c:\temp\log.txt", sb.ToString());
}
private static void ReadRegistryUninstall(ref StringBuilder sb, RegistryView view)
{
const string REGISTRY_KEY = #"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
using var baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, view);
using var subKey = baseKey.OpenSubKey(REGISTRY_KEY);
foreach (string subkey_name in subKey.GetSubKeyNames())
{
using RegistryKey key = subKey.OpenSubKey(subkey_name);
if (!string.IsNullOrEmpty(key.GetValue("DisplayName") as string))
{
var line = string.Format(FORMAT,
key.GetValue("DisplayName"),
key.GetValue("DisplayVersion"),
key.GetValue("Publisher"),
key.GetValue("InstallDate"));
sb.Append(line);
}
key.Close();
}
subKey.Close();
baseKey.Close();
}
Your best bet is to use WMI. Specifically the Win32_Product class.
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");
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;
}
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;
}

Categories

Resources